0x0 Introduction
I got lost in my memory. Please save me!
Author: Jonathan
nc challs.ctf.sekai.team 4001
files: saveme.zip
0x1 Mitigation
1 | Arch: amd64-64-little |
0x2 My approach
First of all lets analysis the program.
the first thing that caught my eye is that the program uses seccomp
to add restriction to certain system calls. We can easily check the the seccomp rules by using a tool called seccomp-tools
.
1 | 23:55:55 $ seccomp-tools dump ./saveme |
The seccomp here check both ARCH_X86_64
and A < 0x40000000
, which means we are not able to use x32 ABI or use retf
to bypass this restriction.
As we can see here, seccomp only allow us to use read
, write
, and exit_group
. There is no way we can get a shell from this.
But luckily, the program already have the flag store in the memory and allocate a rwx
memory space. if we are able to get the address of flag and have an arbitray code execution, we can print out the flag using write
.
1 | 0040129f mmap(0x405000, 0x1000, 7, 0x22, 0, 0); |
now come to the main vulnerabilities.
- the program leak the stack address
- we have a printf that printf whatever user have input.
these two vulnerabilities give us an arbitrary write on the whole memory space. Since the program also leak the stack address, we can also overwrite rip to control the return pointer.
1 | 00401424 void var_68; |
looks like we got everything we want. just write shellcode to the executable memory space and return to that.
the idea is correct, but the program have a 80 input length limit, which means we are not able to write the whole shellcode in a single printf. To do that, we need some how make a loop. so that we can use the printf
vulnerability multiple time and write all the shellcode.
my first approach here is write rip to main function. but it didn't work here. not only because of the stack pointer part, but also the seccomp part. Since the program setup seccomp filter when program execuate main function at first time. Program are not able to use open
syscall again. The syscall to open
violate the seccomp filter and kill the program immediately.
So, how can we bypass this. the solution is straight forward - overwrite the return pointer of printf. Since we have the stack address, we can overwrite the return pointer of printf and let it return to the vulnerability again. In this way, we could write any number of data into the memory space.
finally, when we finish writing shellcode into the memory, we overwrite the return pointer to shellcode itself and get the flag.
there is one more thing that need to be considered: since scanf stop scan at \0xa
(\n). we need to choose an address that could avoid all \0xa
in the final printf payload.
0x3 Exploit
1 | from pwn import * |
0x4 Flag
SEKAI{Y0u_g0T_m3_n@w_93e127fc6e3ab73712408a5090fc9a12}