uxmal / reko

Reko is a binary decompiler.
https://uxmal.github.io/reko
GNU General Public License v2.0
2.16k stars 253 forks source link

win32s: Failed to bind call argument #979

Closed maximilien-noal closed 3 years ago

maximilien-noal commented 3 years ago

Full sourcecode of the Win32s C++ console program :

#include <windows.h>

int main(void) {
    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));
    CreateProcessA("C:\\SEGA\\GARFIELD\\GARFIELD.EXE", 0, 0, 0, 0, 0, 0, "C:\\SEGA\\GARFIELD", &si, &pi);
    Sleep(5000);
    HWND handle;
    handle = FindWindowA("Garfield", 0);
    SetForegroundWindow(handle);
    MoveWindow(handle, 0, 0, 640, 480, 1);
    SetActiveWindow(handle);
    PostMessageA(handle, WM_COMMAND, 301, 0);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    while (1)
    {
        if (FindWindowA("Garfield", 0))
        {
            Sleep(400);
        }
        else
        {
            ExitWindowsEx(0, 0);
        }
    }
    return 0;
}

function output (there is a lot more output than that, of course) :

void fn00401000()
{
    word32 ecx_143;
    word32 * edi_140 = fp - 0x44;
    for (ecx_143 = 0x11; ecx_143 != 0x00; --ecx_143)
    {
        *edi_140 = 0x00;
        ++edi_140;
    }
    CreateProcessA(&g_t40402C, 0x00, null, null, 0x00, 0x00, 0x00, &g_t40404C, fp - 0x44, fp - 0x54);
    Sleep(5000);
    Eq_38 eax_65 = FindWindowA(&g_t404020, null);
    SetForegroundWindow(eax_65);
    MoveWindow(eax_65, 0x00, 0x00, 0x0280, 0x01E0, 0x01);
    SetActiveWindow(eax_65);
    PostMessageA(eax_65, 0x0111, 0x012D, 0x00);
    CloseHandle(null);
    CloseHandle(null);
    while (true)
    {
        if (FindWindowA(&g_t404020, null) != null)
            Sleep(400);
        else
        {
            // Failed to bind call argument.
            // Please report this issue at https://github.com/uxmal/reko
            // Failed to bind call argument.
            // Please report this issue at https://github.com/uxmal/reko
            Eq_15 stackArg4 = <invalid>;
            Eq_15 stackArg8 = <invalid>;
            ExitWindowsEx(stackArg4, stackArg8);
        }
    }
}

Reko diagnostics after 'Finish decompilation':

Info,,Packer 'Microsoft Visual C 2.0' detected.
Warning,,Unable to unpack executable file packed with 'Microsoft Visual C 2.0'.
Warning,00401354,Unable to determine the upper bound of an indirect call or jump; there may be more than 2 entries.
Warning,0040329C,Expected sizes of arrays to have been determined by now
Warning,004032BC,Expected sizes of arrays to have been determined by now
Warning,00404168,Expected sizes of arrays to have been determined by now
Warning,00404169,Expected sizes of arrays to have been determined by now
Warning,00404574,Expected sizes of arrays to have been determined by now

Reko version 0.9.2.0 (latest official release).

Compiled with Microsoft Visual C++ 4.1 on Windows 10 x64 20H2, Release mode.

uxmal commented 3 years ago

Thanks for reporting this. Could you supply the binary that triggered the problem?

maximilien-noal commented 3 years ago

Here it is: RUNEXIT.reko.zip

smx-smx commented 3 years ago

The latest official release is rather old tho. Please try the latest nightly build from appveyor instead or build it yourself

maximilien-noal commented 3 years ago

Will do !

uxmal commented 3 years ago

I've reproduced this on master. I'm working on a fix.

uxmal commented 3 years ago

After 1869cc5, I see this:

void fn00401000()
{
    word32 ecx_143;
    word32 * edi_140 = fp - 0x44;
    for (ecx_143 = 0x11; ecx_143 != 0x00; --ecx_143)
    {
        *edi_140 = 0x00;
        ++edi_140;
    }
    CreateProcessA(&g_t40402C, 0x00, null, null, 0x00, 0x00, 0x00, &g_t40404C, fp - 0x44, fp - 0x54);
    Sleep(5000);
    Eq_38 eax_65 = FindWindowA(&g_t404020, null);
    SetForegroundWindow(eax_65);
    MoveWindow(eax_65, 0x00, 0x00, 0x0280, 0x01E0, 0x01);
    SetActiveWindow(eax_65);
    PostMessageA(eax_65, 0x0111, 0x012D, 0x00);
    CloseHandle(null);
    CloseHandle(null);
    while (true)
    {
        if (FindWindowA(&g_t404020, null) != null)
            Sleep(400);
        else
            ExitWindowsEx(0x00, 0x00);
    }
}