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.