Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement entrypoint hijacking for argument passing #28

Merged
merged 11 commits into from
Apr 14, 2024
137 changes: 135 additions & 2 deletions COREDLL/dllmain.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,130 @@
// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
#include "winuser_wcecl.h"

typedef UINT(__cdecl* CE_ENTRYPOINT)(HINSTANCE, HINSTANCE, LPCWSTR, int);
void WceclEntrypointWrapper();

#ifdef _M_IX86
#else
/* FIXME: No patching code for architectures other than x86. */
#endif

#pragma pack(push, 1)

static struct
{
BYTE Push;
void* Address;
BYTE Ret;
}
EntrypointHijackCode[] = { {0x68, WceclEntrypointWrapper, 0xC3} };
#pragma pack(pop)

static BYTE EntrypointRepairCode[sizeof(EntrypointHijackCode)];
CE_ENTRYPOINT Entrypoint;

static void WceclEntrypointWrapper()
{
STARTUPINFOW startupInfo;
LPCWSTR commandLine;
BOOL bQuoted;
UINT result;
int nCmdShow;

GetStartupInfoW(&startupInfo);
commandLine = GetCommandLineW();

/* FIXME: It seems WinCE programs do not want the image path to be included
in the commandLine passed to them.

For now, find the first argument and skip its length worth of bytes
from the command line. */
bQuoted = FALSE;

while (*commandLine)
{
if (*commandLine == '"')
{
bQuoted = !bQuoted;
}
if (bQuoted == FALSE)
{
if (iswspace(*commandLine))
{
while (iswspace(*commandLine)) commandLine++;
break;
}
}
commandLine++;
}

nCmdShow = 1;
if (startupInfo.dwFlags & STARTF_USESHOWWINDOW)
{
switch (startupInfo.wShowWindow)
{
case SW_RESTORE:
nCmdShow = WINCE_SW_RESTORE;
break;
case SW_MAXIMIZE:
nCmdShow = WINCE_SW_MAXIMIZE;
break;
}
}

memcpy(Entrypoint, EntrypointRepairCode, sizeof(EntrypointRepairCode));
FlushInstructionCache(GetCurrentProcess(), Entrypoint, sizeof(EntrypointRepairCode));
result = Entrypoint(GetModuleHandleW(NULL), NULL, commandLine, nCmdShow);
ExitProcess(result);
}

static BOOL WceclPatchEntrypoint()
{
MODULEINFO moduleInfo;
HMODULE hModule;
PIMAGE_DOS_HEADER dosHeader;
DWORD dwOld;
MEMORY_BASIC_INFORMATION mbi;
CE_ENTRYPOINT entrypoint;

hModule = GetModuleHandleW(NULL);
dosHeader = (PIMAGE_DOS_HEADER)hModule;

if (GetModuleInformation(
GetCurrentProcess(),
hModule,
&moduleInfo,
sizeof(moduleInfo)) == FALSE)
{
return FALSE;
}
entrypoint = (CE_ENTRYPOINT)moduleInfo.EntryPoint;

/* Unprotect the entrypoint, so it is possible to hijack it, and
to later repair it. */

VirtualQuery(entrypoint, &mbi, sizeof(mbi));
mbi.Protect &= ~(PAGE_READONLY | PAGE_EXECUTE_READ);
mbi.Protect |= PAGE_EXECUTE_READWRITE;

if (VirtualProtect(
mbi.BaseAddress,
mbi.RegionSize,
mbi.Protect,
&dwOld) == FALSE)
{
return FALSE;
}

memcpy(EntrypointRepairCode, entrypoint, sizeof(EntrypointRepairCode));
memcpy(entrypoint, EntrypointHijackCode, sizeof(EntrypointHijackCode));
FlushInstructionCache(GetCurrentProcess(), entrypoint, sizeof(EntrypointHijackCode));

Entrypoint = entrypoint;

return TRUE;
}

BOOL __stdcall DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
Expand All @@ -10,6 +135,10 @@ BOOL __stdcall DllMain(HMODULE hModule,
{
case DLL_PROCESS_ATTACH:
{
AllocConsole();
freopen("CONOUT$", "w", stdout);
freopen("CONIN$", "r", stdin);

if (MessageBoxExW(
NULL,
L"Attach a debugger now?",
Expand All @@ -26,7 +155,7 @@ BOOL __stdcall DllMain(HMODULE hModule,
swprintf_s(CmdLineBuf, 256, L"%s -p %d", VSJitDebugger, GetCurrentProcessId());

StartupInfo.wShowWindow = TRUE;

// MessageBoxW(NULL, CmdLineBuf, VSJitDebugger, 0);

Assert32(CreateProcess(
Expand All @@ -41,9 +170,13 @@ BOOL __stdcall DllMain(HMODULE hModule,
CloseHandle(Info.hProcess);
CloseHandle(Info.hThread);
}
#ifdef _M_IX86
WceclPatchEntrypoint();
#else
/* FIXME: No patching code for architectures other than x86. */
#endif
break;
};
//
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
Expand Down
1 change: 1 addition & 0 deletions COREDLL/other.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ void* _fileno_WCECL(FILE* file)
return result;
}

/* https://stackoverflow.com/a/3989842 */
return (void*)_get_osfhandle(_fileno(file));
}

Expand Down