@ -29,32 +29,32 @@ const GUID DETOUR_EXE_HELPER_GUID = { /* ea0251b9-5cde-41b5-98d0-2af4a26b0fee */
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//
//
// Enum ate through modules in the target process.
// Enum er ate through modules in the target process.
//
//
static BOOL WINA PI LoadNtHeaderFromProcess ( HANDLE hProcess ,
static PVO ID LoadNtHeaderFromProcess ( _In_ HANDLE hProcess ,
HMODULE hModule ,
_In_ HMODULE hModule ,
PIMAGE_NT_HEADERS32 pNtHeader )
_Out_ PIMAGE_NT_HEADERS32 pNtHeader )
{
{
ZeroMemory ( pNtHeader , sizeof ( * pNtHeader ) ) ;
PBYTE pbModule = ( PBYTE ) hModule ;
PBYTE pbModule = ( PBYTE ) hModule ;
if ( pbModule = = NULL ) {
if ( pbModule = = NULL ) {
SetLastError ( ERROR_INVALID_PARAMETER ) ;
SetLastError ( ERROR_INVALID_PARAMETER ) ;
return FALSE ;
return NULL ;
}
}
MEMORY_BASIC_INFORMATION mbi ;
MEMORY_BASIC_INFORMATION mbi ;
ZeroMemory ( & mbi , sizeof ( mbi ) ) ;
ZeroMemory ( & mbi , sizeof ( mbi ) ) ;
if ( VirtualQueryEx ( hProcess , hModule , & mbi , sizeof ( mbi ) ) = = 0 ) {
if ( VirtualQueryEx ( hProcess , hModule , & mbi , sizeof ( mbi ) ) = = 0 ) {
return FALSE ;
return NULL ;
}
}
IMAGE_DOS_HEADER idh ;
IMAGE_DOS_HEADER idh ;
if ( ! ReadProcessMemory ( hProcess , pbModule , & idh , sizeof ( idh ) , NULL ) ) {
if ( ! ReadProcessMemory ( hProcess , pbModule , & idh , sizeof ( idh ) , NULL ) ) {
DETOUR_TRACE ( ( " ReadProcessMemory(idh@%p..%p) failed: % d \n " ,
DETOUR_TRACE ( ( " ReadProcessMemory(idh@%p..%p) failed: % lu \n " ,
pbModule , pbModule + sizeof ( idh ) , GetLastError ( ) ) ) ;
pbModule , pbModule + sizeof ( idh ) , GetLastError ( ) ) ) ;
return FALSE ;
return NULL ;
}
}
if ( idh . e_magic ! = IMAGE_DOS_SIGNATURE | |
if ( idh . e_magic ! = IMAGE_DOS_SIGNATURE | |
@ -62,31 +62,37 @@ static BOOL WINAPI LoadNtHeaderFromProcess(HANDLE hProcess,
( DWORD ) idh . e_lfanew < sizeof ( idh ) ) {
( DWORD ) idh . e_lfanew < sizeof ( idh ) ) {
SetLastError ( ERROR_BAD_EXE_FORMAT ) ;
SetLastError ( ERROR_BAD_EXE_FORMAT ) ;
return FALSE ;
return NULL ;
}
}
if ( ! ReadProcessMemory ( hProcess , pbModule + idh . e_lfanew ,
if ( ! ReadProcessMemory ( hProcess , pbModule + idh . e_lfanew ,
pNtHeader , sizeof ( * pNtHeader ) , NULL ) ) {
pNtHeader , sizeof ( * pNtHeader ) , NULL ) ) {
DETOUR_TRACE ( ( " ReadProcessMemory(inh@%p..%p:%p) failed: % d \n " ,
DETOUR_TRACE ( ( " ReadProcessMemory(inh@%p..%p:%p) failed: % lu \n " ,
pbModule + idh . e_lfanew ,
pbModule + idh . e_lfanew ,
pbModule + idh . e_lfanew + sizeof ( * pNtHeader ) ,
pbModule + idh . e_lfanew + sizeof ( * pNtHeader ) ,
pbModule ,
pbModule ,
GetLastError ( ) ) ) ;
GetLastError ( ) ) ) ;
return FALSE ;
return NULL ;
}
}
if ( pNtHeader - > Signature ! = IMAGE_NT_SIGNATURE ) {
if ( pNtHeader - > Signature ! = IMAGE_NT_SIGNATURE ) {
SetLastError ( ERROR_BAD_EXE_FORMAT ) ;
SetLastError ( ERROR_BAD_EXE_FORMAT ) ;
return FALSE ;
return NULL ;
}
}
return TRUE ;
return pbModule + idh . e_lfanew ;
}
}
static HMODULE WINAPI EnumerateModulesInProcess ( HANDLE hProcess ,
static HMODULE EnumerateModulesInProcess ( _In_ HANDLE hProcess ,
HMODULE hModuleLast ,
_In_opt_ HMODULE hModuleLast ,
PIMAGE_NT_HEADERS32 pNtHeader )
_Out_ PIMAGE_NT_HEADERS32 pNtHeader ,
_Out_opt_ PVOID * pRemoteNtHeader )
{
{
ZeroMemory ( pNtHeader , sizeof ( * pNtHeader ) ) ;
if ( pRemoteNtHeader ) {
* pRemoteNtHeader = NULL ;
}
PBYTE pbLast = ( PBYTE ) hModuleLast + MM_ALLOCATION_GRANULARITY ;
PBYTE pbLast = ( PBYTE ) hModuleLast + MM_ALLOCATION_GRANULARITY ;
MEMORY_BASIC_INFORMATION mbi ;
MEMORY_BASIC_INFORMATION mbi ;
@ -118,13 +124,147 @@ static HMODULE WINAPI EnumerateModulesInProcess(HANDLE hProcess,
continue ;
continue ;
}
}
if ( LoadNtHeaderFromProcess ( hProcess , ( HMODULE ) pbLast , pNtHeader ) ) {
PVOID remoteHeader
= LoadNtHeaderFromProcess ( hProcess , ( HMODULE ) pbLast , pNtHeader ) ;
if ( remoteHeader ) {
if ( pRemoteNtHeader ) {
* pRemoteNtHeader = remoteHeader ;
}
return ( HMODULE ) pbLast ;
return ( HMODULE ) pbLast ;
}
}
}
}
return NULL ;
return NULL ;
}
}
//////////////////////////////////////////////////////////////////////////////
//
// Find payloads in target process.
//
static PVOID FindDetourSectionInRemoteModule ( _In_ HANDLE hProcess ,
_In_ HMODULE hModule ,
_In_ const IMAGE_NT_HEADERS32 * pNtHeader ,
_In_ PVOID pRemoteNtHeader )
{
if ( pNtHeader - > FileHeader . SizeOfOptionalHeader = = 0 ) {
SetLastError ( ERROR_EXE_MARKED_INVALID ) ;
return NULL ;
}
PIMAGE_SECTION_HEADER pRemoteSectionHeaders
= ( PIMAGE_SECTION_HEADER ) ( ( PBYTE ) pRemoteNtHeader
+ sizeof ( pNtHeader - > Signature )
+ sizeof ( pNtHeader - > FileHeader )
+ pNtHeader - > FileHeader . SizeOfOptionalHeader ) ;
IMAGE_SECTION_HEADER header ;
for ( DWORD n = 0 ; n < pNtHeader - > FileHeader . NumberOfSections ; + + n ) {
if ( ! ReadProcessMemory ( hProcess , pRemoteSectionHeaders + n , & header , sizeof ( header ) , NULL ) ) {
DETOUR_TRACE ( ( " ReadProcessMemory(ish@%p..%p) failed: %lu \n " ,
pRemoteSectionHeaders + n ,
( PBYTE ) ( pRemoteSectionHeaders + n ) + sizeof ( header ) ,
GetLastError ( ) ) ) ;
return NULL ;
}
if ( strcmp ( ( PCHAR ) header . Name , " .detour " ) = = 0 ) {
if ( header . VirtualAddress = = 0 | |
header . SizeOfRawData = = 0 ) {
break ;
}
SetLastError ( NO_ERROR ) ;
return ( PBYTE ) hModule + header . VirtualAddress ;
}
}
SetLastError ( ERROR_EXE_MARKED_INVALID ) ;
return NULL ;
}
static PVOID FindPayloadInRemoteDetourSection ( _In_ HANDLE hProcess ,
_In_ REFGUID rguid ,
_Out_opt_ DWORD * pcbData ,
_In_ PVOID pvRemoteDetoursSection )
{
if ( pcbData ) {
* pcbData = 0 ;
}
PBYTE pbData = ( PBYTE ) pvRemoteDetoursSection ;
DETOUR_SECTION_HEADER header ;
if ( ! ReadProcessMemory ( hProcess , pbData , & header , sizeof ( header ) , NULL ) ) {
DETOUR_TRACE ( ( " ReadProcessMemory(dsh@%p..%p) failed: %lu \n " ,
pbData ,
pbData + sizeof ( header ) ,
GetLastError ( ) ) ) ;
return NULL ;
}
if ( header . cbHeaderSize < sizeof ( DETOUR_SECTION_HEADER ) | |
header . nSignature ! = DETOUR_SECTION_HEADER_SIGNATURE ) {
SetLastError ( ERROR_EXE_MARKED_INVALID ) ;
return NULL ;
}
if ( header . nDataOffset = = 0 ) {
header . nDataOffset = header . cbHeaderSize ;
}
for ( PVOID pvSection = pbData + header . nDataOffset ; pvSection < pbData + header . cbDataSize ; ) {
DETOUR_SECTION_RECORD section ;
if ( ! ReadProcessMemory ( hProcess , pvSection , & section , sizeof ( section ) , NULL ) ) {
DETOUR_TRACE ( ( " ReadProcessMemory(dsr@%p..%p) failed: %lu \n " ,
pvSection ,
( PBYTE ) pvSection + sizeof ( section ) ,
GetLastError ( ) ) ) ;
return NULL ;
}
if ( DetourAreSameGuid ( section . guid , rguid ) ) {
if ( pcbData ) {
* pcbData = section . cbBytes - sizeof ( section ) ;
}
SetLastError ( NO_ERROR ) ;
return ( DETOUR_SECTION_RECORD * ) pvSection + 1 ;
}
pvSection = ( PBYTE ) pvSection + section . cbBytes ;
}
return NULL ;
}
_Success_ ( return ! = NULL )
PVOID WINAPI DetourFindRemotePayload ( _In_ HANDLE hProcess ,
_In_ REFGUID rguid ,
_Out_opt_ DWORD * pcbData )
{
if ( hProcess = = NULL ) {
SetLastError ( ERROR_INVALID_HANDLE ) ;
return NULL ;
}
IMAGE_NT_HEADERS32 header ;
PVOID pvRemoteHeader ;
for ( HMODULE hMod = NULL ; ( hMod = EnumerateModulesInProcess ( hProcess , hMod , & header , & pvRemoteHeader ) ) ! = NULL ; ) {
PVOID pvData = FindDetourSectionInRemoteModule ( hProcess , hMod , & header , pvRemoteHeader ) ;
if ( pvData ! = NULL ) {
pvData = FindPayloadInRemoteDetourSection ( hProcess , rguid , pcbData , pvData ) ;
if ( pvData ! = NULL ) {
return pvData ;
}
}
}
SetLastError ( ERROR_MOD_NOT_FOUND ) ;
return NULL ;
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//
//
// Find a region of memory in which we can create a replacement import table.
// Find a region of memory in which we can create a replacement import table.
@ -142,7 +282,7 @@ static PBYTE FindAndAllocateNearBase(HANDLE hProcess, PBYTE pbModule, PBYTE pbBa
if ( GetLastError ( ) = = ERROR_INVALID_PARAMETER ) {
if ( GetLastError ( ) = = ERROR_INVALID_PARAMETER ) {
break ;
break ;
}
}
DETOUR_TRACE ( ( " VirtualQueryEx(%p) failed: % d \n " ,
DETOUR_TRACE ( ( " VirtualQueryEx(%p) failed: % lu \n " ,
pbLast , GetLastError ( ) ) ) ;
pbLast , GetLastError ( ) ) ) ;
break ;
break ;
}
}
@ -187,7 +327,7 @@ static PBYTE FindAndAllocateNearBase(HANDLE hProcess, PBYTE pbModule, PBYTE pbBa
PBYTE pbAlloc = ( PBYTE ) VirtualAllocEx ( hProcess , pbAddress , cbAlloc ,
PBYTE pbAlloc = ( PBYTE ) VirtualAllocEx ( hProcess , pbAddress , cbAlloc ,
MEM_RESERVE | MEM_COMMIT , PAGE_READWRITE ) ;
MEM_RESERVE | MEM_COMMIT , PAGE_READWRITE ) ;
if ( pbAlloc = = NULL ) {
if ( pbAlloc = = NULL ) {
DETOUR_TRACE ( ( " VirtualAllocEx(%p) failed: % d \n " , pbAddress , GetLastError ( ) ) ) ;
DETOUR_TRACE ( ( " VirtualAllocEx(%p) failed: % lu \n " , pbAddress , GetLastError ( ) ) ) ;
continue ;
continue ;
}
}
# ifdef _WIN64
# ifdef _WIN64
@ -246,7 +386,7 @@ static BOOL RecordExeRestore(HANDLE hProcess, HMODULE hModule, DETOUR_EXE_RESTOR
der . pidh = ( PBYTE ) hModule ;
der . pidh = ( PBYTE ) hModule ;
der . cbidh = sizeof ( der . idh ) ;
der . cbidh = sizeof ( der . idh ) ;
if ( ! ReadProcessMemory ( hProcess , der . pidh , & der . idh , sizeof ( der . idh ) , NULL ) ) {
if ( ! ReadProcessMemory ( hProcess , der . pidh , & der . idh , sizeof ( der . idh ) , NULL ) ) {
DETOUR_TRACE ( ( " ReadProcessMemory(idh@%p..%p) failed: % d \n " ,
DETOUR_TRACE ( ( " ReadProcessMemory(idh@%p..%p) failed: % lu \n " ,
der . pidh , der . pidh + der . cbidh , GetLastError ( ) ) ) ;
der . pidh , der . pidh + der . cbidh , GetLastError ( ) ) ) ;
return FALSE ;
return FALSE ;
}
}
@ -257,7 +397,7 @@ static BOOL RecordExeRestore(HANDLE hProcess, HMODULE hModule, DETOUR_EXE_RESTOR
der . pinh = der . pidh + der . idh . e_lfanew ;
der . pinh = der . pidh + der . idh . e_lfanew ;
der . cbinh = FIELD_OFFSET ( IMAGE_NT_HEADERS , OptionalHeader ) ;
der . cbinh = FIELD_OFFSET ( IMAGE_NT_HEADERS , OptionalHeader ) ;
if ( ! ReadProcessMemory ( hProcess , der . pinh , & der . inh , der . cbinh , NULL ) ) {
if ( ! ReadProcessMemory ( hProcess , der . pinh , & der . inh , der . cbinh , NULL ) ) {
DETOUR_TRACE ( ( " ReadProcessMemory(inh@%p..%p) failed: % d \n " ,
DETOUR_TRACE ( ( " ReadProcessMemory(inh@%p..%p) failed: % lu \n " ,
der . pinh , der . pinh + der . cbinh , GetLastError ( ) ) ) ;
der . pinh , der . pinh + der . cbinh , GetLastError ( ) ) ) ;
return FALSE ;
return FALSE ;
}
}
@ -272,7 +412,7 @@ static BOOL RecordExeRestore(HANDLE hProcess, HMODULE hModule, DETOUR_EXE_RESTOR
}
}
if ( ! ReadProcessMemory ( hProcess , der . pinh , & der . inh , der . cbinh , NULL ) ) {
if ( ! ReadProcessMemory ( hProcess , der . pinh , & der . inh , der . cbinh , NULL ) ) {
DETOUR_TRACE ( ( " ReadProcessMemory(inh@%p..%p) failed: % d \n " ,
DETOUR_TRACE ( ( " ReadProcessMemory(inh@%p..%p) failed: % lu \n " ,
der . pinh , der . pinh + der . cbinh , GetLastError ( ) ) ) ;
der . pinh , der . pinh + der . cbinh , GetLastError ( ) ) ) ;
return FALSE ;
return FALSE ;
}
}
@ -284,7 +424,7 @@ static BOOL RecordExeRestore(HANDLE hProcess, HMODULE hModule, DETOUR_EXE_RESTOR
if ( der . inh32 . CLR_DIRECTORY . VirtualAddress ! = 0 & &
if ( der . inh32 . CLR_DIRECTORY . VirtualAddress ! = 0 & &
der . inh32 . CLR_DIRECTORY . Size ! = 0 ) {
der . inh32 . CLR_DIRECTORY . Size ! = 0 ) {
DETOUR_TRACE ( ( " CLR32.VirtAddr=% x, CLR.Size=%x \n " ,
DETOUR_TRACE ( ( " CLR32.VirtAddr=% 08lx, CLR.Size=%lu \n " ,
der . inh32 . CLR_DIRECTORY . VirtualAddress ,
der . inh32 . CLR_DIRECTORY . VirtualAddress ,
der . inh32 . CLR_DIRECTORY . Size ) ) ;
der . inh32 . CLR_DIRECTORY . Size ) ) ;
@ -295,7 +435,7 @@ static BOOL RecordExeRestore(HANDLE hProcess, HMODULE hModule, DETOUR_EXE_RESTOR
if ( der . inh64 . CLR_DIRECTORY . VirtualAddress ! = 0 & &
if ( der . inh64 . CLR_DIRECTORY . VirtualAddress ! = 0 & &
der . inh64 . CLR_DIRECTORY . Size ! = 0 ) {
der . inh64 . CLR_DIRECTORY . Size ! = 0 ) {
DETOUR_TRACE ( ( " CLR64.VirtAddr=% x, CLR.Size=%x \n " ,
DETOUR_TRACE ( ( " CLR64.VirtAddr=% 08lx, CLR.Size=%lu \n " ,
der . inh64 . CLR_DIRECTORY . VirtualAddress ,
der . inh64 . CLR_DIRECTORY . VirtualAddress ,
der . inh64 . CLR_DIRECTORY . Size ) ) ;
der . inh64 . CLR_DIRECTORY . Size ) ) ;
@ -306,7 +446,7 @@ static BOOL RecordExeRestore(HANDLE hProcess, HMODULE hModule, DETOUR_EXE_RESTOR
if ( der . pclr ! = 0 ) {
if ( der . pclr ! = 0 ) {
der . cbclr = sizeof ( der . clr ) ;
der . cbclr = sizeof ( der . clr ) ;
if ( ! ReadProcessMemory ( hProcess , der . pclr , & der . clr , der . cbclr , NULL ) ) {
if ( ! ReadProcessMemory ( hProcess , der . pclr , & der . clr , der . cbclr , NULL ) ) {
DETOUR_TRACE ( ( " ReadProcessMemory(clr@%p..%p) failed: % d \n " ,
DETOUR_TRACE ( ( " ReadProcessMemory(clr@%p..%p) failed: % lu \n " ,
der . pclr , der . pclr + der . cbclr , GetLastError ( ) ) ) ;
der . pclr , der . pclr + der . cbclr , GetLastError ( ) ) ) ;
return FALSE ;
return FALSE ;
}
}
@ -323,6 +463,7 @@ static BOOL RecordExeRestore(HANDLE hProcess, HMODULE hModule, DETOUR_EXE_RESTOR
# define IMAGE_NT_HEADERS_XX IMAGE_NT_HEADERS32
# define IMAGE_NT_HEADERS_XX IMAGE_NT_HEADERS32
# define IMAGE_NT_OPTIONAL_HDR_MAGIC_XX IMAGE_NT_OPTIONAL_HDR32_MAGIC
# define IMAGE_NT_OPTIONAL_HDR_MAGIC_XX IMAGE_NT_OPTIONAL_HDR32_MAGIC
# define IMAGE_ORDINAL_FLAG_XX IMAGE_ORDINAL_FLAG32
# define IMAGE_ORDINAL_FLAG_XX IMAGE_ORDINAL_FLAG32
# define IMAGE_THUNK_DATAXX IMAGE_THUNK_DATA32
# define UPDATE_IMPORTS_XX UpdateImports32
# define UPDATE_IMPORTS_XX UpdateImports32
# define DETOURS_BITS_XX 32
# define DETOURS_BITS_XX 32
# include "uimports.cc"
# include "uimports.cc"
@ -339,6 +480,7 @@ static BOOL RecordExeRestore(HANDLE hProcess, HMODULE hModule, DETOUR_EXE_RESTOR
# define IMAGE_NT_HEADERS_XX IMAGE_NT_HEADERS64
# define IMAGE_NT_HEADERS_XX IMAGE_NT_HEADERS64
# define IMAGE_NT_OPTIONAL_HDR_MAGIC_XX IMAGE_NT_OPTIONAL_HDR64_MAGIC
# define IMAGE_NT_OPTIONAL_HDR_MAGIC_XX IMAGE_NT_OPTIONAL_HDR64_MAGIC
# define IMAGE_ORDINAL_FLAG_XX IMAGE_ORDINAL_FLAG64
# define IMAGE_ORDINAL_FLAG_XX IMAGE_ORDINAL_FLAG64
# define IMAGE_THUNK_DATAXX IMAGE_THUNK_DATA64
# define UPDATE_IMPORTS_XX UpdateImports64
# define UPDATE_IMPORTS_XX UpdateImports64
# define DETOURS_BITS_XX 64
# define DETOURS_BITS_XX 64
# include "uimports.cc"
# include "uimports.cc"
@ -374,7 +516,7 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine,
//////////////////////////////////////////////////////// Read old headers.
//////////////////////////////////////////////////////// Read old headers.
//
//
if ( ! ReadProcessMemory ( hProcess , pbModule , & idh , sizeof ( idh ) , NULL ) ) {
if ( ! ReadProcessMemory ( hProcess , pbModule , & idh , sizeof ( idh ) , NULL ) ) {
DETOUR_TRACE ( ( " ReadProcessMemory(idh@%p..%p) failed: % d \n " ,
DETOUR_TRACE ( ( " ReadProcessMemory(idh@%p..%p) failed: % lu \n " ,
pbModule , pbModule + sizeof ( idh ) , GetLastError ( ) ) ) ;
pbModule , pbModule + sizeof ( idh ) , GetLastError ( ) ) ) ;
return FALSE ;
return FALSE ;
}
}
@ -383,7 +525,7 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine,
PBYTE pnh = pbModule + idh . e_lfanew ;
PBYTE pnh = pbModule + idh . e_lfanew ;
if ( ! ReadProcessMemory ( hProcess , pnh , & inh32 , sizeof ( inh32 ) , NULL ) ) {
if ( ! ReadProcessMemory ( hProcess , pnh , & inh32 , sizeof ( inh32 ) , NULL ) ) {
DETOUR_TRACE ( ( " ReadProcessMemory(inh@%p..%p) failed: % d \n " ,
DETOUR_TRACE ( ( " ReadProcessMemory(inh@%p..%p) failed: % lu \n " ,
pnh , pnh + sizeof ( inh32 ) , GetLastError ( ) ) ) ;
pnh , pnh + sizeof ( inh32 ) , GetLastError ( ) ) ) ;
return FALSE ;
return FALSE ;
}
}
@ -398,7 +540,7 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine,
inh32 . FileHeader . SizeOfOptionalHeader ;
inh32 . FileHeader . SizeOfOptionalHeader ;
ULONG cb = inh32 . FileHeader . NumberOfSections * sizeof ( IMAGE_SECTION_HEADER ) ;
ULONG cb = inh32 . FileHeader . NumberOfSections * sizeof ( IMAGE_SECTION_HEADER ) ;
if ( ! ReadProcessMemory ( hProcess , psects , & sects , cb , NULL ) ) {
if ( ! ReadProcessMemory ( hProcess , psects , & sects , cb , NULL ) ) {
DETOUR_TRACE ( ( " ReadProcessMemory(ish@%p..%p) failed: % d \n " ,
DETOUR_TRACE ( ( " ReadProcessMemory(ish@%p..%p) failed: % lu \n " ,
psects , psects + cb , GetLastError ( ) ) ) ;
psects , psects + cb , GetLastError ( ) ) ) ;
return FALSE ;
return FALSE ;
}
}
@ -455,7 +597,7 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine,
}
}
if ( ! WriteProcessMemory ( hProcess , pnh , & inh64 , sizeof ( inh64 ) , NULL ) ) {
if ( ! WriteProcessMemory ( hProcess , pnh , & inh64 , sizeof ( inh64 ) , NULL ) ) {
DETOUR_TRACE ( ( " WriteProcessMemory(inh@%p..%p) failed: % d \n " ,
DETOUR_TRACE ( ( " WriteProcessMemory(inh@%p..%p) failed: % lu \n " ,
pnh , pnh + sizeof ( inh64 ) , GetLastError ( ) ) ) ;
pnh , pnh + sizeof ( inh64 ) , GetLastError ( ) ) ) ;
return FALSE ;
return FALSE ;
}
}
@ -466,7 +608,7 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine,
inh64 . FileHeader . SizeOfOptionalHeader ;
inh64 . FileHeader . SizeOfOptionalHeader ;
cb = inh64 . FileHeader . NumberOfSections * sizeof ( IMAGE_SECTION_HEADER ) ;
cb = inh64 . FileHeader . NumberOfSections * sizeof ( IMAGE_SECTION_HEADER ) ;
if ( ! WriteProcessMemory ( hProcess , psects , & sects , cb , NULL ) ) {
if ( ! WriteProcessMemory ( hProcess , psects , & sects , cb , NULL ) ) {
DETOUR_TRACE ( ( " WriteProcessMemory(ish@%p..%p) failed: % d \n " ,
DETOUR_TRACE ( ( " WriteProcessMemory(ish@%p..%p) failed: % lu \n " ,
psects , psects + cb , GetLastError ( ) ) ) ;
psects , psects + cb , GetLastError ( ) ) ) ;
return FALSE ;
return FALSE ;
}
}
@ -478,12 +620,12 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine,
}
}
// Remove the import table.
// Remove the import table.
if ( der . pclr ! = NULL & & ( der . clr . Flags & 1 ) ) {
if ( der . pclr ! = NULL & & ( der . clr . Flags & COMIMAGE_FLAGS_ILONLY ) ) {
inh64 . IMPORT_DIRECTORY . VirtualAddress = 0 ;
inh64 . IMPORT_DIRECTORY . VirtualAddress = 0 ;
inh64 . IMPORT_DIRECTORY . Size = 0 ;
inh64 . IMPORT_DIRECTORY . Size = 0 ;
if ( ! WriteProcessMemory ( hProcess , pnh , & inh64 , sizeof ( inh64 ) , NULL ) ) {
if ( ! WriteProcessMemory ( hProcess , pnh , & inh64 , sizeof ( inh64 ) , NULL ) ) {
DETOUR_TRACE ( ( " WriteProcessMemory(inh@%p..%p) failed: % d \n " ,
DETOUR_TRACE ( ( " WriteProcessMemory(inh@%p..%p) failed: % lu \n " ,
pnh , pnh + sizeof ( inh64 ) , GetLastError ( ) ) ) ;
pnh , pnh + sizeof ( inh64 ) , GetLastError ( ) ) ) ;
return FALSE ;
return FALSE ;
}
}
@ -499,6 +641,37 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine,
}
}
# endif // DETOURS_64BIT
# endif // DETOURS_64BIT
typedef BOOL ( WINAPI * LPFN_ISWOW64PROCESS ) ( HANDLE , PBOOL ) ;
static BOOL IsWow64ProcessHelper ( HANDLE hProcess ,
PBOOL Wow64Process )
{
# ifdef _X86_
if ( Wow64Process = = NULL ) {
return FALSE ;
}
// IsWow64Process is not available on all supported versions of Windows.
//
HMODULE hKernel32 = LoadLibraryW ( L " KERNEL32.DLL " ) ;
if ( hKernel32 = = NULL ) {
DETOUR_TRACE ( ( " LoadLibraryW failed: %lu \n " , GetLastError ( ) ) ) ;
return FALSE ;
}
LPFN_ISWOW64PROCESS pfnIsWow64Process = ( LPFN_ISWOW64PROCESS ) GetProcAddress (
hKernel32 , " IsWow64Process " ) ;
if ( pfnIsWow64Process = = NULL ) {
DETOUR_TRACE ( ( " GetProcAddress failed: %lu \n " , GetLastError ( ) ) ) ;
return FALSE ;
}
return pfnIsWow64Process ( hProcess , Wow64Process ) ;
# else
return IsWow64Process ( hProcess , Wow64Process ) ;
# endif
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//
//
BOOL WINAPI DetourUpdateProcessWithDll ( _In_ HANDLE hProcess ,
BOOL WINAPI DetourUpdateProcessWithDll ( _In_ HANDLE hProcess ,
@ -507,18 +680,17 @@ BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess,
{
{
// Find the next memory region that contains a mapped PE image.
// Find the next memory region that contains a mapped PE image.
//
//
BOOL bHas64BitDll = FALSE ;
BOOL bHas32BitExe = FALSE ;
BOOL bIs32BitProcess ;
BOOL bIs32BitProcess ;
BOOL bIs64BitOS = FALSE ;
HMODULE hModule = NULL ;
HMODULE hModule = NULL ;
HMODULE hLast = NULL ;
HMODULE hLast = NULL ;
DETOUR_TRACE ( ( " DetourUpdateProcessWithDll(%p,dlls=% d )\n " , hProcess , nDlls ) ) ;
DETOUR_TRACE ( ( " DetourUpdateProcessWithDll(%p,dlls=% lu )\n " , hProcess , nDlls ) ) ;
for ( ; ; ) {
for ( ; ; ) {
IMAGE_NT_HEADERS32 inh ;
IMAGE_NT_HEADERS32 inh ;
if ( ( hLast = EnumerateModulesInProcess ( hProcess , hLast , & inh )) = = NULL ) {
if ( ( hLast = EnumerateModulesInProcess ( hProcess , hLast , & inh , NULL )) = = NULL ) {
break ;
break ;
}
}
@ -527,20 +699,8 @@ BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess,
if ( ( inh . FileHeader . Characteristics & IMAGE_FILE_DLL ) = = 0 ) {
if ( ( inh . FileHeader . Characteristics & IMAGE_FILE_DLL ) = = 0 ) {
hModule = hLast ;
hModule = hLast ;
if ( inh . OptionalHeader . Magic = = IMAGE_NT_OPTIONAL_HDR32_MAGIC
& & inh . FileHeader . Machine ! = 0 ) {
bHas32BitExe = TRUE ;
}
DETOUR_TRACE ( ( " %p Found EXE \n " , hLast ) ) ;
DETOUR_TRACE ( ( " %p Found EXE \n " , hLast ) ) ;
}
}
else {
if ( inh . OptionalHeader . Magic = = IMAGE_NT_OPTIONAL_HDR64_MAGIC
& & inh . FileHeader . Machine ! = 0 ) {
bHas64BitDll = TRUE ;
}
}
}
}
if ( hModule = = NULL ) {
if ( hModule = = NULL ) {
@ -548,19 +708,37 @@ BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess,
return FALSE ;
return FALSE ;
}
}
if ( ! bHas32BitExe ) {
// Determine if the target process is 32bit or 64bit. This is a two-stop process:
bIs32BitProcess = FALSE ;
//
}
// 1. First, determine if we're running on a 64bit operating system.
else if ( ! bHas64BitDll ) {
// - If we're running 64bit code (i.e. _WIN64 is defined), this is trivially true.
bIs32BitProcess = TRUE ;
// - If we're running 32bit code (i.e. _WIN64 is not defined), test if
// we're running under Wow64. If so, it implies that the operating system
// is 64bit.
//
# ifdef _WIN64
bIs64BitOS = TRUE ;
# else
if ( ! IsWow64ProcessHelper ( GetCurrentProcess ( ) , & bIs64BitOS ) ) {
return FALSE ;
}
}
else {
# endif
if ( ! IsWow64Process ( hProcess , & bIs32BitProcess ) ) {
// 2. With the operating system bitness known, we can now consider the target process:
// - If we're running on a 64bit OS, the target process is 32bit in case
// it is running under Wow64. Otherwise, it's 64bit, running natively
// (without Wow64).
// - If we're running on a 32bit OS, the target process must be 32bit, too.
//
if ( bIs64BitOS ) {
if ( ! IsWow64ProcessHelper ( hProcess , & bIs32BitProcess ) ) {
return FALSE ;
return FALSE ;
}
}
} else {
bIs32BitProcess = TRUE ;
}
}
DETOUR_TRACE ( ( " 32BitExe=%d 32BitProcess \n " , bHas32BitExe , bIs32BitProcess ) ) ;
DETOUR_TRACE ( ( " 32Bit Process=%d \n " , bIs32BitProcess ) ) ;
return DetourUpdateProcessWithDllEx ( hProcess ,
return DetourUpdateProcessWithDllEx ( hProcess ,
hModule ,
hModule ,
@ -579,11 +757,11 @@ BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess,
//
//
BOOL bIs32BitExe = FALSE ;
BOOL bIs32BitExe = FALSE ;
DETOUR_TRACE ( ( " DetourUpdateProcessWithDllEx(%p,%p,dlls=% d )\n " , hProcess , hModule , nDlls ) ) ;
DETOUR_TRACE ( ( " DetourUpdateProcessWithDllEx(%p,%p,dlls=% lu )\n " , hProcess , hModule , nDlls ) ) ;
IMAGE_NT_HEADERS32 inh ;
IMAGE_NT_HEADERS32 inh ;
if ( hModule = = NULL | | LoadNtHeaderFromProcess ( hProcess , hModule , & inh ) = = NULL ) {
if ( hModule = = NULL | | ! LoadNtHeaderFromProcess ( hProcess , hModule , & inh ) ) {
SetLastError ( ERROR_INVALID_OPERATION ) ;
SetLastError ( ERROR_INVALID_OPERATION ) ;
return FALSE ;
return FALSE ;
}
}
@ -594,7 +772,7 @@ BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess,
bIs32BitExe = TRUE ;
bIs32BitExe = TRUE ;
}
}
DETOUR_TRACE ( ( " 32BitExe=%d 32BitProcess \n " , bIs32BitExe , bIs32BitProcess ) ) ;
DETOUR_TRACE ( ( " 32BitExe=%d \n " , bIs32BitExe ) ) ;
if ( hModule = = NULL ) {
if ( hModule = = NULL ) {
SetLastError ( ERROR_INVALID_OPERATION ) ;
SetLastError ( ERROR_INVALID_OPERATION ) ;
@ -613,8 +791,8 @@ BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess,
// Try to convert a neutral 32-bit managed binary to a 64-bit managed binary.
// Try to convert a neutral 32-bit managed binary to a 64-bit managed binary.
if ( bIs32BitExe & & ! bIs32BitProcess ) {
if ( bIs32BitExe & & ! bIs32BitProcess ) {
if ( ! der . pclr // Native binary
if ( ! der . pclr // Native binary
| | ( der . clr . Flags & 1 ) = = 0 // Or mixed-mode MSIL
| | ( der . clr . Flags & COMIMAGE_FLAGS_ILONLY ) = = 0 // Or mixed-mode MSIL
| | ( der . clr . Flags & 2 ) ! = 0 ) { // Or 32BIT Required MSIL
| | ( der . clr . Flags & COMIMAGE_FLAGS_32BITREQUIRED ) ! = 0 ) { // Or 32BIT Required MSIL
SetLastError ( ERROR_INVALID_HANDLE ) ;
SetLastError ( ERROR_INVALID_HANDLE ) ;
return FALSE ;
return FALSE ;
@ -677,30 +855,30 @@ BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess,
if ( der . pclr ! = NULL ) {
if ( der . pclr ! = NULL ) {
DETOUR_CLR_HEADER clr ;
DETOUR_CLR_HEADER clr ;
CopyMemory ( & clr , & der . clr , sizeof ( clr ) ) ;
CopyMemory ( & clr , & der . clr , sizeof ( clr ) ) ;
clr . Flags & = 0xfffffffe ; // Clear the IL_ONLY flag.
clr . Flags & = ~ COMIMAGE_FLAGS_ILONLY ; // Clear the IL_ONLY flag.
DWORD dwProtect ;
DWORD dwProtect ;
if ( ! DetourVirtualProtectSameExecuteEx ( hProcess , der . pclr , sizeof ( clr ) , PAGE_READWRITE , & dwProtect ) ) {
if ( ! DetourVirtualProtectSameExecuteEx ( hProcess , der . pclr , sizeof ( clr ) , PAGE_READWRITE , & dwProtect ) ) {
DETOUR_TRACE ( ( " VirtualProtectEx(clr) write failed: % d \n " , GetLastError ( ) ) ) ;
DETOUR_TRACE ( ( " VirtualProtectEx(clr) write failed: % lu \n " , GetLastError ( ) ) ) ;
return FALSE ;
return FALSE ;
}
}
if ( ! WriteProcessMemory ( hProcess , der . pclr , & clr , sizeof ( clr ) , NULL ) ) {
if ( ! WriteProcessMemory ( hProcess , der . pclr , & clr , sizeof ( clr ) , NULL ) ) {
DETOUR_TRACE ( ( " WriteProcessMemory(clr) failed: % d \n " , GetLastError ( ) ) ) ;
DETOUR_TRACE ( ( " WriteProcessMemory(clr) failed: % lu \n " , GetLastError ( ) ) ) ;
return FALSE ;
return FALSE ;
}
}
if ( ! VirtualProtectEx ( hProcess , der . pclr , sizeof ( clr ) , dwProtect , & dwProtect ) ) {
if ( ! VirtualProtectEx ( hProcess , der . pclr , sizeof ( clr ) , dwProtect , & dwProtect ) ) {
DETOUR_TRACE ( ( " VirtualProtectEx(clr) restore failed: % d \n " , GetLastError ( ) ) ) ;
DETOUR_TRACE ( ( " VirtualProtectEx(clr) restore failed: % lu \n " , GetLastError ( ) ) ) ;
return FALSE ;
return FALSE ;
}
}
DETOUR_TRACE ( ( " CLR: %p..%p \n " , der . pclr , der . pclr + der . cbclr ) ) ;
DETOUR_TRACE ( ( " CLR: %p..%p \n " , der . pclr , der . pclr + der . cbclr ) ) ;
# if DETOURS_64BIT
# if DETOURS_64BIT
if ( der . clr . Flags & 0x2 ) { // Is the 32BIT Required Flag set?
if ( der . clr . Flags & COMIMAGE_FLAGS_32BITREQUIRED ) { // Is the 32BIT Required Flag set?
// X64 never gets here because the process appears as a WOW64 process.
// X64 never gets here because the process appears as a WOW64 process.
// However, on IA64, it doesn't appear to be a WOW process.
// However, on IA64, it doesn't appear to be a WOW process.
DETOUR_TRACE ( ( " CLR Requires 32-bit \n " , der . pclr , der . pclr + der . cbclr )) ;
DETOUR_TRACE ( ( " CLR Requires 32-bit \n " )) ;
SetLastError ( ERROR_INVALID_HANDLE ) ;
SetLastError ( ERROR_INVALID_HANDLE ) ;
return FALSE ;
return FALSE ;
}
}
@ -710,7 +888,7 @@ BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess,
//////////////////////////////// Save the undo data to the target process.
//////////////////////////////// Save the undo data to the target process.
//
//
if ( ! DetourCopyPayloadToProcess ( hProcess , DETOUR_EXE_RESTORE_GUID , & der , sizeof ( der ) ) ) {
if ( ! DetourCopyPayloadToProcess ( hProcess , DETOUR_EXE_RESTORE_GUID , & der , sizeof ( der ) ) ) {
DETOUR_TRACE ( ( " DetourCopyPayloadToProcess failed: % d \n " , GetLastError ( ) ) ) ;
DETOUR_TRACE ( ( " DetourCopyPayloadToProcess failed: % lu \n " , GetLastError ( ) ) ) ;
return FALSE ;
return FALSE ;
}
}
return TRUE ;
return TRUE ;
@ -834,9 +1012,23 @@ BOOL WINAPI DetourCreateProcessWithDllW(_In_opt_ LPCWSTR lpApplicationName,
BOOL WINAPI DetourCopyPayloadToProcess ( _In_ HANDLE hProcess ,
BOOL WINAPI DetourCopyPayloadToProcess ( _In_ HANDLE hProcess ,
_In_ REFGUID rguid ,
_In_ REFGUID rguid ,
_In_reads_bytes_ ( cbData ) PVOID pvData ,
_In_reads_bytes_ ( cbData ) LPCVOID pvData ,
_In_ DWORD cbData )
{
return DetourCopyPayloadToProcessEx ( hProcess , rguid , pvData , cbData ) ! = NULL ;
}
_Success_ ( return ! = NULL )
PVOID WINAPI DetourCopyPayloadToProcessEx ( _In_ HANDLE hProcess ,
_In_ REFGUID rguid ,
_In_reads_bytes_ ( cbData ) LPCVOID pvData ,
_In_ DWORD cbData )
_In_ DWORD cbData )
{
{
if ( hProcess = = NULL ) {
SetLastError ( ERROR_INVALID_HANDLE ) ;
return NULL ;
}
DWORD cbTotal = ( sizeof ( IMAGE_DOS_HEADER ) +
DWORD cbTotal = ( sizeof ( IMAGE_DOS_HEADER ) +
sizeof ( IMAGE_NT_HEADERS ) +
sizeof ( IMAGE_NT_HEADERS ) +
sizeof ( IMAGE_SECTION_HEADER ) +
sizeof ( IMAGE_SECTION_HEADER ) +
@ -847,10 +1039,15 @@ BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess,
PBYTE pbBase = ( PBYTE ) VirtualAllocEx ( hProcess , NULL , cbTotal ,
PBYTE pbBase = ( PBYTE ) VirtualAllocEx ( hProcess , NULL , cbTotal ,
MEM_COMMIT , PAGE_READWRITE ) ;
MEM_COMMIT , PAGE_READWRITE ) ;
if ( pbBase = = NULL ) {
if ( pbBase = = NULL ) {
DETOUR_TRACE ( ( " VirtualAllocEx(% d) failed: %d \n " , cbTotal , GetLastError ( ) ) ) ;
DETOUR_TRACE ( ( " VirtualAllocEx(% lu) failed: %lu \n " , cbTotal , GetLastError ( ) ) ) ;
return FALSE ;
return NULL ;
}
}
// As you can see in the following code,
// the memory layout of the payload range "[pbBase, pbBase+cbTotal]" is a PE executable file,
// so DetourFreePayload can use "DetourGetContainingModule(Payload pointer)" to get the above "pbBase" pointer,
// pbBase: the memory block allocated by VirtualAllocEx will be released in DetourFreePayload by VirtualFree.
PBYTE pbTarget = pbBase ;
PBYTE pbTarget = pbBase ;
IMAGE_DOS_HEADER idh ;
IMAGE_DOS_HEADER idh ;
IMAGE_NT_HEADERS inh ;
IMAGE_NT_HEADERS inh ;
@ -864,8 +1061,8 @@ BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess,
idh . e_lfanew = sizeof ( idh ) ;
idh . e_lfanew = sizeof ( idh ) ;
if ( ! WriteProcessMemory ( hProcess , pbTarget , & idh , sizeof ( idh ) , & cbWrote ) | |
if ( ! WriteProcessMemory ( hProcess , pbTarget , & idh , sizeof ( idh ) , & cbWrote ) | |
cbWrote ! = sizeof ( idh ) ) {
cbWrote ! = sizeof ( idh ) ) {
DETOUR_TRACE ( ( " WriteProcessMemory(idh) failed: % d \n " , GetLastError ( ) ) ) ;
DETOUR_TRACE ( ( " WriteProcessMemory(idh) failed: % lu \n " , GetLastError ( ) ) ) ;
return FALSE ;
return NULL ;
}
}
pbTarget + = sizeof ( idh ) ;
pbTarget + = sizeof ( idh ) ;
@ -877,7 +1074,7 @@ BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess,
inh . OptionalHeader . Magic = IMAGE_NT_OPTIONAL_HDR_MAGIC ;
inh . OptionalHeader . Magic = IMAGE_NT_OPTIONAL_HDR_MAGIC ;
if ( ! WriteProcessMemory ( hProcess , pbTarget , & inh , sizeof ( inh ) , & cbWrote ) | |
if ( ! WriteProcessMemory ( hProcess , pbTarget , & inh , sizeof ( inh ) , & cbWrote ) | |
cbWrote ! = sizeof ( inh ) ) {
cbWrote ! = sizeof ( inh ) ) {
return FALSE ;
return NULL ;
}
}
pbTarget + = sizeof ( inh ) ;
pbTarget + = sizeof ( inh ) ;
@ -889,7 +1086,7 @@ BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess,
cbData ) ;
cbData ) ;
if ( ! WriteProcessMemory ( hProcess , pbTarget , & ish , sizeof ( ish ) , & cbWrote ) | |
if ( ! WriteProcessMemory ( hProcess , pbTarget , & ish , sizeof ( ish ) , & cbWrote ) | |
cbWrote ! = sizeof ( ish ) ) {
cbWrote ! = sizeof ( ish ) ) {
return FALSE ;
return NULL ;
}
}
pbTarget + = sizeof ( ish ) ;
pbTarget + = sizeof ( ish ) ;
@ -902,7 +1099,7 @@ BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess,
cbData ) ;
cbData ) ;
if ( ! WriteProcessMemory ( hProcess , pbTarget , & dsh , sizeof ( dsh ) , & cbWrote ) | |
if ( ! WriteProcessMemory ( hProcess , pbTarget , & dsh , sizeof ( dsh ) , & cbWrote ) | |
cbWrote ! = sizeof ( dsh ) ) {
cbWrote ! = sizeof ( dsh ) ) {
return FALSE ;
return NULL ;
}
}
pbTarget + = sizeof ( dsh ) ;
pbTarget + = sizeof ( dsh ) ;
@ -912,19 +1109,20 @@ BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess,
dsr . guid = rguid ;
dsr . guid = rguid ;
if ( ! WriteProcessMemory ( hProcess , pbTarget , & dsr , sizeof ( dsr ) , & cbWrote ) | |
if ( ! WriteProcessMemory ( hProcess , pbTarget , & dsr , sizeof ( dsr ) , & cbWrote ) | |
cbWrote ! = sizeof ( dsr ) ) {
cbWrote ! = sizeof ( dsr ) ) {
return FALSE ;
return NULL ;
}
}
pbTarget + = sizeof ( dsr ) ;
pbTarget + = sizeof ( dsr ) ;
if ( ! WriteProcessMemory ( hProcess , pbTarget , pvData , cbData , & cbWrote ) | |
if ( ! WriteProcessMemory ( hProcess , pbTarget , pvData , cbData , & cbWrote ) | |
cbWrote ! = cbData ) {
cbWrote ! = cbData ) {
return FALSE ;
return NULL ;
}
}
pbTarget + = cbData ;
DETOUR_TRACE ( ( " Copied %d byte payload into target process at %p \n " ,
DETOUR_TRACE ( ( " Copied %lu byte payload into target process at %p \n " ,
cbTotal , pbTarget - cbTotal ) ) ;
cbData , pbTarget ) ) ;
return TRUE ;
SetLastError ( NO_ERROR ) ;
return pbTarget ;
}
}
static BOOL s_fSearchedForHelper = FALSE ;
static BOOL s_fSearchedForHelper = FALSE ;
@ -949,7 +1147,7 @@ VOID CALLBACK DetourFinishHelperProcess(_In_ HWND,
hProcess = OpenProcess ( PROCESS_ALL_ACCESS , FALSE , s_pHelper - > pid ) ;
hProcess = OpenProcess ( PROCESS_ALL_ACCESS , FALSE , s_pHelper - > pid ) ;
if ( hProcess = = NULL ) {
if ( hProcess = = NULL ) {
DETOUR_TRACE ( ( " OpenProcess(pid=% d) failed: %d \n " ,
DETOUR_TRACE ( ( " OpenProcess(pid=% lu) failed: %lu \n " ,
s_pHelper - > pid , GetLastError ( ) ) ) ;
s_pHelper - > pid , GetLastError ( ) ) ) ;
Result = 9901 ;
Result = 9901 ;
goto Cleanup ;
goto Cleanup ;
@ -970,7 +1168,7 @@ VOID CALLBACK DetourFinishHelperProcess(_In_ HWND,
}
}
if ( ! DetourUpdateProcessWithDll ( hProcess , rlpDlls , s_pHelper - > nDlls ) ) {
if ( ! DetourUpdateProcessWithDll ( hProcess , rlpDlls , s_pHelper - > nDlls ) ) {
DETOUR_TRACE ( ( " DetourUpdateProcessWithDll(pid=% d) failed: %d \n " ,
DETOUR_TRACE ( ( " DetourUpdateProcessWithDll(pid=% lu) failed: %lu \n " ,
s_pHelper - > pid , GetLastError ( ) ) ) ;
s_pHelper - > pid , GetLastError ( ) ) ) ;
Result = 9903 ;
Result = 9903 ;
goto Cleanup ;
goto Cleanup ;
@ -983,6 +1181,15 @@ VOID CALLBACK DetourFinishHelperProcess(_In_ HWND,
rlpDlls = NULL ;
rlpDlls = NULL ;
}
}
// Note: s_pHelper is allocated as part of injecting the payload in DetourCopyPayloadToProcess(..),
// it's a fake section and not data allocated by the system PE loader.
// Delete the payload after execution to release the memory occupied by it
if ( s_pHelper ! = NULL ) {
DetourFreePayload ( s_pHelper ) ;
s_pHelper = NULL ;
}
ExitProcess ( Result ) ;
ExitProcess ( Result ) ;
}
}
@ -1146,7 +1353,7 @@ BOOL WINAPI DetourProcessViaHelperDllsA(_In_ DWORD dwTargetPid,
HRESULT hr ;
HRESULT hr ;
DWORD nLen = GetEnvironmentVariableA ( " WINDIR " , szExe , ARRAYSIZE ( szExe ) ) ;
DWORD nLen = GetEnvironmentVariableA ( " WINDIR " , szExe , ARRAYSIZE ( szExe ) ) ;
DETOUR_TRACE ( ( " DetourProcessViaHelperDlls(pid=% d,dlls=%d )\n " , dwTargetPid , nDlls ) ) ;
DETOUR_TRACE ( ( " DetourProcessViaHelperDlls(pid=% lu,dlls=%lu )\n " , dwTargetPid , nDlls ) ) ;
if ( nDlls < 1 | | nDlls > 4096 ) {
if ( nDlls < 1 | | nDlls > 4096 ) {
SetLastError ( ERROR_INVALID_PARAMETER ) ;
SetLastError ( ERROR_INVALID_PARAMETER ) ;
goto Cleanup ;
goto Cleanup ;
@ -1172,8 +1379,10 @@ BOOL WINAPI DetourProcessViaHelperDllsA(_In_ DWORD dwTargetPid,
goto Cleanup ;
goto Cleanup ;
}
}
//for East Asia languages and so on, like Chinese, print format with "%hs" can not work fine before user call _tsetlocale(LC_ALL,_T(".ACP"));
//so we can't use "%hs" in format string, because the dll that contain this code would inject to any process, even not call _tsetlocale(LC_ALL,_T(".ACP")) before
hr = StringCchPrintfA ( szCommand , ARRAYSIZE ( szCommand ) ,
hr = StringCchPrintfA ( szCommand , ARRAYSIZE ( szCommand ) ,
" rundll32.exe \" %hs \" ,#1 " , & helper - > rDlls [ 0 ] ) ;
" rundll32.exe \" % s\" ,#1 " , & helper - > rDlls [ 0 ] ) ;
if ( ! SUCCEEDED ( hr ) ) {
if ( ! SUCCEEDED ( hr ) ) {
goto Cleanup ;
goto Cleanup ;
}
}
@ -1189,7 +1398,7 @@ BOOL WINAPI DetourProcessViaHelperDllsA(_In_ DWORD dwTargetPid,
if ( ! DetourCopyPayloadToProcess ( pi . hProcess ,
if ( ! DetourCopyPayloadToProcess ( pi . hProcess ,
DETOUR_EXE_HELPER_GUID ,
DETOUR_EXE_HELPER_GUID ,
helper , helper - > cb ) ) {
helper , helper - > cb ) ) {
DETOUR_TRACE ( ( " DetourCopyPayloadToProcess failed: % d \n " , GetLastError ( ) ) ) ;
DETOUR_TRACE ( ( " DetourCopyPayloadToProcess failed: % lu \n " , GetLastError ( ) ) ) ;
TerminateProcess ( pi . hProcess , ~ 0u ) ;
TerminateProcess ( pi . hProcess , ~ 0u ) ;
CloseHandle ( pi . hProcess ) ;
CloseHandle ( pi . hProcess ) ;
CloseHandle ( pi . hThread ) ;
CloseHandle ( pi . hThread ) ;
@ -1206,13 +1415,13 @@ BOOL WINAPI DetourProcessViaHelperDllsA(_In_ DWORD dwTargetPid,
CloseHandle ( pi . hThread ) ;
CloseHandle ( pi . hThread ) ;
if ( dwResult ! = 0 ) {
if ( dwResult ! = 0 ) {
DETOUR_TRACE ( ( " Rundll32.exe failed: result=% d \n " , dwResult ) ) ;
DETOUR_TRACE ( ( " Rundll32.exe failed: result=% lu \n " , dwResult ) ) ;
goto Cleanup ;
goto Cleanup ;
}
}
Result = TRUE ;
Result = TRUE ;
}
}
else {
else {
DETOUR_TRACE ( ( " CreateProcess failed: % d \n " , GetLastError ( ) ) ) ;
DETOUR_TRACE ( ( " CreateProcess failed: % lu \n " , GetLastError ( ) ) ) ;
goto Cleanup ;
goto Cleanup ;
}
}
@ -1240,9 +1449,11 @@ BOOL WINAPI DetourProcessViaHelperDllsW(_In_ DWORD dwTargetPid,
WCHAR szCommand [ MAX_PATH ] ;
WCHAR szCommand [ MAX_PATH ] ;
PDETOUR_EXE_HELPER helper = NULL ;
PDETOUR_EXE_HELPER helper = NULL ;
HRESULT hr ;
HRESULT hr ;
WCHAR szDllName [ MAX_PATH ] ;
int cchWrittenWideChar ;
DWORD nLen = GetEnvironmentVariableW ( L " WINDIR " , szExe , ARRAYSIZE ( szExe ) ) ;
DWORD nLen = GetEnvironmentVariableW ( L " WINDIR " , szExe , ARRAYSIZE ( szExe ) ) ;
DETOUR_TRACE ( ( " DetourProcessViaHelperDlls(pid=% d,dlls=%d )\n " , dwTargetPid , nDlls ) ) ;
DETOUR_TRACE ( ( " DetourProcessViaHelperDlls(pid=% lu,dlls=%lu )\n " , dwTargetPid , nDlls ) ) ;
if ( nDlls < 1 | | nDlls > 4096 ) {
if ( nDlls < 1 | | nDlls > 4096 ) {
SetLastError ( ERROR_INVALID_PARAMETER ) ;
SetLastError ( ERROR_INVALID_PARAMETER ) ;
goto Cleanup ;
goto Cleanup ;
@ -1268,8 +1479,15 @@ BOOL WINAPI DetourProcessViaHelperDllsW(_In_ DWORD dwTargetPid,
goto Cleanup ;
goto Cleanup ;
}
}
//for East Asia languages and so on, like Chinese, print format with "%hs" can not work fine before user call _tsetlocale(LC_ALL,_T(".ACP"));
//so we can't use "%hs" in format string, because the dll that contain this code would inject to any process, even not call _tsetlocale(LC_ALL,_T(".ACP")) before
cchWrittenWideChar = MultiByteToWideChar ( CP_ACP , 0 , & helper - > rDlls [ 0 ] , - 1 , szDllName , ARRAYSIZE ( szDllName ) ) ;
if ( cchWrittenWideChar > = ARRAYSIZE ( szDllName ) | | cchWrittenWideChar < = 0 ) {
goto Cleanup ;
}
hr = StringCchPrintfW ( szCommand , ARRAYSIZE ( szCommand ) ,
hr = StringCchPrintfW ( szCommand , ARRAYSIZE ( szCommand ) ,
L " rundll32.exe \" %hs \" ,#1 " , & helper - > rDlls [ 0 ] ) ;
L " rundll32.exe \" % s\" ,#1 " , szDllName ) ;
if ( ! SUCCEEDED ( hr ) ) {
if ( ! SUCCEEDED ( hr ) ) {
goto Cleanup ;
goto Cleanup ;
}
}
@ -1285,15 +1503,13 @@ BOOL WINAPI DetourProcessViaHelperDllsW(_In_ DWORD dwTargetPid,
if ( ! DetourCopyPayloadToProcess ( pi . hProcess ,
if ( ! DetourCopyPayloadToProcess ( pi . hProcess ,
DETOUR_EXE_HELPER_GUID ,
DETOUR_EXE_HELPER_GUID ,
helper , helper - > cb ) ) {
helper , helper - > cb ) ) {
DETOUR_TRACE ( ( " DetourCopyPayloadToProcess failed: % d \n " , GetLastError ( ) ) ) ;
DETOUR_TRACE ( ( " DetourCopyPayloadToProcess failed: % lu \n " , GetLastError ( ) ) ) ;
TerminateProcess ( pi . hProcess , ~ 0u ) ;
TerminateProcess ( pi . hProcess , ~ 0u ) ;
CloseHandle ( pi . hProcess ) ;
CloseHandle ( pi . hProcess ) ;
CloseHandle ( pi . hThread ) ;
CloseHandle ( pi . hThread ) ;
goto Cleanup ;
goto Cleanup ;
}
}
ResumeThread ( pi . hThread ) ;
ResumeThread ( pi . hThread ) ;
ResumeThread ( pi . hThread ) ;
WaitForSingleObject ( pi . hProcess , INFINITE ) ;
WaitForSingleObject ( pi . hProcess , INFINITE ) ;
@ -1304,13 +1520,13 @@ BOOL WINAPI DetourProcessViaHelperDllsW(_In_ DWORD dwTargetPid,
CloseHandle ( pi . hThread ) ;
CloseHandle ( pi . hThread ) ;
if ( dwResult ! = 0 ) {
if ( dwResult ! = 0 ) {
DETOUR_TRACE ( ( " Rundll32.exe failed: result=% d \n " , dwResult ) ) ;
DETOUR_TRACE ( ( " Rundll32.exe failed: result=% lu \n " , dwResult ) ) ;
goto Cleanup ;
goto Cleanup ;
}
}
Result = TRUE ;
Result = TRUE ;
}
}
else {
else {
DETOUR_TRACE ( ( " CreateProcess failed: % d \n " , GetLastError ( ) ) ) ;
DETOUR_TRACE ( ( " CreateProcess failed: % lu \n " , GetLastError ( ) ) ) ;
goto Cleanup ;
goto Cleanup ;
}
}