SCTF is a CTF contest hold by XCTF ( seems like a Chinese version’s CTFtime.org ). Teaming up with my labmates, we have a lot of fun solving the challenges, and scored 2161 pts with the final rank 13/659. In Pwn200, they gave us a binary file and a libc.so. First we open the binary file with IDA Pro, and check the main function:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
.......................
.......................
int buf; // [sp+9Ch] [bp-1Ch]@1
.......................
size_t n; // [sp+ACh] [bp-Ch]@1
.......................
.......................
read(0, &buf, n + 1);
if ( strlen((const char *)&buf) - 1 > 9 || strncmp("syclover", (const char *)&buf, 8u) )
{
result = -1;
}
else
{
write(1, "input slogan:", 0xEu);
read(0, &v1, n);
result = write(1, &v1, n);
}
notice at line read(0, &buf, n + 1);
, we can overwrite the variable n
by overflowing the buf
variable. After we control n
, we can input at most 255 characters at the line read(0, &v1, n);
. By doing this, we can overwrite (control) the return address!
But there’s one problem: the program has enable the DEP protection. Since it gave us the libc.so, we think they might want us to use the return-to-libc attack. By checking the GOT entry using objdump, we know the GOT entry of read()
is at address 0x08049850
.
So how do we get the address of system()
? Well, since we can overwrite the return address, we can set the return address to write()
’s GOT entry. By giving the parameter 0x08049850
, we can leak the function pointer of read()
, and calculate system()
’s address by adding the offset ( we can get the offset by checking libc.so ).
After getting the address of system()
, we can set the return address back to the head of main function, so we can execute the whole program again and write the memory by using read()
. We can write “/bin/sh” to a memory address in .bss section, and set the return address to system()
, with pointer to “/bin/sh” as the parameter. Finally, we spawn a shell and capture the flag.
To sum up, here’s the step of the exploitation:
- Overwrite
n
, so we can useread()
to overwrite (control) the return address - Set the return address to
write()
, with the parameter0x08049850
(read()’s GOT entry) - Calculate the address of
system()
- Set the return address back to the head of main function
- Write “/bin/sh” to an address in .bss section by using read()
- Repeat step 3 (for the final exploit)
- Set the return address to
system()
, with pointer to “/bin/sh” as the parameter - Spawn the shell & capture the flag
flag: SCTF{SH3NG_4_KAN_DAN__BU_FU_9_GANN}
Comments powered by Disqus.