[Dreamhack] dungeon-in-1983

chrmqgozj·2025년 2월 11일

DreamHack

목록 보기
23/39
post-thumbnail
  1. main

10개의 스테이지를 해결해야 flag를 얻을 수 있다.
스테이지 클리어 여부는 sub_1407에서 결정한다. (check로 수정)

  1. check
_BOOL8 __fastcall check(__int64 a1, __int64 a2)
{
  int v2; // eax
  int v4; // [rsp+1Ch] [rbp-14h]
  int v5; // [rsp+20h] [rbp-10h]
  int i; // [rsp+24h] [rbp-Ch]
  __int64 v7; // [rsp+28h] [rbp-8h]

  v7 = 0LL;
  v4 = 0;
  v5 = 0;
  for ( i = 0; *(_BYTE *)(i + a1); ++i )
  {
    v2 = *(char *)(i + a1);
    if ( v2 == 65 )
    {
      v5 = 1;
      ++v7;
      if ( v4 )
      {
        puts("A button stucked! Retreat...");
        exit(-1);
      }
      v4 = 1;
    }
    else
    {
      if ( v2 != 66 )
      {
        puts("Invalid button!");
        exit(-1);
      }
      if ( !v5 )
      {
        puts("Lore says the spell should start with A...");
        exit(-1);
      }
      v7 *= 2LL;
      v4 = 0;
    }
  }
  return v7 == a2;
}

저 INFO 값이 ptr의 값이다.

int __fastcall sub_138D(__int64 a1)
{
  return printf(
           "[INFO] HP: %5hu, STR: %5hhu, AGI: %5hhu, VIT: %5hhu, INT: %5hhu, END: %5hhu, DEX: %5hhu\n",
           HIWORD(a1),
           (unsigned __int8)a1,
           BYTE1(a1),
           BYTE2(a1),
           BYTE3(a1),
           BYTE4(a1),
           BYTE5(a1));
}

이 함수에서 ptr이 쪼개진다.

찾아보면 (little-endian 기준)
byte1: 뒤에서 2번째 바이트 (하위 2번째 1바이트)
byte2: 뒤에서 3번째 바이트 (하위 3번째 1바이트)
hiword: 상위 2바이트
unsigned __int8: 하위 1바이트 (little endian 기준으로 마지막 1바이트가 제일 앞에 저장되기 때문

hp << 48 | dex << 40 | end << 32 | iint << 24 | vit << 16 | agi << 8 | sstr

내가 입력한 A, B 배열로 위의 값을 만들 수 있으면 된다.

while num:
	if num%2==1:
    	s += 'A'
        num -= 1
    else:
    	s += 'B'
        num //= 2
  1. exploit.py
from pwn import *

p = remote('host1.dreamhack.games', 24538)

for i in range(10):
    p.recvuntil(b'HP: ')
    hp = int(p.recvuntil(b',')[:-1])
    print(hp)

    p.recvuntil(b'STR: ')
    sstr = int(p.recvuntil(b',')[:-1])
    print(sstr)

    p.recvuntil(b'AGI: ')
    agi = int(p.recvuntil(b',')[:-1])
    print(agi)

    p.recvuntil(b'VIT: ')
    vit = int(p.recvuntil(b',')[:-1])
    print(vit)

    p.recvuntil(b'INT: ')
    iint = int(p.recvuntil(b',')[:-1])
    print(iint)

    p.recvuntil(b'END: ')
    end = int(p.recvuntil(b',')[:-1])
    print(end)

    p.recvuntil(b'DEX: ')
    dex = int(p.recvline()[:-1])
    print(dex)

    num = hp << 48 | dex << 40 | end << 32 | iint << 24 | vit << 16 | agi << 8 | sstr

    s = ''

    while num:
        if num%2==1:
            s += 'A'
            num -= 1
        else:
            s += 'B'
            num //= 2
    #p.interactive()
    print(s[::-1])
    p.sendlineafter(b'Cast your spell!: ', s[::-1])

p.interactive()

0개의 댓글