From 70fb4e150a4fcc05c3487cdfdeea72db99f13b04 Mon Sep 17 00:00:00 2001 From: Peter Deutsch Date: Tue, 31 Jan 2023 15:19:02 -0500 Subject: [PATCH] Initial cache attack lab commit --- Part1-Timing/Makefile | 17 +++++ Part1-Timing/graph.py | 49 +++++++++++++ Part1-Timing/main.c | 72 +++++++++++++++++++ Part1-Timing/reference | Bin 0 -> 10216 bytes Part1-Timing/run.py | 44 ++++++++++++ Part1-Timing/utility.h | 148 ++++++++++++++++++++++++++++++++++++++ Part2-DeadDrop/Makefile | 26 +++++++ Part2-DeadDrop/receiver.c | 29 ++++++++ Part2-DeadDrop/sender.c | 45 ++++++++++++ Part2-DeadDrop/util.c | 102 ++++++++++++++++++++++++++ Part2-DeadDrop/util.h | 33 +++++++++ Part3-CTF/Makefile | 32 +++++++++ Part3-CTF/attacker.c | 12 ++++ Part3-CTF/util.c | 33 +++++++++ Part3-CTF/util.h | 25 +++++++ Part3-CTF/victim-2 | Bin 0 -> 6120 bytes Part3-CTF/victim-3 | Bin 0 -> 6120 bytes Part3-CTF/victim-4 | Bin 0 -> 6120 bytes README.md | 11 +++ cpu.mk | 6 ++ update.sh | 48 +++++++++++++ 21 files changed, 732 insertions(+) create mode 100644 Part1-Timing/Makefile create mode 100644 Part1-Timing/graph.py create mode 100644 Part1-Timing/main.c create mode 100755 Part1-Timing/reference create mode 100644 Part1-Timing/run.py create mode 100644 Part1-Timing/utility.h create mode 100644 Part2-DeadDrop/Makefile create mode 100755 Part2-DeadDrop/receiver.c create mode 100755 Part2-DeadDrop/sender.c create mode 100755 Part2-DeadDrop/util.c create mode 100755 Part2-DeadDrop/util.h create mode 100644 Part3-CTF/Makefile create mode 100644 Part3-CTF/attacker.c create mode 100755 Part3-CTF/util.c create mode 100755 Part3-CTF/util.h create mode 100755 Part3-CTF/victim-2 create mode 100755 Part3-CTF/victim-3 create mode 100755 Part3-CTF/victim-4 create mode 100644 README.md create mode 100644 cpu.mk create mode 100644 update.sh diff --git a/Part1-Timing/Makefile b/Part1-Timing/Makefile new file mode 100644 index 0000000..5bc5f7a --- /dev/null +++ b/Part1-Timing/Makefile @@ -0,0 +1,17 @@ +include ../cpu.mk + +all: main + +run: main + @taskset -c $(SENDER_CPU) ./main + +run-reference: reference + @taskset -c $(SENDER_CPU) ./reference + +main: main.c Makefile + @gcc main.c -o main + +.PHONY: clean + +clean: + rm -f main diff --git a/Part1-Timing/graph.py b/Part1-Timing/graph.py new file mode 100644 index 0000000..9eb1b01 --- /dev/null +++ b/Part1-Timing/graph.py @@ -0,0 +1,49 @@ +import os +import json +import matplotlib.pyplot as plt +import numpy as np +from tqdm import tqdm +from datetime import datetime + +num_runs = 100 +dict_of_dict_of_lists = dict() + +graph_repo="data" +os.makedirs(graph_repo, exist_ok=True) + +fancy_num_runs = range(0, num_runs, 1) +for run_id in tqdm(fancy_num_runs): + filename = graph_repo+"/run"+str(run_id)+".json" + with open(filename) as f: + dict_of_dict_of_lists[run_id] = json.load(f) + +l1_all = [] +l2_all = [] +l3_all = [] +mem_all = [] + +for run_id in tqdm(fancy_num_runs): + l1_all += dict_of_dict_of_lists[run_id]['1'] + l2_all += dict_of_dict_of_lists[run_id]['2'] + l3_all += dict_of_dict_of_lists[run_id]['3'] + mem_all += dict_of_dict_of_lists[run_id]['4'] + +# +# MAX 300 +# +fig_all = plt.figure(figsize=(11.25, 7.5)) +ax_all = fig_all.add_subplot(1,1,1) +ax_all.set_xlabel("Access Time") +ax_all.set_ylabel("Number of Samples") + +ax_all.hist(l1_all, label="L1", bins=np.arange(0, 300 ), alpha=0.5) +ax_all.hist(l2_all, label="L2", bins=np.arange(0, 300 ), alpha=0.5) +ax_all.hist(l3_all, label="L3", bins=np.arange(0, 300 ), alpha=0.5) +ax_all.hist(mem_all, label="DRAM", bins=np.arange(0, 300 ), alpha=0.5) +fig_all.legend() + +os.makedirs("graphs", exist_ok=True) +now = datetime.now() +date_time = now.strftime("%m:%d:%Y_%H:%M:%S") +fig_all.savefig(str("graphs/"+date_time+".pdf")) +plt.close(fig_all) diff --git a/Part1-Timing/main.c b/Part1-Timing/main.c new file mode 100644 index 0000000..1b6fa97 --- /dev/null +++ b/Part1-Timing/main.c @@ -0,0 +1,72 @@ +#include "utility.h" + +// TODO: Uncomment the following lines and fill in the correct size +//#define L1_SIZE [TODO] +//#define L2_SIZE [TODO] +//#define L3_SIZE [TODO] + +int main (int ac, char **av) { + + // create 4 arrays to store the latency numbers + // the arrays are initialized to 0 + uint64_t dram_latency[SAMPLES] = {0}; + uint64_t l1_latency[SAMPLES] = {0}; + uint64_t l2_latency[SAMPLES] = {0}; + uint64_t l3_latency[SAMPLES] = {0}; + + // A temporary variable we can use to load addresses + // The volatile keyword tells the compiler to not put this variable into a + // register- it should always try to load from memory/ cache. + volatile char tmp; + + // Allocate a buffer of 64 Bytes + // the size of an unsigned integer (uint64_t) is 8 Bytes + // Therefore, we request 8 * 8 Bytes + uint64_t *target_buffer = (uint64_t *)malloc(8*sizeof(uint64_t)); + + if (NULL == target_buffer) { + perror("Unable to malloc"); + return EXIT_FAILURE; + } + + // [1.2] TODO: Uncomment the following line to allocate a buffer of a size + // of your chosing. This will help you measure the latencies at L2 and L3. + //uint64_t *eviction_buffer = (uint64_t)malloc(TODO); + + // Example: Measure L1 access latency, store results in l1_latency array + for (int i=0; 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 +#include +#include +#include +#include +#include +#include + +#ifndef __UTILITY_H__ +#define __UTILITY_H__ + +#define SAMPLES 10 + + +// Function to read the time stamp counter, which is called tsc for short +// "rdtscpp" returns a 32bit unsigned integer +// "rdtscpp64" return a 64 bit unsigned integer +// Details in https://www.felixcloutier.com/x86/rdtscpp +static inline uint32_t rdtscpp() { + uint32_t rv; + asm volatile ("rdtscpp": "=a" (rv) :: "edx", "ecx"); + return rv; +} + +static inline uint64_t rdtscpp64() { + uint32_t low, high; + asm volatile ("rdtscpp": "=a" (low), "=d" (high) :: "ecx"); + return (((uint64_t)high) << 32) | low; +} + +// Function "lfence" wrap the assembly instruction lfence +// This function performs a serializing operation which ensures that +// the instructions after "lfence" start execution after +// all the instructions before "lfence" complete +// Details in https://www.felixcloutier.com/x86/lfence +static inline void lfence() { + asm volatile("lfence"); +} + +// Here is an example of using "rdtscp" and "mfence" to +// measure the time it takes to access a block specified by its virtual address +// The corresponding pseudo code is +// ========= +// t1 = rdtscp +// load addr +// t2 = rdtscp +// cycles = t2 - t1 +// return cycles +// ========= +static inline uint64_t measure_one_block_access_time(uint64_t addr) +{ + uint64_t cycles; + + asm volatile("mov %1, %%r8\n\t" + "mfence\n\t" + "lfence\n\t" + "rdtscp\n\t" + "mov %%eax, %%edi\n\t" + "mov (%%r8), %%r8\n\t" + "rdtscp\n\t" + "sub %%edi, %%eax\n\t" + : "=a"(cycles) /*output*/ + : "r"(addr) /*input*/ + : "r8", "edi"); /*reserved register*/ + + return cycles; +} + +static inline uint64_t one_block_access(uint64_t addr) +{ + asm volatile("mov (%0), %%r8\n\t" + : /*output*/ + : "r"(addr) /*input*/ + : "r8"); /*reserved register*/ + +} + + +// A wrapper function of the clflush instruction +// The instruction evict the given address from the cache to DRAM +// so that the next time the line is accessed, it will be fetched from DRAM +// Details in https://www.felixcloutier.com/x86/clflush +static inline void clflush(void *v) { + asm volatile ("clflush 0(%0)": : "r" (v):); +} + + + + +// Supporting functions for printing results in different formats +// Function "compare" is used in the priting functions and you do not need it +int compare(const void *p1, const void *p2) { + uint64_t u1 = *(uint64_t *)p1; + uint64_t u2 = *(uint64_t *)p2; + + return (int)u1 - (int)u2; +} + + +// Print out the latencies you measured +void print_results(uint64_t* dram, uint64_t* l1, uint64_t* l2, uint64_t* l3) { + qsort(dram, SAMPLES, sizeof(uint64_t), compare); + qsort(l1, SAMPLES, sizeof(uint64_t), compare); + qsort(l2, SAMPLES, sizeof(uint64_t), compare); + qsort(l3, SAMPLES, sizeof(uint64_t), compare); + printf(" : L1 L2 L3 Mem \n"); + printf("Minimum : %5ld %5ld %5ld %5ld\n", l1[0], l2[0], l3[0], dram[0]); + + printf("Bottom decile: %5ld %5ld %5ld %5ld\n", l1[SAMPLES/10], l2[SAMPLES/10], + l3[SAMPLES/10], dram[SAMPLES/10]); + + printf("Median : %5ld %5ld %5ld %5ld\n", l1[SAMPLES/2], l2[SAMPLES/2], + l3[SAMPLES/2], dram[SAMPLES/2]); + + printf("Top decile : %5ld %5ld %5ld %5ld\n", l1[(SAMPLES * 9)/10], l2[(SAMPLES * 9)/10], + l3[(SAMPLES * 9)/10], dram[(SAMPLES * 9)/10]); + + printf("Maximum : %5ld %5ld %5ld %5ld\n", l1[SAMPLES-1], l2[SAMPLES-1], + l3[SAMPLES-1], dram[SAMPLES-1]); +} + +// Format the latencies for part 1.5 +void print_results_for_python(uint64_t* dram, uint64_t* l1, uint64_t* l2, uint64_t* l3) +{ + qsort(dram, SAMPLES, sizeof(uint64_t), compare); + qsort(l1, SAMPLES, sizeof(uint64_t), compare); + qsort(l2, SAMPLES, sizeof(uint64_t), compare); + qsort(l3, SAMPLES, sizeof(uint64_t), compare); + + for (int i = 0; i < SAMPLES; i++) { + printf("%ld ", l1[i]); + } + printf("\n"); + for (int i = 0; i < SAMPLES; i++) { + printf("%ld ", l2[i]); + } + printf("\n"); + for (int i = 0; i < SAMPLES; i++) { + printf("%ld ", l3[i]); + } + printf("\n"); + for (int i = 0; i < SAMPLES; i++) { + printf("%ld ", dram[i]); + } + printf("\n"); +} + +#endif // _UTILITY_H__ diff --git a/Part2-DeadDrop/Makefile b/Part2-DeadDrop/Makefile new file mode 100644 index 0000000..ae7f4c2 --- /dev/null +++ b/Part2-DeadDrop/Makefile @@ -0,0 +1,26 @@ +include ../cpu.mk + +TARGETS=receiver sender +UTILS=util.o + +all: $(TARGETS) + +$(UTILS): %.o: %.c %.h + $(CC) $(CFLAGS) -c $< + +%.o: %.c util.h + $(CC) $(CFLAGS) -c $< + +$(TARGETS): %:%.o util.o + $(CC) $(CFLAGS) $^ -o $@ + +run_sender: sender + taskset -c $(SENDER_CPU) ./sender + +run_receiver: receiver + taskset -c $(RECEIVER_CPU) ./receiver + +.PHONY: clean + +clean: + $(RM) *.o $(HELPERS) $(TARGETS) diff --git a/Part2-DeadDrop/receiver.c b/Part2-DeadDrop/receiver.c new file mode 100755 index 0000000..4a658e1 --- /dev/null +++ b/Part2-DeadDrop/receiver.c @@ -0,0 +1,29 @@ + +#include"util.h" +// mman library to be used for hugepage allocations (e.g. mmap or posix_memalign only) +#include + +int main(int argc, char **argv) +{ + // Put your covert channel setup code here + + printf("Please press enter.\n"); + + char text_buf[2]; + fgets(text_buf, sizeof(text_buf), stdin); + + printf("Receiver now listening.\n"); + + bool listening = true; + while (listening) { + + // Put your covert channel code here + + } + + printf("Receiver finished.\n"); + + return 0; +} + + diff --git a/Part2-DeadDrop/sender.c b/Part2-DeadDrop/sender.c new file mode 100755 index 0000000..d196515 --- /dev/null +++ b/Part2-DeadDrop/sender.c @@ -0,0 +1,45 @@ + +#include"util.h" +// mman library to be used for hugepage allocations (e.g. mmap or posix_memalign only) +#include + +// TODO: define your own buffer size +#define BUFF_SIZE (1<<21) +//#define BUFF_SIZE [TODO] + +int main(int argc, char **argv) +{ + // Allocate a buffer using huge page + // See the handout for details about hugepage management + void *buf= mmap(NULL, BUFF_SIZE, PROT_READ | PROT_WRITE, MAP_POPULATE | MAP_ANONYMOUS | MAP_PRIVATE | MAP_HUGETLB, -1, 0); + + if (buf == (void*) - 1) { + perror("mmap() error\n"); + exit(EXIT_FAILURE); + } + // The first access to a page triggers overhead associated with + // page allocation, TLB insertion, etc. + // Thus, we use a dummy write here to trigger page allocation + // so later access will not suffer from such overhead. + //*((char *)buf) = 1; // dummy write to trigger page allocation + + + // TODO: + // Put your covert channel setup code here + + printf("Please type a message.\n"); + + bool sending = true; + while (sending) { + char text_buf[128]; + fgets(text_buf, sizeof(text_buf), stdin); + + // TODO: + // Put your covert channel code here + } + + printf("Sender finished.\n"); + return 0; +} + + diff --git a/Part2-DeadDrop/util.c b/Part2-DeadDrop/util.c new file mode 100755 index 0000000..56bbe0b --- /dev/null +++ b/Part2-DeadDrop/util.c @@ -0,0 +1,102 @@ + +#include "util.h" + +/* Measure the time it takes to access a block with virtual address addr. */ +CYCLES measure_one_block_access_time(ADDR_PTR addr) +{ + CYCLES cycles; + + asm volatile("mov %1, %%r8\n\t" + "lfence\n\t" + "rdtsc\n\t" + "mov %%eax, %%edi\n\t" + "mov (%%r8), %%r8\n\t" + "lfence\n\t" + "rdtsc\n\t" + "sub %%edi, %%eax\n\t" + : "=a"(cycles) /*output*/ + : "r"(addr) + : "r8", "edi"); + + return cycles; +} + +/* + * CLFlushes the given address. + * + * Note: clflush is provided to help you debug and should not be used in your + * final submission + */ +void clflush(ADDR_PTR addr) +{ + asm volatile ("clflush (%0)"::"r"(addr)); +} + +/* + * Converts a string to its binary representation. + */ +char *string_to_binary(char *s) +{ + if (s == NULL) + return 0; /* no input string */ + + size_t len = strlen(s); + + // Each char is one byte (8 bits) and + 1 at the end for null terminator + char *binary = malloc(len * 8 + 1); + binary[len] = '\0'; + + for (size_t i = 0; i < len; ++i) + { + char ch = s[i]; + for (int j = 7; j >= 0; --j) + { + if (ch & (1 << j)) + { + strcat(binary, "1"); + } + else + { + strcat(binary, "0"); + } + } + } + + return binary; +} + +/* + * Converts a binary string to its ASCII representation. + */ +char *binary_to_string(char *data) +{ + // Each char is 8 bits + size_t msg_len = strlen(data) / 8; + + // Add one for null terminator at the end + char *msg = malloc(msg_len + 1); + msg[msg_len] = '\0'; + + for (int i = 0; i < msg_len; i++) + { + char tmp[8]; + int k = 0; + + for (int j = i * 8; j < ((i + 1) * 8); j++) + { + tmp[k++] = data[j]; + } + + msg[i] = strtol(tmp, 0, 2); + } + + return msg; +} + +/* + * Converts a string to integer + */ +int string_to_int(char* s) +{ + return atoi(s); +} diff --git a/Part2-DeadDrop/util.h b/Part2-DeadDrop/util.h new file mode 100755 index 0000000..79ea9b6 --- /dev/null +++ b/Part2-DeadDrop/util.h @@ -0,0 +1,33 @@ + +// You may only use fgets() to pull input from stdin +// You may use any print function to stdout to print +// out chat messages +#include + +// You may use memory allocators and helper functions +// (e.g., rand()). You may not use system(). +#include + +#include +#include +#include +#include + +#ifndef UTIL_H_ +#define UTIL_H_ + +#define ADDR_PTR uint64_t +#define CYCLES uint32_t + +CYCLES measure_one_block_access_time(ADDR_PTR addr); + +// You Should Not Use clflush in your final submission +// It is only used for debug +void clflush(ADDR_PTR addr); + +char *string_to_binary(char *s); +char *binary_to_string(char *data); + +int string_to_int(char* s); + +#endif diff --git a/Part3-CTF/Makefile b/Part3-CTF/Makefile new file mode 100644 index 0000000..39e47ad --- /dev/null +++ b/Part3-CTF/Makefile @@ -0,0 +1,32 @@ +include ../cpu.mk + +TARGETS=attacker +UTILS=util.o + +all: $(TARGETS) + +$(UTILS): %.o: %.c %.h + $(CC) $(CFLAGS) -c $< + +%.o: %.c util.h + $(CC) $(CFLAGS) -c $< + +$(TARGETS): %:%.o util.o + $(CC) $(CFLAGS) $^ -o $@ + +run_victim-2: + taskset -c $(SENDER_CPU) ./victim-2 + +run_victim-3: + taskset -c $(SENDER_CPU) ./victim-3 + +run_victim-4: + taskset -c $(SENDER_CPU) ./victim-4 + +run_attacker: attacker + taskset -c $(RECEIVER_CPU) ./attacker + +.PHONY: clean + +clean: + $(RM) *.o $(HELPERS) $(TARGETS) diff --git a/Part3-CTF/attacker.c b/Part3-CTF/attacker.c new file mode 100644 index 0000000..7679cea --- /dev/null +++ b/Part3-CTF/attacker.c @@ -0,0 +1,12 @@ +#include "util.h" +// mman library to be used for hugepage allocations (e.g. mmap or posix_memalign only) +#include + +int main(int argc, char const *argv[]) { + int flag = -1; + + // Put your capture-the-flag code here + + printf("Flag: %d\n", flag); + return 0; +} diff --git a/Part3-CTF/util.c b/Part3-CTF/util.c new file mode 100755 index 0000000..9bf191b --- /dev/null +++ b/Part3-CTF/util.c @@ -0,0 +1,33 @@ + +#include "util.h" + +/* Measure the time it takes to access a block with virtual address addr. */ +CYCLES measure_one_block_access_time(ADDR_PTR addr) +{ + CYCLES cycles; + + asm volatile("mov %1, %%r8\n\t" + "lfence\n\t" + "rdtsc\n\t" + "mov %%eax, %%edi\n\t" + "mov (%%r8), %%r8\n\t" + "lfence\n\t" + "rdtsc\n\t" + "sub %%edi, %%eax\n\t" + : "=a"(cycles) /*output*/ + : "r"(addr) + : "r8", "edi"); + + return cycles; +} + +/* + * CLFlushes the given address. + * + * Note: clflush is provided to help you debug and should not be used in your + * final submission + */ +void clflush(ADDR_PTR addr) +{ + asm volatile ("clflush (%0)"::"r"(addr)); +} diff --git a/Part3-CTF/util.h b/Part3-CTF/util.h new file mode 100755 index 0000000..847284f --- /dev/null +++ b/Part3-CTF/util.h @@ -0,0 +1,25 @@ + +// You may only use fgets() to pull input from stdin +// You may use any print function to stdout to print +// out chat messages +#include + +// You may use memory allocators and helper functions +// (e.g., rand()). You may not use system(). +#include + +#include +#include +#include + +#ifndef UTIL_H_ +#define UTIL_H_ + +#define ADDR_PTR uint64_t +#define CYCLES uint32_t + +CYCLES measure_one_block_access_time(ADDR_PTR addr); + +void clflush(ADDR_PTR addr); + +#endif diff --git a/Part3-CTF/victim-2 b/Part3-CTF/victim-2 new file mode 100755 index 0000000000000000000000000000000000000000..61c6c93ec573dd916b71ed23b759ec02bea964f1 GIT binary patch literal 6120 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 D;4p!k literal 0 HcmV?d00001 diff --git a/README.md b/README.md new file mode 100644 index 0000000..1a2481e --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +# Hands-On Hardware Side Channels Lab + +This repository contains all the starting code you will need for the lab. + +A randomly-generated password will be emailed to you when the lab is released. Please log in and change your password immediately to something secure using the `passwd` command. Please note that your account will be deleted at the end of this course. + +## Starting the Lab + +As stated on the lab handout, you must first change the `SENDER_CPU` and `RECEIVER_CPU` variables in the Makefile to your assigned CPUs. These will be emailed to you along with your lab machine password when the lab is released. **Double check that you have set these values correctly.** + +After completing these steps, you are now ready to start the lab. Good luck! diff --git a/cpu.mk b/cpu.mk new file mode 100644 index 0000000..fd08cf6 --- /dev/null +++ b/cpu.mk @@ -0,0 +1,6 @@ +CC=gcc +CFLAGS=-O0 -I /usr/local +$(error Please set SENDER_CPU and RECEIVER_CPU to your assigned values) +SENDER_CPU= +RECEIVER_CPU= + diff --git a/update.sh b/update.sh new file mode 100644 index 0000000..c5fe63d --- /dev/null +++ b/update.sh @@ -0,0 +1,48 @@ +#!/bin/bash +# Updates repository to latest starter code +# +# Adapted from Oliver Beckstein's ASU-CompMethodsPhysics-PHY494 course 2016-2020 placed into the public domain + +# With GitHub template repositories one needs to use --allow-unrelated-histories +# at least once. https://help.github.com/en/github/creating-cloning-and-archiving-repositories/creating-a-repository-from-a-template + +progname="$0" +REMOTE_NAME="startercode" +REMOTE_URL="https://github.com/CSAIL-Arch-Sec/SHD-CacheAttackLab.git" + +# progname, from top dir +UPDATESH="./deploy/$(basename $progname)" + +CONTACT_MESSAGE="Contact the instructor and TA with a screen shot of ALL output from running $0." + +function die () { + local msg="$1" err=${2:-1} + echo "ERROR: ${msg}." + exit $err +} + +# ensure everything relative to top dir +topdir="$(git rev-parse --show-toplevel)" || die "Failed to get rootdir" +cd "${topdir}" || die "Failed to get to the git root dir ${rootdir}" + + +# first time +# 1. set remote repo +# 2. merge histories between student (template) and remote skeleton + +if ! git remote get-url ${REMOTE_NAME} >/dev/null 2>&1; then + echo "Adding remote repository '${REMOTE_NAME}'." + git remote add ${REMOTE_NAME} ${REMOTE_URL} + + echo "Merging histories for the first time..." + set -x + git pull --allow-unrelated-histories -s recursive -X theirs --no-edit ${REMOTE_NAME} main || \ + { git rev-list -1 MERGE_HEAD >/dev/null 2>&1 && git merge --abort ; \ + git remote rm ${REMOTE_NAME}; \ + die "Failed to merge histories. ${CONTACT_MESSAGE}" $?; } + + set +x +fi + +echo "updating repository... git pull from ${REMOTE_NAME}" +git pull --no-edit ${REMOTE_NAME} main || die "Failed to pull from ${REMOTE_NAME}. ${CONTACT_MESSAGE}"