Home IrisCTF 2024: Insanity Check
Post
Cancel

IrisCTF 2024: Insanity Check

Challenge Description

I’ve tried the brand new michael-ld linker on my hello world program. I’m pretty sure it’s super safe now.

Insanity Check

This challenge is supposed to be an homage to the common pwn-category sanity check challenges, where you can usually just write over the end of a buffer to achieve code execution.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[...]

const char suffix[] = "! Welcome to IrisCTF2024. If you have any questions you can contact us at test@example.com\0\0\0\0";

int main() {
    char message[128];
    char name[64];
    fgets(name, 64, stdin);
    rstrip(name, 64);

    strcpy(message, "Hi there, ");
    strcpy(message + strlen(message), name);
    memcpy(message + strlen(message), suffix, sizeof(suffix));

    printf("%s\n", message);
}

__attribute__((section(".flag")))
void win() {
    __asm__("pop %rdi");
    system("cat /flag");
}

It might be immediately obvious, that it is possible to overflow the message buffer. The slight trick is, that you cannot directly control the values you write into the return address. Instead, you can shift the suffix value further into the output buffer. As is slightly hinted at by the __attribute__((section(".flag"))), the win function is located at a weird address:

1
2
3
4
     6: 00000000400007f6    76 FUNC    GLOBAL DEFAULT   15 rstrip
    23: 000000006d6f632e    18 FUNC    GLOBAL DEFAULT   28 win
    27: 00000000400009c0    95 OBJECT  GLOBAL DEFAULT   17 suffix
    29: 0000000040000842   311 FUNC    GLOBAL DEFAULT   15 main

If we look at the address of win as a hex value, it evaluates to moc. (or .com in little endian). This perfectly matches the end of the suffix value we have above. By sending 57 characters, we can push the buffer just far enough that the .com overwrites the return address, which returns us directly into the win function. The __asm__("pop %rdi"); was added to realign the stack, which is required for system() to work correctly.

How it’s made

If you want to replicate the compilation steps done for this challenge, you can run gcc vuln.c -no-pie -fno-stack-protector -T ./insanity-check.x with the attached linker script. This script was taken from my current working machine and only slightly modified to place the flag at the correct address.

This post is licensed under CC BY 4.0 by the author.