Size of a Giant - 110 (Game)

Writeup by r3ndom_

Created: 2015-12-8

Problem

Grow your character 10x its natural size! That is the power of giants!

Hint

There's a variable somewhere in the code that is set to the character size... Maybe if I could just find it...? Or measure the character, then it could help me find it easier if I have the actual value of it....

Maybe this link could help. I'm trying to manipulate a variable that should be 30 into 300. And look! Here's a line of the source I managed to get! gl::drawSolidTriangle(Vec2f(300, 300), Vec2f(300 - (s / 2), 300 + s), Vec2f(300 + (s / 2), 300 + s));

Another helpful link!

Answer

Overview

Grow your character bigger or manipulate the check for the size.

Methods: 1) Manipulate the check for your size. 2) Change your size (and don't die to the walls). 3) Decrypt the string.

Details

To manipulate the check for size I began by looking references to the encrypted string, "322505102c192c310521342b011920113f34".

I found this in a function, in a subsection at 0x0040921C.

loc_40921C:                             ; CODE XREF: sub_409190+37j
                                        ; sub_409190+57j ...
                add     esi, 14h
                cmp     esi, 140h
                jb      short loc_4091C0
                lea     eax, [edi-12Bh]
                cmp     eax, 2
                ja      loc_4092CB
                cmp     byte_568831, 0
                jnz     loc_4092CB
                mov     eax, dword_55C4FC
                sub     esp, 18h
                mov     esi, esp
                mov     dword_55C558, eax
                sub     esp, 18h
                mov     dword_55C55C, ebx
                mov     ecx, esp        ; int
                mov     dword_55C560, 2
                mov     byte_568831, 1
                push    24h             ; size_t
                mov     dword ptr [ecx+14h], 0Fh
                mov     dword ptr [ecx+10h], 0
                push    offset a322505102c192c ; "322505102c192c310521342b011920113f34"
                mov     byte ptr [ecx], 0
                call    sub_40A2D0
                mov     ecx, esi
                call    sub_408C20
                add     esp, 18h
                lea     ecx, [esp+48h+var_1C]
                call    sub_408D30
                add     esp, 18h
                mov     ecx, offset byte_55C610 ; void *
                push    eax             ; void *
                call    sub_409CD0
                cmp     [esp+30h+var_8], 10h
                jb      short loc_4092BF
                push    [esp+30h+var_1C] ; int
                call    j__free
                add     esp, 4

Note the conditional at the top that jumps away if a specific condition is not met. The easiest way to do this challenge is simply to change the two conditionals to nops or to jump over them. I chose the latter of these two even though it was probably the harder route its often more enjoyable.

So I wrote a quick dll to get the job done.

// Where to jmp to.
dword g_dwsize = 0x0409243;
__declspec(naked) void __cdecl draw_hk()
{
    // Simple long jmp.
    __asm
    {
        jmp dword ptr ds : [g_dwsize]
    }
}

dword HookThread(LPVOID lpParam)
{
    // This just does a little jmp patch for me, I could use it to jmp directly over but I figured why not
    // make the code flow a bit more obtuse?
    Detour((byte*)0x409230, (byte*)draw_hk, 6);
    return 0;
}

#define COERCE_THREAD(a) reinterpret_cast<LPTHREAD_START_ROUTINE>(a)

BOOL WINAPI DllMain(
    _In_ HINSTANCE hinstDLL,
    _In_ DWORD     fdwReason,
    _In_ LPVOID    lpvReserved
    )
{
    if (fdwReason == DLL_PROCESS_ATTACH)
    {
        // Creating a thread here is the best because it doesn't have a chance to cause deadlock.
        CreateThread(0, 0, COERCE_THREAD(HookThread), 0, 0, 0);
    }
    return TRUE;
}

Flag

sctf{maximumpower}

Alternative Methods (in brief)

Decrypting the string is possible as always.

There are also many possible modifications that all achieve the same goal of skipping the check, I chose that in particular because it was fairly quick.

Modifying the size variable in the binary would not be a good idea simply because it will kill you instantly on the spawn of your character. Instead the best idea is to do a live change of the size variable after you find it in the binary once you're out of the square.