Download the lab files from here. The archive password is infected
.
apt-get install gdb git
$ cd
$ git clone https://github.com/longld/peda
$ echo "source ~/peda/peda.py" >> ~/.gdbinit
$
= "amd64"
context.arch = 0x400123
pop_rdi_ret
#Either like this
= p64(pop_rdi_ret) + p64(0x1234)
ropchain
#Or like this
= flat([
ropchain
pop_rdi_ret,0x1234,
]) io.send(ropchain)
gdb-peda$ find "%s" binary
Searching for '%s' in: binary ranges
Found 2 results, display max 2 items:
test : 0x402004 --> 0x3b031b0100007325
test : 0x403004 --> 0x3b031b0100007325
gdb-peda$ hexdump 0x402004
0x00402004 : 25 73 00 00 01 1b 03 3b 64 00 00 00 0b 00 00 00 %s.....;d.......
gdb-peda$ asmsearch "pop rdi; ret"
Searching for ASM code: 'pop rdi; ret' in: binary ranges
0x0040125b : (5fc3) pop rdi; ret
gdb-peda$ dumprop
Warning: this can be very slow, do not run for large memory range
Writing ROP gadgets to file: test-rop.txt ...
0x40115c: ret
0x40112a: repz ret
0x4011db: leave; ret
0x40125a: pop r15; ret
0x4010c0: pop rbp; ret
0x40125b: pop rdi; ret
rp-lin-x64 -f ./test -r 1 --unique #here for length 1 gadgets
$ Trying to open './test'..
Loading ELF information..
FileFormat: Elf, Arch: x64
Using the Nasm syntax..
Wait a few seconds, rp++ is looking for gadgets..
in LOAD
55 found.
A total of 55 gadgets found.
You decided to keep only the unique ones, 30 unique gadgets found.
0x0040107e: add byte [rax], al ; ret ; (1 found)
0x0040107d: add byte [rax], r8L ; ret ; (1 found)
0x00401128: add byte [rcx], al ; rep ret ; (1 found)
0x00401129: add ebx, esi ; ret ; (1 found)
0x00401013: add esp, 0x08 ; ret ; (2 found)
0x00401012: add rsp, 0x08 ; ret ; (2 found)
0x00401241: call qword [r12+rbx*8] ; (1 found)
0x00401196: call qword [rax+0x4855C35D] ; (1 found)
0x004011d9: call qword [rax+0x4855C3C9] ; (1 found)
0x00401155: call qword [rbp+0x48] ; (1 found)
0x00401242: call qword [rsp+rbx*8] ; (1 found)
0x00401010: call rax ; (2 found)
0x00401244: fmul qword [rax-0x7D] ; ret ; (1 found)
0x004010b5: jmp rax ; (2 found)
0x004011db: leave ; ret ; (1 found)
0x00401123: mov byte [0x0000000000404058], 0x00000001 ; rep ret ; (1 found)
0x0040114c: mov ebp, esp ; call rax ; (1 found)
0x004010b0: mov edi, 0x00404038 ; jmp rax ; (2 found)
0x0040123f: mov edi, ebp ; call qword [r12+rbx*8] ; (1 found)
0x0040123e: mov edi, r13d ; call qword [r12+rbx*8] ; (1 found)
0x0040114b: mov rbp, rsp ; call rax ; (1 found)
0x0040107b: nop dword [rax+rax+0x00] ; ret ; (1 found)
0x0040125d: nop dword [rax] ; ret ; (1 found)
0x00401240: out dx, eax ; call qword [r12+rbx*8] ; (1 found)
0x0040125a: pop r15 ; ret ; (1 found)
0x004010c0: pop rbp ; ret ; (7 found)
0x0040125b: pop rdi ; ret ; (1 found)
0x0040112a: rep ret ; (1 found)
0x00401016: ret ; (15 found)
0x0040123d: test byte [rcx+rcx*4-0x11], 0x00000041 ; call qword [rsp+rbx*8] ; (1 found)
gdb-peda$ p puts
$1 = {<text variable, no debug info>} 0x7ffff7e37b10 <puts>
gdb-peda$ xinfo 0x7ffff7e37b10
0x7ffff7e37b10 (<puts>: push r13)
Virtual memory mapping:
Start : 0x00007ffff7de8000
End : 0x00007ffff7f30000
Offset: 0x4fb10
Perm : r-xp
Name : /lib/x86_64-linux-gnu/libc-2.28.so
So the puts
function is at offset 0x4fb10. If, through an information leak, we find that puts
is at address:
$ cat main.c
int main(int argc, char **argv) {
//classic usage
printf("%d %d\n", 12, 34);
//indexed usage, equivalent to the above
printf("%1$d %2$d\n", 12, 34);
//switched indexes
printf("%2$d %1$d\n", 12, 34);
//reading out of bounds
printf("%1$d %2$d %3$d %4$d\n", 12, 34);
// reading out of bounds from arbitrary start
printf("%4$p %5$p %6$p %7$p %8$p %9$p %10$p %11$p \n", 12, 34);
int out;
//write number of bytes printed to "out" parameter
printf("%s %n", "TEST", &out);
printf("Written %d bytes\n", out); // "TEST " => 5 bytes
printf("%100s %n", "TEST", &out);
printf("Written %d bytes\n", out); // 100 + 1 => 101 bytes
return 0;
}
$ ./main
12 34
12 34
34 12
12 34 0 0
(nil) 0xa 0x7fffffffe178 0x155555050 0x7fffffffe170 (nil) 0x555555555240 0x7ffff7dfed0a
TEST Written 5 bytes
TEST Written 101 bytes
The binaries have a trivial vulnerability as in the previous lab. However, this time, the end game is not to just print “Task X solved” but to obtain code execution. We achieve this by calling system("/bin/sh")
. To this end, you will need to construct increasingly difficult ROP chains.
pop rdi; ret
gadget.pop rsi; ret
gadget.
system
in the binary. Using gdb find the address of the string “/bin/sh\x00” in the binary
system
password.txt
(1p)system
is no longer called. However, it is possible to recover its address using a helper function.password.txt
(2p)password.txt
(1p)password.txt
(1p)