Skip to content

Commit bc76883

Browse files
Fix: Delete payload after finish associated task (microsoft#143)
Delete the payload after finish associated task, and need change the `DETOUR_EXE_RESTORE_GUID`'s value for compatibility with these dlls that compiled by old version Detours. For example: - Create a pair of dlls named `dll_createwith_mysocks_32/64.dll`, their function is hooked `CreateProcess` to create any new process with it. - Create a 32bit exe(named exe_socks) use dll_createwith_mysocks_32.dll by PE import table. So it starts any process will with dll_createwith_mysocks_32/64.dll. - Now it starts a 32bit exe (named exe_vs), but exe_vs will load a dll (named dll_createwith_myluainject_32/64.dll) that build with detours and their function is hooked `CreateProcess` to create any new process with it. So if `exe_vs` starts a 64bit exe, `DetourCreateProcessXXX` API will only restore the first IAT which was modified by `dll_createwith_mysocks_32/64.dll`, and `dll_createwith_myluainject_32/64.dll` modified IAT will not restore. Because they create payload with the same GUID `DETOUR_EXE_RESTORE_GUID`, Detours will do restore with the first founded payload twice. To fix this we need to delete the payload after the associated task finishes, immediately. If we do this then the payload with GUID `DETOUR_EXE_RESTORE_GUID` can be used by the next dll that complied by Detours. And for compatible with these dlls that compiled by old version Detours which we don`t have source code to recompile these. So we need change `DETOUR_EXE_RESTORE_GUID`'s value to a new value, so even these dlls can not delete the payload, because we only search the new `DETOUR_EXE_RESTORE_GUID`'s value's payload, the old playload things will not executed by us.
1 parent 7b7977d commit bc76883

File tree

4 files changed

+77
-2
lines changed

4 files changed

+77
-2
lines changed

src/creatwth.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,6 +1043,11 @@ PVOID WINAPI DetourCopyPayloadToProcessEx(_In_ HANDLE hProcess,
10431043
return NULL;
10441044
}
10451045

1046+
// As you can see in the following code,
1047+
// the memory layout of the payload range "[pbBase, pbBase+cbTotal]" is a PE executable file,
1048+
// so DetourFreePayload can use "DetourGetContainingModule(Payload pointer)" to get the above "pbBase" pointer,
1049+
// pbBase: the memory block allocated by VirtualAllocEx will be released in DetourFreePayload by VirtualFree.
1050+
10461051
PBYTE pbTarget = pbBase;
10471052
IMAGE_DOS_HEADER idh;
10481053
IMAGE_NT_HEADERS inh;
@@ -1176,6 +1181,15 @@ VOID CALLBACK DetourFinishHelperProcess(_In_ HWND,
11761181
rlpDlls = NULL;
11771182
}
11781183

1184+
// Note: s_pHelper is allocated as part of injecting the payload in DetourCopyPayloadToProcess(..),
1185+
// it's a fake section and not data allocated by the system PE loader.
1186+
1187+
// Delete the payload after execution to release the memory occupied by it
1188+
if (s_pHelper != NULL) {
1189+
DetourFreePayload(s_pHelper);
1190+
s_pHelper = NULL;
1191+
}
1192+
11791193
ExitProcess(Result);
11801194
}
11811195

src/detours.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,27 @@
1818

1919
#define NOTHROW
2020

21+
//////////////////////////////////////////////////////////////////////////////
22+
//
23+
24+
#ifdef _DEBUG
25+
extern "C" IMAGE_DOS_HEADER __ImageBase;
26+
int Detour_AssertExprWithFunctionName(int reportType, const char* filename, int linenumber, const char* FunctionName, const char* msg)
27+
{
28+
int nRet = 0;
29+
DWORD dwLastError = GetLastError();
30+
CHAR szModuleNameWithFunctionName[MAX_PATH * 2];
31+
szModuleNameWithFunctionName[0] = 0;
32+
GetModuleFileNameA((HMODULE)&__ImageBase, szModuleNameWithFunctionName, ARRAYSIZE(szModuleNameWithFunctionName));
33+
StringCchCatNA(szModuleNameWithFunctionName, ARRAYSIZE(szModuleNameWithFunctionName), ",", ARRAYSIZE(szModuleNameWithFunctionName) - strlen(szModuleNameWithFunctionName) - 1);
34+
StringCchCatNA(szModuleNameWithFunctionName, ARRAYSIZE(szModuleNameWithFunctionName), FunctionName, ARRAYSIZE(szModuleNameWithFunctionName) - strlen(szModuleNameWithFunctionName) - 1);
35+
SetLastError(dwLastError);
36+
nRet = _CrtDbgReport(reportType, filename, linenumber, szModuleNameWithFunctionName, msg);
37+
SetLastError(dwLastError);
38+
return nRet;
39+
}
40+
#endif// _DEBUG
41+
2142
//////////////////////////////////////////////////////////////////////////////
2243
//
2344
struct _DETOUR_ALIGN

