0

In IDA Pro, i found a function in the game that writes text to console. Here is the function:

; void __cdecl write_to_console(char *Format, char ArgList)
write_to_console proc near              ; CODE XREF: sub_4069C0+34↑p
                                        ; sub_4069C0+10A↑p ...

Format          = dword ptr  4
ArgList         = byte ptr  8

                push    esi
                push    1
                call    sub_67D4F0
                mov     ecx, [eax+1000h]
                lea     edx, [ecx+1]
                and     edx, 80000003h
                jns     short loc_57CDEE
                dec     edx
                or      edx, 0FFFFFFFCh
                inc     edx

loc_57CDEE:                             ; CODE XREF: write_to_console+17↑j
                shl     ecx, 0Ah
                add     ecx, eax
                mov     [eax+1000h], edx
                mov     esi, ecx
                mov     ecx, [esp+8+Format]
                lea     eax, [esp+8+ArgList]
                push    eax             ; ArgList
                push    ecx             ; Format
                push    400h            ; BufferCount
                push    esi             ; Buffer
                call    __vsnprintf
                xor     ecx, ecx
                add     esp, 14h
                cmp     eax, ecx
                mov     [esi+3FFh], cl
                jl      short loc_57CE26
                cmp     eax, 400h
                jl      short loc_57CE3C

loc_57CE26:                             ; CODE XREF: write_to_console+4D↑j
                push    esi             ; ArgList
                push    offset byte_9EE7FC ; Format
                push    1               ; int
                mov     [esi+3FFh], cl
                call    sub_651D90
                add     esp, 0Ch

loc_57CE3C:                             ; CODE XREF: write_to_console+54↑j
                mov     eax, esi
                pop     esi
                retn
write_to_console endp

Image from IDA

Here how it's called:

xor     dword ptr [esi+170h], 1
test    byte ptr [esi+170h], 1
mov     eax, offset aGameGodmodeOn ; "GAME_GODMODE_ON"
jnz     short loc_6462AA
mov     eax, offset aGameGodmodeOff ; "GAME_GODMODE_OFF"
push    eax
push    65h ; 'e'       ; ArgList
push    offset aCS      ; "%c \"%s\""
call    write_to_console
push    eax
sub     esi, offset unk_1A796F8
mov     eax, 4DA637Dh

Image from IDA

now inside my C++ i tried to call the function like this:

typedef void(__cdecl* setup)(const char*, ...);
setup write_to_console= reinterpret_cast<setup>(0x0057CDD0);

void MainThread()
{
    while (true)
    {
        if (GetAsyncKeyState('N') & 0x8000)
        {
            write_to_console("The Function Call worked");
        }
        Sleep(50);
    }
}

I expected it to write "The Function Call worked" in the game console log if i press 'N' in keyboard but instead the game freezes when i press it. How to fix that? Thanks.

EDIT1: after debugging, it turned out that the function is called with EAX beign 0, so the function was accessing invalid memory, but why is that? EAX is supposed to hold the Address of the string to be printed to console, does it have something to do with the game first moving the string address to EAX then push it instead of pushing the string address immediately?

i tried mimic the original code exactly which is:

write_to_console("%c \"%s\"",'e', "GAME_GODMODE_ON");

but didn't work, i also tried to do this before calling:

const char* msg = "GAME_GODMODE_ON";
__asm {
            mov eax, msg
        }

but in both EAX is still zero, i don't know what's the problem.

Image from x64dbg for the original game function been called
Image from x64dbg with my broken function as EAX=0

EDIT2:

sub_67D4F0 while debugging the original function:
0067D4F0 | mov eax,dword ptr ds:[3956508]; eax was the address of the string and here becomes 0
0067D4F5 | mov ecx,dword ptr fs:[2C]; ecx was 0 and becomes 2B95B0E8
0067D4FC | mov edx,dword ptr ds:[ecx+eax*4]; edx was 0 and becomes 09A0F3F0
0067D4FF | mov eax,dword ptr ds:[edx+28]; eax becomes 0251C9F8
0067D505 | mov ecx,dword ptr ss:[esp+4]; ecx becomes 1
0067D509 | mov eax,dword ptr ds:[eax+ecx*4] ;exact point of freeze in my broken function; eax become the address of the string "normal", at the beginning it was another address for the string "GAME_GODMODE_ON".

in my function call EAX is 0 at freeze point not 0251C9F8 like the original function.

6
  • Where does it freeze? Also I assume the game is running on other threads, it may simply deadlock if called from MainThread.
    – Jester
    Commented Jul 6 at 21:20
  • @Jester std::thread consoleThread(CallWriteToConsole); consoleThread.detach(); i tried this inside MainThread(), CallWriteToConsole() is just a void that call write_to_console, to ensure there is no deadlock, yet the game still freezes. I'm not sure if that the correct way tho. The freeze is at the execution of write_to_console("The Function Call worked"); line, just when i press 'N'. Commented Jul 6 at 21:47
  • 1
    You should use your debugger to pinpoint the exact location of the freeze, the source line is not much of a help.
    – Jester
    Commented Jul 6 at 21:58
  • @Jester Edited. Commented Jul 7 at 0:24
  • Value in eax at function entry does not matter. call sub_67D4F0 will set eax as that is the return value. That looks like some memory allocation function.
    – Jester
    Commented Jul 7 at 1:04

0

Browse other questions tagged or ask your own question.