Skip to content

Commit

Permalink
Implement entrypoint hijacking for argument passing (#28)
Browse files Browse the repository at this point in the history
* Implement changes for cmd.exe support

* Fix FindXXXFile functions

* Add a very dirty hack for cmd.exe

* Add initial entrypoint hijacking support

* Move stdio related functions to a separate file

* Add instruction cache clearing (probably needed for ARM)

* Add #error for compiling on ARM
I do not know ARM assembly, so I can't write the patching code for that.

* Replace the #error directive with a FIXME comment

* Fix an ARM compile error
  • Loading branch information
TheNNX authored Apr 14, 2024
1 parent df55bb7 commit 22efc0b
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 2 deletions.
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

0 comments on commit 22efc0b

Please sign in to comment.