src/detours.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#include <intsafe.h>
4949
#pragma warning(pop)
5050
#endif
51+
#include <crtdbg.h>
5152

5253
// Allow Detours to cleanly compile with the MingW toolchain.
5354
//
@@ -624,6 +625,7 @@ PVOID WINAPI DetourFindPayloadEx(_In_ REFGUID rguid,
624625

625626
DWORD WINAPI DetourGetSizeOfPayloads(_In_opt_ HMODULE hModule);
626627

628+
BOOL WINAPI DetourFreePayload(_In_ PVOID pvData);
627629
///////////////////////////////////////////////// Persistent Binary Functions.
628630
//
629631

@@ -982,6 +984,21 @@ PDETOUR_SYM_INFO DetourLoadImageHlp(VOID);
982984
#endif
983985
#define _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS 1
984986

987+
#ifdef _DEBUG
988+
989+
int Detour_AssertExprWithFunctionName(int reportType, const char* filename, int linenumber, const char* FunctionName, const char* msg);
990+
991+
#define DETOUR_ASSERT_EXPR_WITH_FUNCTION(expr, msg) \
992+
(void) ((expr) || \
993+
(1 != Detour_AssertExprWithFunctionName(_CRT_ASSERT, __FILE__, __LINE__,__FUNCTION__, msg)) || \
994+
(_CrtDbgBreak(), 0))
995+
996+
#define DETOUR_ASSERT(expr) DETOUR_ASSERT_EXPR_WITH_FUNCTION((expr), #expr)
997+
998+
#else// _DEBUG
999+
#define DETOUR_ASSERT(expr)
1000+
#endif// _DEBUG
1001+
9851002
#ifndef DETOUR_TRACE
9861003
#if DETOUR_DEBUG
9871004
#define DETOUR_TRACE(x) printf x

src/modules.cpp

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
//////////////////////////////////////////////////////////////////////////////
2424
//
2525
const GUID DETOUR_EXE_RESTORE_GUID = {
26-
0x2ed7a3ff, 0x3339, 0x4a8d,
27-
{ 0x80, 0x5c, 0xd4, 0x98, 0x15, 0x3f, 0xc2, 0x8f }};
26+
0xbda26f34, 0xbc82, 0x4829,
27+
{ 0x9e, 0x64, 0x74, 0x2c, 0x4, 0xc8, 0x4f, 0xa0 } };
2828

2929
//////////////////////////////////////////////////////////////////////////////
3030
//
@@ -843,6 +843,24 @@ PVOID WINAPI DetourFindPayloadEx(_In_ REFGUID rguid,
843843
return NULL;
844844
}
845845

846+
BOOL WINAPI DetourFreePayload(_In_ PVOID pvData)
847+
{
848+
BOOL fSucceeded = FALSE;
849+
850+
// If you have any doubts about the following code, please refer to the comments in DetourCopyPayloadToProcess.
851+
HMODULE hModule = DetourGetContainingModule(pvData);
852+
DETOUR_ASSERT(hModule != NULL);
853+
if (hModule != NULL) {
854+
fSucceeded = VirtualFree(hModule, 0, MEM_RELEASE);
855+
DETOUR_ASSERT(fSucceeded);
856+
if (fSucceeded) {
857+
hModule = NULL;
858+
}
859+
}
860+
861+
return fSucceeded;
862+
}
863+
846864
BOOL WINAPI DetourRestoreAfterWithEx(_In_reads_bytes_(cbData) PVOID pvData,
847865
_In_ DWORD cbData)
848866
{
@@ -889,6 +907,11 @@ BOOL WINAPI DetourRestoreAfterWithEx(_In_reads_bytes_(cbData) PVOID pvData,
889907
}
890908
VirtualProtect(pder->pidh, pder->cbidh, dwPermIdh, &dwIgnore);
891909
}
910+
// Delete the payload after successful recovery to prevent repeated restore
911+
if (fSucceeded) {
912+
DetourFreePayload(pder);
913+
pder = NULL;
914+
}
892915
return fSucceeded;
893916
}
894917

0 commit comments

Comments
 (0)