106 lines
3.2 KiB
C
106 lines
3.2 KiB
C
/*
|
|
Test for a valid process. This may sometimes detect GUI, even for a console
|
|
process. I think this is due to a DLL being loaded in the address space
|
|
before the main image. Ideally I could just use the base address directly,
|
|
but that doesn't seem easy to do for another process - there doesn't seem to
|
|
be a GetModuleHandle for another process. The CreateRemoteThread trick won't
|
|
work with 64-bit (exit code is DWORD) and setting it up to make it work
|
|
hardly seems worth it. There's GetModuleInformation, but passing in NULL just
|
|
returns a base of NULL, so that's no help. Since 64/32 is sufficient, let
|
|
ansicon.exe handle the difference between console/GUI.
|
|
|
|
Update: ignore images characterised as DLL.
|
|
*/
|
|
|
|
#include "ansicon.h"
|
|
|
|
|
|
int ProcessType( LPPROCESS_INFORMATION pinfo, BOOL* gui )
|
|
{
|
|
char* ptr;
|
|
MEMORY_BASIC_INFORMATION minfo;
|
|
IMAGE_DOS_HEADER dos_header;
|
|
IMAGE_NT_HEADERS nt_header;
|
|
SIZE_T read;
|
|
|
|
*gui = FALSE;
|
|
for (ptr = NULL;
|
|
VirtualQueryEx( pinfo->hProcess, ptr, &minfo, sizeof(minfo) );
|
|
ptr += minfo.RegionSize)
|
|
{
|
|
if (minfo.BaseAddress == minfo.AllocationBase &&
|
|
ReadProcessMemory( pinfo->hProcess, minfo.AllocationBase,
|
|
&dos_header, sizeof(dos_header), &read ))
|
|
{
|
|
if (dos_header.e_magic == IMAGE_DOS_SIGNATURE)
|
|
{
|
|
if (ReadProcessMemory( pinfo->hProcess, (char*)minfo.AllocationBase +
|
|
dos_header.e_lfanew, &nt_header,
|
|
sizeof(nt_header), &read ))
|
|
{
|
|
if (nt_header.Signature == IMAGE_NT_SIGNATURE &&
|
|
(nt_header.FileHeader.Characteristics &
|
|
(IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL))
|
|
== IMAGE_FILE_EXECUTABLE_IMAGE)
|
|
{
|
|
*gui = (nt_header.OptionalHeader.Subsystem
|
|
== IMAGE_SUBSYSTEM_WINDOWS_GUI);
|
|
if (nt_header.OptionalHeader.Subsystem ==
|
|
IMAGE_SUBSYSTEM_WINDOWS_CUI || *gui)
|
|
{
|
|
if (nt_header.FileHeader.Machine == IMAGE_FILE_MACHINE_I386)
|
|
{
|
|
// Microsoft ignores precision on %p.
|
|
DEBUGSTR( 1, L" 32-bit %s (base = %.8X)",
|
|
(*gui) ? L"GUI" : L"console",
|
|
(DWORD)(DWORD_PTR)minfo.AllocationBase );
|
|
return 32;
|
|
}
|
|
#ifdef _WIN64
|
|
if (nt_header.FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64)
|
|
{
|
|
DEBUGSTR( 1, L" 64-bit %s (base = %p)",
|
|
(*gui) ? L"GUI" : L"console", minfo.AllocationBase );
|
|
return 64;
|
|
}
|
|
#elif defined(W32ON64)
|
|
if (nt_header.FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64)
|
|
{
|
|
DEBUGSTR( 1, L" 64-bit %s",
|
|
(*gui) ? L"GUI" : L"console" );
|
|
return 64;
|
|
}
|
|
#endif
|
|
DEBUGSTR( 1, L" Ignoring unsupported machine (0x%X)",
|
|
nt_header.FileHeader.Machine );
|
|
}
|
|
else
|
|
{
|
|
DEBUGSTR( 1, L" Ignoring unsupported subsystem (%u)",
|
|
nt_header.OptionalHeader.Subsystem );
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#ifdef _WIN32
|
|
// If a 32-bit process loads a 64-bit one, we may miss the base
|
|
// address. If the pointer overflows, assume 64-bit.
|
|
if (((DWORD)ptr >> 12) + ((DWORD)minfo.RegionSize >> 12) > 0x80000)
|
|
{
|
|
#ifdef W32ON64
|
|
DEBUGSTR( 1, L" Pointer overflow: assuming 64-bit console" );
|
|
return 64;
|
|
#else
|
|
DEBUGSTR( 1, L" Ignoring apparent 64-bit process" );
|
|
return 0;
|
|
#endif
|
|
}
|
|
#endif
|
|
}
|
|
|
|
DEBUGSTR( 1, L" Ignoring non-Windows process" );
|
|
return 0;
|
|
}
|