1. 보호기법 확인
NX와 PIE 보호기법이 적용되어 있다.
NX로 shellcode를 stack에 올리지 못하고(mprotect 함수 사용하면 되긴 하지만),
PIE로 메모리 주소가 계속 변경된다.
따라서 RTL + gadgets 인 ROP를 사용하고, offset을 구해서 실행 시 정확한 주소를 구할 수 있다.
* 그리고 64-bit 바이너리 파일이다!
2. IDA - pseudo code 확인
savedregs 변수는 rbp+0h에 위치 => SFP에 위치함
menu 1 : libc address 출력
menu 2 : 입력한 함수의 address 출력 => 실행 시 system 함수 주소 구해 따로 저장
menu 3 : 입력받을 문자열 길이를 입력하고, 문자열을 gets로 입력받고, 입력받은 것을 nptr에 옮긴 후
nptr 변수에 저장된 문자열을 savedregs 변수에 복사!
savedregs 변수는 rbp 레지스터가 가리키는 곳에 위치하는 SFP이다.
따라서 savedregs 변수의 시작부터 복사되는 문자열은
SFP(8) + return address(8)
의 구조로 return address를 덮어 변조할 수 있다.
(기존의 흔한 문제들처럼 buffer와 return address 사이 거리를 구하지 않아도 된다!)
3. 실행 확인
4. 64-bit 인자 전달 방식의 이해 : Gadget의 사용
1) 호출하는 함수의 첫 번째 인자 값 저장 : "pop rdi; ret"
- 공격에 사용하는 RTL의 system 함수의 인자는 1 개이므로 "pop rdi; ret" 가젯만 필요
2) 호출하는 함수의 두 번째 인자 값 저장 : "pop rsi; ret"
3) 호출하는 함수의 첫 번째, 세 번째 인자 값 저장 : "pop rdi; pop rdx; ret"
5. ROP 과정
입력받는 문자열이 복사되는 savedregs 변수는 SFP부터 구조가 이루어지므로
SFP(8) + return address(8) + ...
구조로 payload를 전달하면 된다.
return address에는 rop gadget인 "pop rdi; ret"을 넣어서 system 함수가 인자를 저장할 수 있도록 하고,
ret 시 system 함수 주소로 이동하게 system 함수 주소를 전달한다.
x64 특성 상 구조가
payload += p64(pop_rdi_ret)
payload += p64(binsh)
payload += p64(system)
이러하므로 기존의 x86 형식과 다름을 유의하여 exploit 코드를 작성해보자!
6. 필요한 정보
libc base와 system 함수 offset
libc base와 "/bin/sh" 문자열 offset
libc base와 "pop rdi; ret" 가젯 offset
7. offset 구하기
1) 실행 시 libc start address, system function address, "/bin/sh" address
$ gdb -q r0pbaby
(gdb) info proc map => libc start address
libc start address : 0x7ffff7809000
(gdb) set stop-on-solib-events 1
(gdb) run
(gdb) c
(gdb) p system 또는 (gdb) p &system 또는 (gdb) x system
system function address : 0x7ffff784e390
(gdb) find &system, +9999999, "/bin/sh"
"/bin/sh" address : 0x7ffff7995d57
libc와 "/bin/sh" offset : 0x18cd57
# libc 파일 debugging 해서 libc와 함수 offset 구하기
$ gdb -q /lib/x86_64-linux-gnu/libc-2.23.so
(gdb) p &system
libc_system_offset : 0x45390
# "pop rdi; ret" gadget
$ rp-lin-x64 -f /libc/x86_64-linux-gnu/libc-2.23.so -r 4 | grep "pop rdi"
libc와 "pop rdi; ret" 가젯 offset : 0x13dd17
(나오는 것 중 아무거나 선택)
* libc_system_offset = 0x45390
* libc_binsh_offset = 0x18cd57
* libc_pop_rdi_ret_offset = 0x13dd17
8. exploit code
- menu 2 에서 system 주소를 저장해서 실행 시 libc_addr, binsh_addr, prr_addr를 구한다.
- menu 1에서 libc address를 구하는 것으로 system, binsh, pop_rdi_ret 주소를 구하려고 했는데 안 되서
menu 2에서 system addr 구하는 것으로 함
-payload 전달 시 뒤에 "\n"을 붙여서 exploit이 잘 됐음
- ELF("./r0pbaby")는 없어도 상관없음
-주소를 받아올 때도 long형으로
-long(p.recvn(18), 16)으로 하면 안 됐음. long(p.recv(18), 16) long(p.recv(18), 16)로 하면 됨
위의 long(p.recv(18), 16)으로 system_addr를 받는 방법도 exploit이 된다.
9. exploit
[HITCON-Training] lab4 : ret2lib (0) | 2019.08.18 |
---|---|
r0pbaby 풀고 정리 (0) | 2019.08.16 |
[PlaidCTF 2013] ropasaurusrex (0) | 2019.08.15 |
[HITCON-Training] lab5 : simplerop (0) | 2019.08.15 |
[TAMU 2019] pwn2 (0) | 2019.08.14 |