diff --git a/.gitignore b/.gitignore index 1207e230..19ba5aa2 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,10 @@ include/ obj.* *.ipdb *.iobj +*.tlog +*.log +*.obj +*.user +*.recipe +/bin.* +*.vcxproj.FileListAbsolute.txt diff --git a/CREDITS.TXT b/CREDITS.TXT index a1226767..275b5f0a 100644 --- a/CREDITS.TXT +++ b/CREDITS.TXT @@ -3,6 +3,9 @@ The following individuals have helped identify specific bugs and improvements in Detours. The entire Detours community has benefited from their help. ============================================================================== +* Jay Krell: Identified error in DetourFindPayload that caused a + incorrect failure when pcbData is NULL. (Build_342) + * Jay Krell: Identified issue with VirtualSize == 0 files created in NT 3.1 images. (Build_339) diff --git a/samples/comeasy/wrotei.cpp b/samples/comeasy/wrotei.cpp index 7bd925d5..f2ceaccd 100644 --- a/samples/comeasy/wrotei.cpp +++ b/samples/comeasy/wrotei.cpp @@ -82,8 +82,8 @@ int WINAPI TimedEntryPoint(VOID) CreateStreamOnHGlobal(NULL, TRUE, &pStream); // Apply the detour to the vtable. - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); if (pStream != NULL) { RealIStreamWrite = pStream->lpVtbl->Write; DetourAttach(&(PVOID&)RealIStreamWrite, MineIStreamWrite); @@ -132,8 +132,8 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved) TrueEntryPoint = (int (WINAPI *)(VOID))DetourGetEntryPoint(NULL); RawEntryPoint = TrueEntryPoint; - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttach(&(PVOID&)TrueEntryPoint, TimedEntryPoint); error = DetourTransactionCommit(); @@ -147,8 +147,8 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved) } } else if (dwReason == DLL_PROCESS_DETACH) { - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); if (RealIStreamWrite != NULL) { DetourDetach(&(PVOID&)RealIStreamWrite, (PVOID)MineIStreamWrite); } diff --git a/samples/commem/commem.cpp b/samples/commem/commem.cpp index 67798438..6bd64f41 100644 --- a/samples/commem/commem.cpp +++ b/samples/commem/commem.cpp @@ -84,8 +84,8 @@ int main(int argc, char **argv) li.QuadPart = 0; hr = pStream->lpVtbl->Write(pStream, &ul, sizeof(ul), NULL); - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttach(&(PVOID&)RealIStreamWrite, MineIStreamWrite); DetourTransactionCommit(); @@ -94,8 +94,8 @@ int main(int argc, char **argv) li.QuadPart = 1; hr = pStream->lpVtbl->Write(pStream, &li, sizeof(li), NULL); - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourDetach(&(PVOID&)RealIStreamWrite, MineIStreamWrite); DetourTransactionCommit(); diff --git a/samples/common.mak b/samples/common.mak index aa63a156..821425a5 100644 --- a/samples/common.mak +++ b/samples/common.mak @@ -23,7 +23,7 @@ CLIB=/MT !ENDIF AFLAGS=/nologo /Zi /c /Fl -CFLAGS=/nologo /Zi $(CLIB) /Gm- /W4 /WX /we4777 /we4800 /Od +CFLAGS=/nologo /Zi $(CLIB) /Gm- /W4 /WX /we4777 /we4800 /Od /D__AUTO_CREATE_DETOUR_HEAP__ !IF $(DETOURS_SOURCE_BROWSING)==1 CFLAGS=$(CFLAGS) /FR @@ -80,7 +80,7 @@ LIBS = $(DEPS) !endif .rc{$(OBJD)}.res: - rc /nologo /DDETOURS_BITS=$(DETOURS_BITS) /fo$(@) /i$(INCD) $(*B).rc + rc /DDETOURS_BITS=$(DETOURS_BITS) /fo$(@) /i$(INCD) $(*B).rc ## ################################################################# End of File. diff --git a/samples/cping/Makefile b/samples/cping/Makefile index cc99a097..da5b3306 100644 --- a/samples/cping/Makefile +++ b/samples/cping/Makefile @@ -50,7 +50,7 @@ CPPFLAGS= !endif .rc{$(OBJD)}.res: - rc /nologo /Fo$@ .\$(*B).rc + rc /Fo$@ .\$(*B).rc ############################################################################## ## diff --git a/samples/cping/cping.cpp b/samples/cping/cping.cpp index 79a72f6e..52d3848e 100644 --- a/samples/cping/cping.cpp +++ b/samples/cping/cping.cpp @@ -723,8 +723,8 @@ LONG RerouteEntryPoints(VOID) ULONG)) DetourFindFunction("ntdll.dll", "NtDeviceIoControlFile")); - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttach(&(PVOID&)Real_NtWaitForSingleObject, Catch_NtWaitForSingleObject); diff --git a/samples/dtest/dtest.cpp b/samples/dtest/dtest.cpp index f7de56d1..53cfe804 100644 --- a/samples/dtest/dtest.cpp +++ b/samples/dtest/dtest.cpp @@ -505,16 +505,16 @@ int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR lpszCmdLine, int nCmd printf("Calling LocalTarget1 w/o detour\n"); LocalTarget1(1); - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttach(&(PVOID&)Trampoline_LocalTarget1, MyLocalTarget1); DetourTransactionCommit(); printf("Calling LocalTarget1 w/ detour\n"); LocalTarget1(2); - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttach(&(PVOID&)Trampoline_Target0, MyTarget0); DetourTransactionCommit(); @@ -523,8 +523,8 @@ int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR lpszCmdLine, int nCmd //dprintf("- Target0 :: %p\n", Target0); Target0(); - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttach(&(PVOID&)Trampoline_Target1, MyTarget1); DetourAttach(&(PVOID&)Trampoline_Target2, MyTarget2); DetourAttach(&(PVOID&)Trampoline_Target3, MyTarget3); @@ -595,8 +595,8 @@ int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR lpszCmdLine, int nCmd printf("Calling Target0 again with 1 detour.\n"); Target0(); - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttach(&(PVOID&)Trampoline_Target0_1, MyTarget0_1); DetourTransactionCommit(); @@ -605,8 +605,8 @@ int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR lpszCmdLine, int nCmd printf("Calling Target0 again with 2 detours.\n"); Target0(); - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttach(&(PVOID&)Trampoline_Target0_2, MyTarget0_2); DetourTransactionCommit(); @@ -616,8 +616,8 @@ int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR lpszCmdLine, int nCmd Target0(); - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttach(&(PVOID&)Trampoline_Target0_3, MyTarget0_3); DetourTransactionCommit(); @@ -626,8 +626,8 @@ int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR lpszCmdLine, int nCmd printf("Calling Target0 again with 4 detours.\n"); Target0(); - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourDetach(&(PVOID&)Trampoline_Target0, MyTarget0); DetourDetach(&(PVOID&)Trampoline_Target1, MyTarget1); DetourDetach(&(PVOID&)Trampoline_Target2, MyTarget2); diff --git a/samples/dynamic_alloc/main.cpp b/samples/dynamic_alloc/main.cpp index a61232f2..b6c0bb7b 100644 --- a/samples/dynamic_alloc/main.cpp +++ b/samples/dynamic_alloc/main.cpp @@ -22,6 +22,12 @@ #include #include +#if _MSC_VER <= 1600 +#define nullptr NULL +typedef unsigned int uint32_t; +typedef unsigned char uint8_t; +#endif + extern "C" { void *CodeTemplate(); void *CodeTemplate_End(); @@ -45,14 +51,17 @@ void *target_function() { // Helper function to sandwich a given function between `DetourTransactionBegin` // and `DetourTransactionCommit`/`DetourTransactionAbort`. -bool DetourTransaction(std::function callback) { - LONG status = DetourTransactionBegin(); +typedef bool (*callback_type)(PVOID* pdetour_target, PVOID detour_destination); +bool DetourTransaction(callback_type callback, PVOID* pdetour_target, PVOID detour_destination) { + DetourCreateHeap(TRUE); + LONG status = DetourTransactionBegin(TRUE); if (status != NO_ERROR) { Log("DetourTransactionBegin failed with %08x\n", status); return status == NO_ERROR; } + DetourUpdateAllOtherThreads(); - if (callback()) { + if (callback(pdetour_target, detour_destination)) { status = DetourTransactionCommit(); if (status != NO_ERROR) { Log("DetourTransactionCommit failed with %08x\n", status); @@ -73,7 +82,7 @@ bool DetourTransaction(std::function callback) { // This class manages one dynamically-allocated region that is allocated by // the Detours API `DetourAllocateRegionWithinJumpBounds`, to which we can // push binary data sequentially to use it as a detour function. -class CodeRegionFactory final { +class CodeRegionFactory /*final*/ { template static const T *at(const void *base, uint32_t offset) { return @@ -88,14 +97,24 @@ class CodeRegionFactory final { reinterpret_cast(base) + offset); } - void *region_ = nullptr; - uint8_t *current_ = nullptr, - *current_end_ = nullptr; + void *region_; + uint8_t *current_,*current_end_; public: + void Init() + { + region_ = nullptr; + current_ = nullptr; + current_end_ = nullptr; + } + CodeRegionFactory() + { + Init(); + } CodeRegionFactory(const void *source) { + Init(); DWORD new_region_size = 0; - auto new_region_address = + PVOID new_region_address = DetourAllocateRegionWithinJumpBounds(source, &new_region_size); if (new_region_address) { region_ = current_ = at(new_region_address, 0); @@ -117,55 +136,67 @@ class CodeRegionFactory final { // the start address of a copy in the region if succeeded. void *PushTemplate(const void *start, const void *end) { - auto diff = at(end, 0) - at(start, 0); + INT_PTR diff = at(end, 0) - at(start, 0); if (diff < 0 || current_ + diff > current_end_) return nullptr; - auto start_pos = current_; + uint8_t* start_pos = current_; memcpy(start_pos, start, diff); current_ += diff; return start_pos; } }; +static bool is_detoured = false; +bool callback_attach(PVOID* pdetour_target, PVOID detour_destination) { + PDETOUR_TRAMPOLINE trampoline = nullptr; + void* target = nullptr, + * detour = nullptr; + LONG status = DetourAttachEx(pdetour_target, + detour_destination, + &trampoline, + &target, + &detour); + if (status != NO_ERROR) { + Log("DetourAttachEx failed - %08x\n", status); + return false; + } + is_detoured = true; + std::cout + << "detour: " << target << " --> " << detour + << " (trampoline: " << trampoline << " )" + << std::endl; + return true; +} + +bool callback_detach(PVOID* pdetour_target, PVOID detour_destination) { + LONG status = DetourDetach(pdetour_target, detour_destination); + if (status != NO_ERROR) { + Log("DetourDetach failed - %08x\n", status); + return false; + } + return true; +} + int main(int, char**) { std::cout << "1. target_function() without Detour" << std::endl; - auto ret = target_function(); + void* ret = target_function(); std::cout << ret << std::endl; assert(!ret); CodeRegionFactory factory(target_function); - void *detour_destination, + void *detour_destination = nullptr, *detour_target = reinterpret_cast(target_function); // Fill the allocated page with as many instances as possible of the code // template, and pick the last instance - while (auto p = factory.PushTemplate(CodeTemplate, + while (void* p = factory.PushTemplate(CodeTemplate, CodeTemplate_End)) { detour_destination = p; } - bool is_detoured = false; - DetourTransaction([&]() { - PDETOUR_TRAMPOLINE trampoline = nullptr; - void *target = nullptr, - *detour = nullptr; - auto status = DetourAttachEx(&detour_target, - detour_destination, - &trampoline, - &target, - &detour); - if (status != NO_ERROR) { - Log("DetourAttachEx failed - %08x\n", status); - return false; - } - is_detoured = true; - std::cout - << "detour: " << target << " --> " << detour - << " (trampoline: " << trampoline << " )" - << std::endl; - return true; - }); + DetourCreateHeap(TRUE); + DetourTransaction(callback_attach, &detour_target, detour_destination); // Attach failed for some reason. Bail out. if (!is_detoured) @@ -176,14 +207,7 @@ int main(int, char**) { std::cout << ret << std::endl; assert(ret); // The return value is cracked by the detour function - DetourTransaction([&]() { - auto status = DetourDetach(&detour_target, detour_destination); - if (status != NO_ERROR) { - Log("DetourDetach failed - %08x\n", status); - return false; - } - return true; - }); + DetourTransaction(callback_detach, &detour_target, detour_destination); std::cout << "3. target_function() without Detour" << std::endl; ret = target_function(); diff --git a/samples/echo/echofx.cpp b/samples/echo/echofx.cpp index 73b5a7f3..93e91f45 100644 --- a/samples/echo/echofx.cpp +++ b/samples/echo/echofx.cpp @@ -32,8 +32,8 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved) " Starting.\n"); fflush(stdout); - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttach(&(PVOID&)Real_Echo, Mine_Echo); error = DetourTransactionCommit(); @@ -47,8 +47,8 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved) } } else if (dwReason == DLL_PROCESS_DETACH) { - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourDetach(&(PVOID&)Real_Echo, Mine_Echo); error = DetourTransactionCommit(); diff --git a/samples/excep/firstexc.cpp b/samples/excep/firstexc.cpp index 4222ba89..ee46e93b 100644 --- a/samples/excep/firstexc.cpp +++ b/samples/excep/firstexc.cpp @@ -176,8 +176,8 @@ DetourFirstChanceExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER pNewFirstChanceFil (VOID (NTAPI *)(IN PEXCEPTION_RECORD, IN PCONTEXT)) DetourFindFunction("ntdll.dll", "KiUserExceptionDispatcher"); - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttach(&(PVOID&)Real_KiUserExceptionDispatcher, Detour_KiUserExceptionDispatcher); DetourTransactionCommit(); diff --git a/samples/findfunc/extend.cpp b/samples/findfunc/extend.cpp index 744a3abe..d3eeea3a 100644 --- a/samples/findfunc/extend.cpp +++ b/samples/findfunc/extend.cpp @@ -51,8 +51,8 @@ static int WINAPI ExtendEntryPoint() TrueTarget = (DWORD (WINAPI *)(DWORD)) DetourFindFunction("target" DETOURS_STRINGIFY(DETOURS_BITS) ".dll", "Target"); - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttach(&(PVOID&)TrueTarget, Extend); error = DetourTransactionCommit(); @@ -72,8 +72,8 @@ static int WINAPI ExtendEntryPoint() printf("extend" DETOURS_STRINGIFY(DETOURS_BITS) ".dll: TrueHidden = %p (error = %ld)\n", TrueHidden, error); } - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttach(&(PVOID&)TrueHidden, Intern); error = DetourTransactionCommit(); @@ -111,8 +111,8 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved) TrueEntryPoint = (int (WINAPI *)())DetourGetEntryPoint(NULL); - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttach(&(PVOID&)TrueEntryPoint, ExtendEntryPoint); error = DetourTransactionCommit(); @@ -124,8 +124,8 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved) } } else if (dwReason == DLL_PROCESS_DETACH) { - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); // Detach functions found from the export table. if (TrueTarget != NULL) { diff --git a/samples/member/member.cpp b/samples/member/member.cpp index 585ef98a..6842fbeb 100644 --- a/samples/member/member.cpp +++ b/samples/member/member.cpp @@ -86,8 +86,8 @@ int main(int argc, char **argv) printf("\n"); - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttach(&(PVOID&)CDetour::Real_Target, *(PBYTE*)&pfMine); diff --git a/samples/opengl/ogldet.cpp b/samples/opengl/ogldet.cpp index b1659d9c..be0b56c3 100644 --- a/samples/opengl/ogldet.cpp +++ b/samples/opengl/ogldet.cpp @@ -42,8 +42,8 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved) " Starting.\n"); fflush(stdout); - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttach(&(PVOID&)trueGlFinish, hookedGlFinish); error = DetourTransactionCommit(); @@ -57,8 +57,8 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved) } } else if (dwReason == DLL_PROCESS_DETACH) { - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourDetach(&(PVOID&)trueGlFinish, hookedGlFinish); error = DetourTransactionCommit(); diff --git a/samples/region/region.cpp b/samples/region/region.cpp index 976cef15..d7eba25a 100644 --- a/samples/region/region.cpp +++ b/samples/region/region.cpp @@ -33,8 +33,8 @@ PVOID AttachAndDetach(DWORD dwMilliseconds) LONG error; PVOID trampoline; - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttach(&(PVOID&)TrueSleepEx, LoudSleepEx); error = DetourTransactionCommit(); @@ -47,8 +47,8 @@ PVOID AttachAndDetach(DWORD dwMilliseconds) Sleep(dwMilliseconds); printf("\n"); - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourDetach(&(PVOID&)TrueSleepEx, LoudSleepEx); error = DetourTransactionCommit(); diff --git a/samples/simple/simple.cpp b/samples/simple/simple.cpp index bc902f18..37924a06 100644 --- a/samples/simple/simple.cpp +++ b/samples/simple/simple.cpp @@ -45,8 +45,8 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved) " Starting.\n"); fflush(stdout); - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttach(&(PVOID&)TrueSleepEx, TimedSleepEx); error = DetourTransactionCommit(); @@ -60,8 +60,8 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved) } } else if (dwReason == DLL_PROCESS_DETACH) { - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourDetach(&(PVOID&)TrueSleepEx, TimedSleepEx); error = DetourTransactionCommit(); diff --git a/samples/slept/dslept.cpp b/samples/slept/dslept.cpp index 39298209..09e7a4e7 100644 --- a/samples/slept/dslept.cpp +++ b/samples/slept/dslept.cpp @@ -53,8 +53,8 @@ int WINAPI TimedEntryPoint(VOID) TrueSleepEx = (DWORD (WINAPI *)(DWORD, BOOL)) DetourFindFunction("kernel32.dll", "SleepEx"); - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttach(&(PVOID&)TrueSleepEx, TimedSleepEx); error = DetourTransactionCommit(); @@ -104,8 +104,8 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved) Verify("EntryPoint", RawEntryPoint); - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttach(&(PVOID&)TrueEntryPoint, TimedEntryPoint); error = DetourTransactionCommit(); @@ -122,8 +122,8 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved) } } else if (dwReason == DLL_PROCESS_DETACH) { - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); if (TrueSleepEx != NULL) { DetourDetach(&(PVOID&)TrueSleepEx, (PVOID)TimedSleepEx); } diff --git a/samples/slept/sleepbed.cpp b/samples/slept/sleepbed.cpp index 49b7934d..c0e57ee9 100644 --- a/samples/slept/sleepbed.cpp +++ b/samples/slept/sleepbed.cpp @@ -57,8 +57,8 @@ int __cdecl main(void) printf("\n"); fflush(stdout); - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttach(&(PVOID&)TrueSleepEx, TimedSleepEx); error = DetourTransactionCommit(); @@ -88,8 +88,8 @@ int __cdecl main(void) UntimedSleepEx(1000, false); printf("sleepbed.exe: Done sleeping.\n\n"); - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourDetach(&(PVOID&)TrueSleepEx, TimedSleepEx); error = DetourTransactionCommit(); printf("sleepbed.exe: Removed SleepEx() detour (%d), slept %ld ticks.\n", diff --git a/samples/slept/slept.cpp b/samples/slept/slept.cpp index 5903295a..6358f581 100644 --- a/samples/slept/slept.cpp +++ b/samples/slept/slept.cpp @@ -100,8 +100,8 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved) printf("\n"); fflush(stdout); - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttach(&(PVOID&)TrueSleepEx, TimedSleepEx); error = DetourTransactionCommit(); @@ -115,8 +115,8 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved) } } else if (dwReason == DLL_PROCESS_DETACH) { - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourDetach(&(PVOID&)TrueSleepEx, TimedSleepEx); error = DetourTransactionCommit(); printf("slept" DETOURS_STRINGIFY(DETOURS_BITS) ".dll: " diff --git a/samples/talloc/talloc.cpp b/samples/talloc/talloc.cpp index 85eb6b32..99f3cc27 100644 --- a/samples/talloc/talloc.cpp +++ b/samples/talloc/talloc.cpp @@ -409,8 +409,8 @@ int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR lpszCmdLine, int nCmd Reserve(Dll5 - 0x7ff00000, 0x7ff00000); Reserve(Dll9 + DllSize, 0x7fe00000); - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttach(&(PVOID&)TrueDll1Function, MineDll1Function); error = DetourTransactionCommit(); if (error != NO_ERROR) { @@ -419,64 +419,64 @@ int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR lpszCmdLine, int nCmd exit(1); } - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttach(&(PVOID&)TrueDll2Function, MineDll2Function); error = DetourTransactionCommit(); if (error != NO_ERROR) { goto failed; } - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttach(&(PVOID&)TrueDll3Function, MineDll3Function); error = DetourTransactionCommit(); if (error != NO_ERROR) { goto failed; } - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttach(&(PVOID&)TrueDll4Function, MineDll4Function); error = DetourTransactionCommit(); if (error != NO_ERROR) { goto failed; } - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttach(&(PVOID&)TrueDll5Function, MineDll5Function); error = DetourTransactionCommit(); if (error != NO_ERROR) { goto failed; } - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttach(&(PVOID&)TrueDll6Function, MineDll6Function); error = DetourTransactionCommit(); if (error != NO_ERROR) { goto failed; } - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttach(&(PVOID&)TrueDll7Function, MineDll7Function); error = DetourTransactionCommit(); if (error != NO_ERROR) { goto failed; } - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttach(&(PVOID&)TrueDll8Function, MineDll8Function); error = DetourTransactionCommit(); if (error != NO_ERROR) { goto failed; } - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttach(&(PVOID&)TrueDll9Function, MineDll9Function); error = DetourTransactionCommit(); if (error != NO_ERROR) { @@ -514,8 +514,8 @@ int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR lpszCmdLine, int nCmd Dll8Function(10); Dll9Function(10); - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourDetach(&(PVOID&)TrueDll1Function, MineDll1Function); DetourDetach(&(PVOID&)TrueDll2Function, MineDll2Function); DetourDetach(&(PVOID&)TrueDll3Function, MineDll3Function); diff --git a/samples/traceapi/_win32.cpp b/samples/traceapi/_win32.cpp index f28daf3f..487918d6 100644 --- a/samples/traceapi/_win32.cpp +++ b/samples/traceapi/_win32.cpp @@ -33705,8 +33705,8 @@ VOID DetDetach(PVOID *ppvReal, PVOID pvMine, PCHAR psz) LONG AttachDetours(VOID) { - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); // For this many APIs, we'll ignore one or two can't be detoured. DetourSetIgnoreTooSmall(TRUE); @@ -35386,8 +35386,8 @@ LONG AttachDetours(VOID) LONG DetachDetours(VOID) { - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); // For this many APIs, we'll ignore one or two can't be detoured. DetourSetIgnoreTooSmall(TRUE); diff --git a/samples/tracebld/trcbld.cpp b/samples/tracebld/trcbld.cpp index 0573fd95..b4e20ca6 100644 --- a/samples/tracebld/trcbld.cpp +++ b/samples/tracebld/trcbld.cpp @@ -3739,8 +3739,8 @@ DWORD CDECL Mine_wdupenv_s(PWCHAR *ppBuffer, DWORD *pcBuffer, PCWSTR varname) // LONG AttachDetours(VOID) { - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttach(&(PVOID&)Real_EntryPoint, Mine_EntryPoint); DetourAttach(&(PVOID&)Real_ExitProcess, Mine_ExitProcess); @@ -3789,8 +3789,8 @@ LONG AttachDetours(VOID) LONG DetachDetours(VOID) { - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourDetach(&(PVOID&)Real_EntryPoint, Mine_EntryPoint); DetourAttach(&(PVOID&)Real_ExitProcess, Mine_ExitProcess); @@ -4515,8 +4515,8 @@ int WINAPI Mine_EntryPoint(VOID) FindProc(&(PVOID&)Real_dupenv_s, "_dupenv_s"); FindProc(&(PVOID&)Real_wdupenv_s, "_wdupenv_s"); - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttachIf(&(PVOID&)Real_getenv, Mine_getenv); DetourAttachIf(&(PVOID&)Real_getenv_s, Mine_getenv_s); diff --git a/samples/tracelnk/trclnk.cpp b/samples/tracelnk/trclnk.cpp index 75cbfe2c..3e1ef1b7 100644 --- a/samples/tracelnk/trclnk.cpp +++ b/samples/tracelnk/trclnk.cpp @@ -256,8 +256,8 @@ VOID DetDetach(PVOID *ppbReal, PVOID pbMine, PCHAR psz) LONG AttachDetours(VOID) { - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); ATTACH(FreeLibrary); ATTACH(GetModuleHandleW); @@ -270,8 +270,8 @@ LONG AttachDetours(VOID) LONG DetachDetours(VOID) { - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DETACH(FreeLibrary); DETACH(GetModuleHandleW); diff --git a/samples/tracemem/trcmem.cpp b/samples/tracemem/trcmem.cpp index 85f72b98..08f98736 100644 --- a/samples/tracemem/trcmem.cpp +++ b/samples/tracemem/trcmem.cpp @@ -256,8 +256,8 @@ VOID DetDetach(PVOID *ppbReal, PVOID pbMine, PCHAR psz) LONG AttachDetours(VOID) { - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); ATTACH(CreateProcessW); ATTACH(HeapAlloc); @@ -267,8 +267,8 @@ LONG AttachDetours(VOID) LONG DetachDetours(VOID) { - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DETACH(CreateProcessW); DETACH(HeapAlloc); diff --git a/samples/tracereg/trcreg.cpp b/samples/tracereg/trcreg.cpp index 7e1b7808..637e9f5a 100644 --- a/samples/tracereg/trcreg.cpp +++ b/samples/tracereg/trcreg.cpp @@ -1175,8 +1175,8 @@ VOID DetDetach(PVOID *ppbReal, PVOID pbMine, PCHAR psz) LONG AttachDetours(VOID) { - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); ATTACH(CloseHandle); ATTACH(CopyFileExA); @@ -1228,8 +1228,8 @@ LONG AttachDetours(VOID) LONG DetachDetours(VOID) { - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DETACH(CloseHandle); DETACH(CopyFileExA); diff --git a/samples/traceser/trcser.cpp b/samples/traceser/trcser.cpp index b696fe6b..5dc400bd 100644 --- a/samples/traceser/trcser.cpp +++ b/samples/traceser/trcser.cpp @@ -777,8 +777,8 @@ VOID DetDetach(PVOID *ppbReal, PVOID pbMine, PCHAR psz) LONG AttachDetours(VOID) { - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); ATTACH(BuildCommDCBA); ATTACH(BuildCommDCBAndTimeoutsA); @@ -816,8 +816,8 @@ LONG AttachDetours(VOID) LONG DetachDetours(VOID) { - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DETACH(BuildCommDCBA); DETACH(BuildCommDCBAndTimeoutsA); diff --git a/samples/tracessl/trcssl.cpp b/samples/tracessl/trcssl.cpp index ffc44391..0802bd61 100644 --- a/samples/tracessl/trcssl.cpp +++ b/samples/tracessl/trcssl.cpp @@ -1422,8 +1422,8 @@ VOID DetDetach(PVOID *ppbReal, PVOID pbMine, PCHAR psz) LONG AttachDetours(VOID) { - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); ATTACH(CreateProcessW); ATTACH(DecryptMessage); @@ -1478,8 +1478,8 @@ LONG AttachDetours(VOID) LONG DetachDetours(VOID) { - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DETACH(CreateProcessW); DETACH(DecryptMessage); diff --git a/samples/tracetcp/trctcp.cpp b/samples/tracetcp/trctcp.cpp index 9f2a879b..bc3af98e 100644 --- a/samples/tracetcp/trctcp.cpp +++ b/samples/tracetcp/trctcp.cpp @@ -1526,8 +1526,8 @@ VOID DetDetach(PVOID *ppbReal, PVOID pbMine, PCHAR psz) LONG AttachDetours(VOID) { - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); ATTACH(CreateProcessW); ATTACH(WSAAccept); @@ -1585,8 +1585,8 @@ LONG AttachDetours(VOID) LONG DetachDetours(VOID) { - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DETACH(CreateProcessW); DETACH(WSAAccept); diff --git a/samples/tryman/tstman.cpp b/samples/tryman/tstman.cpp index 0ae169b0..99aab0bd 100644 --- a/samples/tryman/tstman.cpp +++ b/samples/tryman/tstman.cpp @@ -292,8 +292,8 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved) TrueEntryPoint = (int (WINAPI *)(VOID))DetourGetEntryPoint(NULL); RawEntryPoint = TrueEntryPoint; - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourAttach(&(PVOID&)TrueEntryPoint, TestEntryPoint); DetourAttach(&(PVOID&)Real_CreateProcessA, Mine_CreateProcessA); DetourAttach(&(PVOID&)Real_CreateProcessW, Mine_CreateProcessW); @@ -315,8 +315,8 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved) } else if (dwReason == DLL_PROCESS_DETACH) { - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + DetourTransactionBegin(TRUE); + DetourUpdateAllOtherThreads(); DetourDetach(&(PVOID&)TrueEntryPoint, TestEntryPoint); DetourDetach(&(PVOID&)Real_CreateProcessA, Mine_CreateProcessA); DetourDetach(&(PVOID&)Real_CreateProcessW, Mine_CreateProcessW); diff --git a/src/creatwth.cpp b/src/creatwth.cpp index 057e4f95..928802bf 100644 --- a/src/creatwth.cpp +++ b/src/creatwth.cpp @@ -1,4 +1,4 @@ -////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// // // Create a process with a DLL (creatwth.cpp of detours.lib) // @@ -11,6 +11,7 @@ #define DETOURS_INTERNAL #include "detours.h" #include +#include #if DETOURS_VERSION != 0x4c0c1 // 0xMAJORcMINORcPATCH #error detours.h version mismatch @@ -408,7 +409,10 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine, // inh64.Signature = inh32.Signature; inh64.FileHeader = inh32.FileHeader; - inh64.FileHeader.Machine = machine; + inh64.FileHeader.Machine = machine;//如果这里就赋值为inh32.FileHeader.Machine的话,win7及以下的PE加载器会过不了, + //会报错STATUS_INVALID_IMAGE_FORMAT,所以需要在dep中保存原来的PE头中的Machine的值,即inh32.FileHeader.Machine的值, + //If inh32.FileHeader.Machine is assigned here, the PE loader of win7 and below will not be able to pass, + //It will report an error STATUS_INVALID_IMAGE_FORMAT, so you need to save the value of Machine in the original PE header in dep, that is, the value of inh32.FileHeader.Machine, inh64.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER64); inh64.OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR64_MAGIC; @@ -476,6 +480,11 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine, if (!RecordExeRestore(hProcess, hModule, der)) { return FALSE; } + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //上面的RecordExeRestore调用之后,dep中保存的是64位的PE头了,所以需要恢复der中保存的PE头的Machine的值,以使得.NET的PE解析器可以正常加载该CLR文件 + //After the above RecordExeRestore call, the 64-bit PE header is saved in dep, so it is necessary to restore the Machine value of the PE header saved in der, so that the PE parser of .NET can load the CLR file normally + der.inh.FileHeader.Machine = inh32.FileHeader.Machine; + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Remove the import table. if (der.pclr != NULL && (der.clr.Flags & COMIMAGE_FLAGS_ILONLY)) { @@ -499,37 +508,60 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine, } #endif // DETOURS_64BIT -typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS)(HANDLE, PBOOL); - -static BOOL IsWow64ProcessHelper(HANDLE hProcess, - PBOOL Wow64Process) +namespace Detour { -#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: %d\n", GetLastError())); - return FALSE; - } - - LPFN_ISWOW64PROCESS pfnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress( - hKernel32, "IsWow64Process"); - - if (pfnIsWow64Process == NULL) { - DETOUR_TRACE(("GetProcAddress failed: %d\n", GetLastError())); - return FALSE; - } - return pfnIsWow64Process(hProcess, Wow64Process); -#else - return IsWow64Process(hProcess, Wow64Process); +#ifndef PROCESSOR_ARCHITECTURE_ARM64 +#define PROCESSOR_ARCHITECTURE_ARM64 12 #endif + BOOL Is64BitOS() + { + BOOL bRet = FALSE; + HMODULE hModule = GetModuleHandle(TEXT("kernel32.dll")); + if (!hModule) + { + return bRet; + } + VOID(WINAPI * _GetNativeSystemInfo)(OUT LPSYSTEM_INFO lpSystemInfo) = (void(__stdcall *)(LPSYSTEM_INFO))GetProcAddress(hModule, "GetNativeSystemInfo"); + if (!_GetNativeSystemInfo) + { + return bRet; + } + + SYSTEM_INFO si; + _GetNativeSystemInfo(&si); + if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 || si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ARM64 || + si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64 || si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ALPHA64) + { + bRet = TRUE; + } + return bRet; + }; + //进程句柄hProcess需要有PROCESS_QUERY_INFORMATION或者PROCESS_QUERY_LIMITED_INFORMATION访问权限 + //The process handle hProcess needs to have PROCESS_QUERY_INFORMATION or PROCESS_QUERY_LIMITED_INFORMATION access rights + BOOL Is64BitProcess(HANDLE hProcess) + { + BOOL bRet = FALSE; + if (hProcess) + { + if (Is64BitOS()) + { + HMODULE hModule = GetModuleHandle(TEXT("kernel32.dll")); + if (hModule) + { + BOOL(WINAPI * _IsWow64Process)(IN HANDLE hProcess, + OUT PBOOL Wow64Process) + = (BOOL(__stdcall*)(HANDLE, PBOOL))GetProcAddress(hModule, "IsWow64Process"); + BOOL bX86ProcessRunAt64BitOS; + if (_IsWow64Process && _IsWow64Process(hProcess, &bX86ProcessRunAt64BitOS) && bX86ProcessRunAt64BitOS == FALSE) + { + bRet = TRUE; + } + } + } + } + return bRet; + } } - ////////////////////////////////////////////////////////////////////////////// // BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess, @@ -579,19 +611,29 @@ BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess, return FALSE; } - if (!bHas32BitExe) { - bIs32BitProcess = FALSE; - } - else if (!bHas64BitDll) { - bIs32BitProcess = TRUE; - } - else { - if (!IsWow64ProcessHelper(hProcess, &bIs32BitProcess)) { - return FALSE; - } - } - - DETOUR_TRACE((" 32BitExe=%d 32BitProcess\n", bHas32BitExe, bIs32BitProcess)); + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //被注释掉的代码 + //下面的代码不能正确判断启动的进程是否是32位的 + //Commented out code + //The following code cannot correctly determine whether the started process is 32-bit + //if (!bHas32BitExe) { + // bIs32BitProcess = FALSE; + //} + //else if (!bHas64BitDll) { + // bIs32BitProcess = TRUE; + //} + //else { + // if (!IsWow64Process(hProcess, &bIs32BitProcess)) { + // return FALSE; + // } + //} + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //添加的代码 + //Added code + bIs32BitProcess = !Detour::Is64BitProcess(hProcess); + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + DETOUR_TRACE((" 32BitExe=%d 32BitProcess=%d\n", bHas32BitExe, bIs32BitProcess)); return DetourUpdateProcessWithDllEx(hProcess, hModule, @@ -625,7 +667,7 @@ BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess, bIs32BitExe = TRUE; } - DETOUR_TRACE((" 32BitExe=%d 32BitProcess\n", bIs32BitExe, bIs32BitProcess)); + DETOUR_TRACE((" 32BitExe=%d 32BitProcess=%d\n", bIs32BitExe, bIs32BitProcess)); if (hModule == NULL) { SetLastError(ERROR_INVALID_OPERATION); @@ -709,6 +751,10 @@ BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess, DETOUR_CLR_HEADER clr; CopyMemory(&clr, &der.clr, sizeof(clr)); clr.Flags &= ~COMIMAGE_FLAGS_ILONLY; // Clear the IL_ONLY flag. + //上面这句清除了IL_ONLY标志,所以我们之后启动完成进程后,恢复IAT后需要恢复这个IL_ONLY标志 + //不清除IL_ONLY标志将导致无法启动进程,因为我们替换了原IAT为包含我们的DLL的名称项的新IAT + //The above sentence clears the IL_ONLY flag, so we need to restore the IL_ONLY flag after the IAT is restored after starting the process completion + //Not clearing the IL_ONLY flag will result in the inability to start the process, because we replaced the original IAT with the new IAT containing the name of our DLL DWORD dwProtect; if (!DetourVirtualProtectSameExecuteEx(hProcess, der.pclr, sizeof(clr), PAGE_READWRITE, &dwProtect)) { @@ -986,7 +1032,7 @@ VOID CALLBACK DetourFinishHelperProcess(_In_ HWND, goto Cleanup; } - rlpDlls = new NOTHROW LPCSTR [s_pHelper->nDlls]; + rlpDlls = DetourCreateObjectArray(s_pHelper->nDlls); cSize = s_pHelper->cb - sizeof(DETOUR_EXE_HELPER); for (DWORD n = 0; n < s_pHelper->nDlls; n++) { size_t cchDest = 0; @@ -1010,10 +1056,23 @@ VOID CALLBACK DetourFinishHelperProcess(_In_ HWND, Cleanup: if (rlpDlls != NULL) { - delete[] rlpDlls; + DetourDestroyObjectArray(rlpDlls); rlpDlls = NULL; } + //执行完成后删除该负载以释放其所占用的内存 + //Delete the payload after execution to release the memory occupied by it + if (s_pHelper != NULL) + { + HMODULE hModule = DetourGetContainingModule(s_pHelper); + assert(hModule != NULL); + if (hModule != NULL) + { + VirtualFree(hModule, 0, MEM_RELEASE); + hModule = NULL; + } + } + ExitProcess(Result); } @@ -1075,7 +1134,7 @@ BOOL WINAPI AllocExeHelper(_Out_ PDETOUR_EXE_HELPER *pHelper, cSize += (DWORD)cchDest + 1; } - Helper = (PDETOUR_EXE_HELPER) new NOTHROW BYTE[sizeof(DETOUR_EXE_HELPER) + cSize]; + Helper = (PDETOUR_EXE_HELPER)DetourCreateObjectArray(sizeof(DETOUR_EXE_HELPER) + cSize); if (Helper == NULL) { goto Cleanup; } @@ -1140,7 +1199,7 @@ BOOL WINAPI AllocExeHelper(_Out_ PDETOUR_EXE_HELPER *pHelper, Cleanup: if (Helper != NULL) { - delete[] (PBYTE)Helper; + DetourDestroyObjectArray((PBYTE)Helper); Helper = NULL; } return Result; @@ -1150,7 +1209,7 @@ static VOID WINAPI FreeExeHelper(PDETOUR_EXE_HELPER *pHelper) { if (*pHelper != NULL) { - delete[] (PBYTE)*pHelper; + DetourDestroyObjectArray((PBYTE)*pHelper); *pHelper = NULL; } } @@ -1203,8 +1262,11 @@ BOOL WINAPI DetourProcessViaHelperDllsA(_In_ DWORD dwTargetPid, goto Cleanup; } - hr = StringCchPrintfA(szCommand, ARRAYSIZE(szCommand), - "rundll32.exe \"%hs\",#1", &helper->rDlls[0]); + //hr = StringCchPrintfA(szCommand, ARRAYSIZE(szCommand), + // "rundll32.exe \"%hs\",#1", &helper->rDlls[0]); + //fix for chinese + hr = StringCchPrintfA(szCommand, ARRAYSIZE(szCommand), + "rundll32.exe \"%s\",#1", &helper->rDlls[0]); if (!SUCCEEDED(hr)) { goto Cleanup; } @@ -1299,8 +1361,13 @@ BOOL WINAPI DetourProcessViaHelperDllsW(_In_ DWORD dwTargetPid, goto Cleanup; } - hr = StringCchPrintfW(szCommand, ARRAYSIZE(szCommand), - L"rundll32.exe \"%hs\",#1", &helper->rDlls[0]); + //hr = StringCchPrintfW(szCommand, ARRAYSIZE(szCommand), + // L"rundll32.exe \"%hs\",#1", &helper->rDlls[0]); + //fix for chinese + WCHAR szDllName[MAX_PATH]; + MultiByteToWideChar(CP_ACP, 0, &helper->rDlls[0], -1, szDllName, ARRAYSIZE(szDllName)); + hr = StringCchPrintfW(szCommand, ARRAYSIZE(szCommand), + L"rundll32.exe \"%s\",#1", szDllName); if (!SUCCEEDED(hr)) { goto Cleanup; } diff --git a/src/detours.cpp b/src/detours.cpp index 34f2458f..117a409e 100644 --- a/src/detours.cpp +++ b/src/detours.cpp @@ -1,2554 +1,3001 @@ -////////////////////////////////////////////////////////////////////////////// -// -// Core Detours Functionality (detours.cpp of detours.lib) -// -// Microsoft Research Detours Package, Version 4.0.1 -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// - - -//#define DETOUR_DEBUG 1 -#define DETOURS_INTERNAL -#include "detours.h" - -#if DETOURS_VERSION != 0x4c0c1 // 0xMAJORcMINORcPATCH -#error detours.h version mismatch -#endif - -#define NOTHROW - -////////////////////////////////////////////////////////////////////////////// -// -struct _DETOUR_ALIGN -{ - BYTE obTarget : 3; - BYTE obTrampoline : 5; -}; - -C_ASSERT(sizeof(_DETOUR_ALIGN) == 1); - -////////////////////////////////////////////////////////////////////////////// -// -// Region reserved for system DLLs, which cannot be used for trampolines. -// -static PVOID s_pSystemRegionLowerBound = (PVOID)(ULONG_PTR)0x70000000; -static PVOID s_pSystemRegionUpperBound = (PVOID)(ULONG_PTR)0x80000000; - -////////////////////////////////////////////////////////////////////////////// -// -static bool detour_is_imported(PBYTE pbCode, PBYTE pbAddress) -{ - MEMORY_BASIC_INFORMATION mbi; - VirtualQuery((PVOID)pbCode, &mbi, sizeof(mbi)); - __try { - PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)mbi.AllocationBase; - if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) { - return false; - } - - PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader + - pDosHeader->e_lfanew); - if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) { - return false; - } - - if (pbAddress >= ((PBYTE)pDosHeader + - pNtHeader->OptionalHeader - .DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress) && - pbAddress < ((PBYTE)pDosHeader + - pNtHeader->OptionalHeader - .DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress + - pNtHeader->OptionalHeader - .DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size)) { - return true; - } - } -#pragma prefast(suppress:28940, "A bad pointer means this probably isn't a PE header.") - __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? - EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { - return false; - } - return false; -} - -inline ULONG_PTR detour_2gb_below(ULONG_PTR address) -{ - return (address > (ULONG_PTR)0x7ff80000) ? address - 0x7ff80000 : 0x80000; -} - -inline ULONG_PTR detour_2gb_above(ULONG_PTR address) -{ -#if defined(DETOURS_64BIT) - return (address < (ULONG_PTR)0xffffffff80000000) ? address + 0x7ff80000 : (ULONG_PTR)0xfffffffffff80000; -#else - return (address < (ULONG_PTR)0x80000000) ? address + 0x7ff80000 : (ULONG_PTR)0xfff80000; -#endif -} - -///////////////////////////////////////////////////////////////////////// X86. -// -#ifdef DETOURS_X86 - -struct _DETOUR_TRAMPOLINE -{ - BYTE rbCode[30]; // target code + jmp to pbRemain - BYTE cbCode; // size of moved target code. - BYTE cbCodeBreak; // padding to make debugging easier. - BYTE rbRestore[22]; // original target code. - BYTE cbRestore; // size of original target code. - BYTE cbRestoreBreak; // padding to make debugging easier. - _DETOUR_ALIGN rAlign[8]; // instruction alignment array. - PBYTE pbRemain; // first instruction after moved code. [free list] - PBYTE pbDetour; // first instruction of detour function. -}; - -C_ASSERT(sizeof(_DETOUR_TRAMPOLINE) == 72); - -enum { - SIZE_OF_JMP = 5 -}; - -inline PBYTE detour_gen_jmp_immediate(PBYTE pbCode, PBYTE pbJmpVal) -{ - PBYTE pbJmpSrc = pbCode + 5; - *pbCode++ = 0xE9; // jmp +imm32 - *((INT32*&)pbCode)++ = (INT32)(pbJmpVal - pbJmpSrc); - return pbCode; -} - -inline PBYTE detour_gen_jmp_indirect(PBYTE pbCode, PBYTE *ppbJmpVal) -{ - *pbCode++ = 0xff; // jmp [+imm32] - *pbCode++ = 0x25; - *((INT32*&)pbCode)++ = (INT32)((PBYTE)ppbJmpVal); - return pbCode; -} - -inline PBYTE detour_gen_brk(PBYTE pbCode, PBYTE pbLimit) -{ - while (pbCode < pbLimit) { - *pbCode++ = 0xcc; // brk; - } - return pbCode; -} - -inline PBYTE detour_skip_jmp(PBYTE pbCode, PVOID *ppGlobals) -{ - if (pbCode == NULL) { - return NULL; - } - if (ppGlobals != NULL) { - *ppGlobals = NULL; - } - - // First, skip over the import vector if there is one. - if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [imm32] - // Looks like an import alias jump, then get the code it points to. - PBYTE pbTarget = *(UNALIGNED PBYTE *)&pbCode[2]; - if (detour_is_imported(pbCode, pbTarget)) { - PBYTE pbNew = *(UNALIGNED PBYTE *)pbTarget; - DETOUR_TRACE(("%p->%p: skipped over import table.\n", pbCode, pbNew)); - pbCode = pbNew; - } - } - - // Then, skip over a patch jump - if (pbCode[0] == 0xeb) { // jmp +imm8 - PBYTE pbNew = pbCode + 2 + *(CHAR *)&pbCode[1]; - DETOUR_TRACE(("%p->%p: skipped over short jump.\n", pbCode, pbNew)); - pbCode = pbNew; - - // First, skip over the import vector if there is one. - if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [imm32] - // Looks like an import alias jump, then get the code it points to. - PBYTE pbTarget = *(UNALIGNED PBYTE *)&pbCode[2]; - if (detour_is_imported(pbCode, pbTarget)) { - pbNew = *(UNALIGNED PBYTE *)pbTarget; - DETOUR_TRACE(("%p->%p: skipped over import table.\n", pbCode, pbNew)); - pbCode = pbNew; - } - } - // Finally, skip over a long jump if it is the target of the patch jump. - else if (pbCode[0] == 0xe9) { // jmp +imm32 - pbNew = pbCode + 5 + *(UNALIGNED INT32 *)&pbCode[1]; - DETOUR_TRACE(("%p->%p: skipped over long jump.\n", pbCode, pbNew)); - pbCode = pbNew; - } - } - return pbCode; -} - -inline void detour_find_jmp_bounds(PBYTE pbCode, - PDETOUR_TRAMPOLINE *ppLower, - PDETOUR_TRAMPOLINE *ppUpper) -{ - // We have to place trampolines within +/- 2GB of code. - ULONG_PTR lo = detour_2gb_below((ULONG_PTR)pbCode); - ULONG_PTR hi = detour_2gb_above((ULONG_PTR)pbCode); - DETOUR_TRACE(("[%p..%p..%p]\n", lo, pbCode, hi)); - - // And, within +/- 2GB of relative jmp targets. - if (pbCode[0] == 0xe9) { // jmp +imm32 - PBYTE pbNew = pbCode + 5 + *(UNALIGNED INT32 *)&pbCode[1]; - - if (pbNew < pbCode) { - hi = detour_2gb_above((ULONG_PTR)pbNew); - } - else { - lo = detour_2gb_below((ULONG_PTR)pbNew); - } - DETOUR_TRACE(("[%p..%p..%p] +imm32\n", lo, pbCode, hi)); - } - - *ppLower = (PDETOUR_TRAMPOLINE)lo; - *ppUpper = (PDETOUR_TRAMPOLINE)hi; -} - -inline BOOL detour_does_code_end_function(PBYTE pbCode) -{ - if (pbCode[0] == 0xeb || // jmp +imm8 - pbCode[0] == 0xe9 || // jmp +imm32 - pbCode[0] == 0xe0 || // jmp eax - pbCode[0] == 0xc2 || // ret +imm8 - pbCode[0] == 0xc3 || // ret - pbCode[0] == 0xcc) { // brk - return TRUE; - } - else if (pbCode[0] == 0xf3 && pbCode[1] == 0xc3) { // rep ret - return TRUE; - } - else if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [+imm32] - return TRUE; - } - else if ((pbCode[0] == 0x26 || // jmp es: - pbCode[0] == 0x2e || // jmp cs: - pbCode[0] == 0x36 || // jmp ss: - pbCode[0] == 0x3e || // jmp ds: - pbCode[0] == 0x64 || // jmp fs: - pbCode[0] == 0x65) && // jmp gs: - pbCode[1] == 0xff && // jmp [+imm32] - pbCode[2] == 0x25) { - return TRUE; - } - return FALSE; -} - -inline ULONG detour_is_code_filler(PBYTE pbCode) -{ - // 1-byte through 11-byte NOPs. - if (pbCode[0] == 0x90) { - return 1; - } - if (pbCode[0] == 0x66 && pbCode[1] == 0x90) { - return 2; - } - if (pbCode[0] == 0x0F && pbCode[1] == 0x1F && pbCode[2] == 0x00) { - return 3; - } - if (pbCode[0] == 0x0F && pbCode[1] == 0x1F && pbCode[2] == 0x40 && - pbCode[3] == 0x00) { - return 4; - } - if (pbCode[0] == 0x0F && pbCode[1] == 0x1F && pbCode[2] == 0x44 && - pbCode[3] == 0x00 && pbCode[4] == 0x00) { - return 5; - } - if (pbCode[0] == 0x66 && pbCode[1] == 0x0F && pbCode[2] == 0x1F && - pbCode[3] == 0x44 && pbCode[4] == 0x00 && pbCode[5] == 0x00) { - return 6; - } - if (pbCode[0] == 0x0F && pbCode[1] == 0x1F && pbCode[2] == 0x80 && - pbCode[3] == 0x00 && pbCode[4] == 0x00 && pbCode[5] == 0x00 && - pbCode[6] == 0x00) { - return 7; - } - if (pbCode[0] == 0x0F && pbCode[1] == 0x1F && pbCode[2] == 0x84 && - pbCode[3] == 0x00 && pbCode[4] == 0x00 && pbCode[5] == 0x00 && - pbCode[6] == 0x00 && pbCode[7] == 0x00) { - return 8; - } - if (pbCode[0] == 0x66 && pbCode[1] == 0x0F && pbCode[2] == 0x1F && - pbCode[3] == 0x84 && pbCode[4] == 0x00 && pbCode[5] == 0x00 && - pbCode[6] == 0x00 && pbCode[7] == 0x00 && pbCode[8] == 0x00) { - return 9; - } - if (pbCode[0] == 0x66 && pbCode[1] == 0x66 && pbCode[2] == 0x0F && - pbCode[3] == 0x1F && pbCode[4] == 0x84 && pbCode[5] == 0x00 && - pbCode[6] == 0x00 && pbCode[7] == 0x00 && pbCode[8] == 0x00 && - pbCode[9] == 0x00) { - return 10; - } - if (pbCode[0] == 0x66 && pbCode[1] == 0x66 && pbCode[2] == 0x66 && - pbCode[3] == 0x0F && pbCode[4] == 0x1F && pbCode[5] == 0x84 && - pbCode[6] == 0x00 && pbCode[7] == 0x00 && pbCode[8] == 0x00 && - pbCode[9] == 0x00 && pbCode[10] == 0x00) { - return 11; - } - - // int 3. - if (pbCode[0] == 0xcc) { - return 1; - } - return 0; -} - -#endif // DETOURS_X86 - -///////////////////////////////////////////////////////////////////////// X64. -// -#ifdef DETOURS_X64 - -struct _DETOUR_TRAMPOLINE -{ - // An X64 instuction can be 15 bytes long. - // In practice 11 seems to be the limit. - BYTE rbCode[30]; // target code + jmp to pbRemain. - BYTE cbCode; // size of moved target code. - BYTE cbCodeBreak; // padding to make debugging easier. - BYTE rbRestore[30]; // original target code. - BYTE cbRestore; // size of original target code. - BYTE cbRestoreBreak; // padding to make debugging easier. - _DETOUR_ALIGN rAlign[8]; // instruction alignment array. - PBYTE pbRemain; // first instruction after moved code. [free list] - PBYTE pbDetour; // first instruction of detour function. - BYTE rbCodeIn[8]; // jmp [pbDetour] -}; - -C_ASSERT(sizeof(_DETOUR_TRAMPOLINE) == 96); - -enum { - SIZE_OF_JMP = 5 -}; - -inline PBYTE detour_gen_jmp_immediate(PBYTE pbCode, PBYTE pbJmpVal) -{ - PBYTE pbJmpSrc = pbCode + 5; - *pbCode++ = 0xE9; // jmp +imm32 - *((INT32*&)pbCode)++ = (INT32)(pbJmpVal - pbJmpSrc); - return pbCode; -} - -inline PBYTE detour_gen_jmp_indirect(PBYTE pbCode, PBYTE *ppbJmpVal) -{ - PBYTE pbJmpSrc = pbCode + 6; - *pbCode++ = 0xff; // jmp [+imm32] - *pbCode++ = 0x25; - *((INT32*&)pbCode)++ = (INT32)((PBYTE)ppbJmpVal - pbJmpSrc); - return pbCode; -} - -inline PBYTE detour_gen_brk(PBYTE pbCode, PBYTE pbLimit) -{ - while (pbCode < pbLimit) { - *pbCode++ = 0xcc; // brk; - } - return pbCode; -} - -inline PBYTE detour_skip_jmp(PBYTE pbCode, PVOID *ppGlobals) -{ - if (pbCode == NULL) { - return NULL; - } - if (ppGlobals != NULL) { - *ppGlobals = NULL; - } - - // First, skip over the import vector if there is one. - if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [+imm32] - // Looks like an import alias jump, then get the code it points to. - PBYTE pbTarget = pbCode + 6 + *(UNALIGNED INT32 *)&pbCode[2]; - if (detour_is_imported(pbCode, pbTarget)) { - PBYTE pbNew = *(UNALIGNED PBYTE *)pbTarget; - DETOUR_TRACE(("%p->%p: skipped over import table.\n", pbCode, pbNew)); - pbCode = pbNew; - } - } - - // Then, skip over a patch jump - if (pbCode[0] == 0xeb) { // jmp +imm8 - PBYTE pbNew = pbCode + 2 + *(CHAR *)&pbCode[1]; - DETOUR_TRACE(("%p->%p: skipped over short jump.\n", pbCode, pbNew)); - pbCode = pbNew; - - // First, skip over the import vector if there is one. - if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [+imm32] - // Looks like an import alias jump, then get the code it points to. - PBYTE pbTarget = pbCode + 6 + *(UNALIGNED INT32 *)&pbCode[2]; - if (detour_is_imported(pbCode, pbTarget)) { - pbNew = *(UNALIGNED PBYTE *)pbTarget; - DETOUR_TRACE(("%p->%p: skipped over import table.\n", pbCode, pbNew)); - pbCode = pbNew; - } - } - // Finally, skip over a long jump if it is the target of the patch jump. - else if (pbCode[0] == 0xe9) { // jmp +imm32 - pbNew = pbCode + 5 + *(UNALIGNED INT32 *)&pbCode[1]; - DETOUR_TRACE(("%p->%p: skipped over long jump.\n", pbCode, pbNew)); - pbCode = pbNew; - } - } - return pbCode; -} - -inline void detour_find_jmp_bounds(PBYTE pbCode, - PDETOUR_TRAMPOLINE *ppLower, - PDETOUR_TRAMPOLINE *ppUpper) -{ - // We have to place trampolines within +/- 2GB of code. - ULONG_PTR lo = detour_2gb_below((ULONG_PTR)pbCode); - ULONG_PTR hi = detour_2gb_above((ULONG_PTR)pbCode); - DETOUR_TRACE(("[%p..%p..%p]\n", lo, pbCode, hi)); - - // And, within +/- 2GB of relative jmp vectors. - if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [+imm32] - PBYTE pbNew = pbCode + 6 + *(UNALIGNED INT32 *)&pbCode[2]; - - if (pbNew < pbCode) { - hi = detour_2gb_above((ULONG_PTR)pbNew); - } - else { - lo = detour_2gb_below((ULONG_PTR)pbNew); - } - DETOUR_TRACE(("[%p..%p..%p] [+imm32]\n", lo, pbCode, hi)); - } - // And, within +/- 2GB of relative jmp targets. - else if (pbCode[0] == 0xe9) { // jmp +imm32 - PBYTE pbNew = pbCode + 5 + *(UNALIGNED INT32 *)&pbCode[1]; - - if (pbNew < pbCode) { - hi = detour_2gb_above((ULONG_PTR)pbNew); - } - else { - lo = detour_2gb_below((ULONG_PTR)pbNew); - } - DETOUR_TRACE(("[%p..%p..%p] +imm32\n", lo, pbCode, hi)); - } - - *ppLower = (PDETOUR_TRAMPOLINE)lo; - *ppUpper = (PDETOUR_TRAMPOLINE)hi; -} - -inline BOOL detour_does_code_end_function(PBYTE pbCode) -{ - if (pbCode[0] == 0xeb || // jmp +imm8 - pbCode[0] == 0xe9 || // jmp +imm32 - pbCode[0] == 0xe0 || // jmp eax - pbCode[0] == 0xc2 || // ret +imm8 - pbCode[0] == 0xc3 || // ret - pbCode[0] == 0xcc) { // brk - return TRUE; - } - else if (pbCode[0] == 0xf3 && pbCode[1] == 0xc3) { // rep ret - return TRUE; - } - else if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [+imm32] - return TRUE; - } - else if ((pbCode[0] == 0x26 || // jmp es: - pbCode[0] == 0x2e || // jmp cs: - pbCode[0] == 0x36 || // jmp ss: - pbCode[0] == 0x3e || // jmp ds: - pbCode[0] == 0x64 || // jmp fs: - pbCode[0] == 0x65) && // jmp gs: - pbCode[1] == 0xff && // jmp [+imm32] - pbCode[2] == 0x25) { - return TRUE; - } - return FALSE; -} - -inline ULONG detour_is_code_filler(PBYTE pbCode) -{ - // 1-byte through 11-byte NOPs. - if (pbCode[0] == 0x90) { - return 1; - } - if (pbCode[0] == 0x66 && pbCode[1] == 0x90) { - return 2; - } - if (pbCode[0] == 0x0F && pbCode[1] == 0x1F && pbCode[2] == 0x00) { - return 3; - } - if (pbCode[0] == 0x0F && pbCode[1] == 0x1F && pbCode[2] == 0x40 && - pbCode[3] == 0x00) { - return 4; - } - if (pbCode[0] == 0x0F && pbCode[1] == 0x1F && pbCode[2] == 0x44 && - pbCode[3] == 0x00 && pbCode[4] == 0x00) { - return 5; - } - if (pbCode[0] == 0x66 && pbCode[1] == 0x0F && pbCode[2] == 0x1F && - pbCode[3] == 0x44 && pbCode[4] == 0x00 && pbCode[5] == 0x00) { - return 6; - } - if (pbCode[0] == 0x0F && pbCode[1] == 0x1F && pbCode[2] == 0x80 && - pbCode[3] == 0x00 && pbCode[4] == 0x00 && pbCode[5] == 0x00 && - pbCode[6] == 0x00) { - return 7; - } - if (pbCode[0] == 0x0F && pbCode[1] == 0x1F && pbCode[2] == 0x84 && - pbCode[3] == 0x00 && pbCode[4] == 0x00 && pbCode[5] == 0x00 && - pbCode[6] == 0x00 && pbCode[7] == 0x00) { - return 8; - } - if (pbCode[0] == 0x66 && pbCode[1] == 0x0F && pbCode[2] == 0x1F && - pbCode[3] == 0x84 && pbCode[4] == 0x00 && pbCode[5] == 0x00 && - pbCode[6] == 0x00 && pbCode[7] == 0x00 && pbCode[8] == 0x00) { - return 9; - } - if (pbCode[0] == 0x66 && pbCode[1] == 0x66 && pbCode[2] == 0x0F && - pbCode[3] == 0x1F && pbCode[4] == 0x84 && pbCode[5] == 0x00 && - pbCode[6] == 0x00 && pbCode[7] == 0x00 && pbCode[8] == 0x00 && - pbCode[9] == 0x00) { - return 10; - } - if (pbCode[0] == 0x66 && pbCode[1] == 0x66 && pbCode[2] == 0x66 && - pbCode[3] == 0x0F && pbCode[4] == 0x1F && pbCode[5] == 0x84 && - pbCode[6] == 0x00 && pbCode[7] == 0x00 && pbCode[8] == 0x00 && - pbCode[9] == 0x00 && pbCode[10] == 0x00) { - return 11; - } - - // int 3. - if (pbCode[0] == 0xcc) { - return 1; - } - return 0; -} - -#endif // DETOURS_X64 - -//////////////////////////////////////////////////////////////////////// IA64. -// -#ifdef DETOURS_IA64 - -struct _DETOUR_TRAMPOLINE -{ - // On the IA64, a trampoline is used for both incoming and outgoing calls. - // - // The trampoline contains the following bundles for the outgoing call: - // movl gp=target_gp; - // - // brl target_code; - // - // The trampoline contains the following bundles for the incoming call: - // alloc r41=ar.pfs, b, 0, 8, 0 - // mov r40=rp - // - // adds r50=0, r39 - // adds r49=0, r38 - // adds r48=0, r37 ;; - // - // adds r47=0, r36 - // adds r46=0, r35 - // adds r45=0, r34 - // - // adds r44=0, r33 - // adds r43=0, r32 - // adds r42=0, gp ;; - // - // movl gp=ffffffff`ffffffff ;; - // - // brl.call.sptk.few rp=disas!TestCodes+20e0 (00000000`00404ea0) ;; - // - // adds gp=0, r42 - // mov rp=r40, +0 ;; - // mov.i ar.pfs=r41 - // - // br.ret.sptk.many rp ;; - // - // This way, we only have to relocate a single bundle. - // - // The complicated incoming trampoline is required because we have to - // create an additional stack frame so that we save and restore the gp. - // We must do this because gp is a caller-saved register, but not saved - // if the caller thinks the target is in the same DLL, which changes - // when we insert a detour. - // - DETOUR_IA64_BUNDLE bMovlTargetGp; // Bundle which sets target GP - BYTE rbCode[sizeof(DETOUR_IA64_BUNDLE)]; // moved bundle. - DETOUR_IA64_BUNDLE bBrlRemainEip; // Brl to pbRemain - // This must be adjacent to bBranchIslands. - - // Each instruction in the moved bundle could be a IP-relative chk or branch or call. - // Any such instructions are changed to point to a brl in bBranchIslands. - // This must be adjacent to bBrlRemainEip -- see "pbPool". - DETOUR_IA64_BUNDLE bBranchIslands[DETOUR_IA64_INSTRUCTIONS_PER_BUNDLE]; - - // Target of brl inserted in target function - DETOUR_IA64_BUNDLE bAllocFrame; // alloc frame - DETOUR_IA64_BUNDLE bSave37to39; // save r37, r38, r39. - DETOUR_IA64_BUNDLE bSave34to36; // save r34, r35, r36. - DETOUR_IA64_BUNDLE bSaveGPto33; // save gp, r32, r33. - DETOUR_IA64_BUNDLE bMovlDetourGp; // set detour GP. - DETOUR_IA64_BUNDLE bCallDetour; // call detour. - DETOUR_IA64_BUNDLE bPopFrameGp; // pop frame and restore gp. - DETOUR_IA64_BUNDLE bReturn; // return to caller. - - PLABEL_DESCRIPTOR pldTrampoline; - - BYTE rbRestore[sizeof(DETOUR_IA64_BUNDLE)]; // original target bundle. - BYTE cbRestore; // size of original target code. - BYTE cbCode; // size of moved target code. - _DETOUR_ALIGN rAlign[14]; // instruction alignment array. - PBYTE pbRemain; // first instruction after moved code. [free list] - PBYTE pbDetour; // first instruction of detour function. - PPLABEL_DESCRIPTOR ppldDetour; // [pbDetour,gpDetour] - PPLABEL_DESCRIPTOR ppldTarget; // [pbTarget,gpDetour] -}; - -C_ASSERT(sizeof(DETOUR_IA64_BUNDLE) == 16); -C_ASSERT(sizeof(_DETOUR_TRAMPOLINE) == 256 + DETOUR_IA64_INSTRUCTIONS_PER_BUNDLE * 16); - -enum { - SIZE_OF_JMP = sizeof(DETOUR_IA64_BUNDLE) -}; - -inline PBYTE detour_skip_jmp(PBYTE pPointer, PVOID *ppGlobals) -{ - PBYTE pGlobals = NULL; - PBYTE pbCode = NULL; - - if (pPointer != NULL) { - PPLABEL_DESCRIPTOR ppld = (PPLABEL_DESCRIPTOR)pPointer; - pbCode = (PBYTE)ppld->EntryPoint; - pGlobals = (PBYTE)ppld->GlobalPointer; - } - if (ppGlobals != NULL) { - *ppGlobals = pGlobals; - } - if (pbCode == NULL) { - return NULL; - } - - DETOUR_IA64_BUNDLE *pb = (DETOUR_IA64_BUNDLE *)pbCode; - - // IA64 Local Import Jumps look like: - // addl r2=ffffffff`ffe021c0, gp ;; - // ld8 r2=[r2] - // nop.i 0 ;; - // - // ld8 r3=[r2], 8 ;; - // ld8 gp=[r2] - // mov b6=r3, +0 - // - // nop.m 0 - // nop.i 0 - // br.cond.sptk.few b6 - // - - // 002024000200100b - if ((pb[0].wide[0] & 0xfffffc000603ffff) == 0x002024000200100b && - pb[0].wide[1] == 0x0004000000203008 && - pb[1].wide[0] == 0x001014180420180a && - pb[1].wide[1] == 0x07000830c0203008 && - pb[2].wide[0] == 0x0000000100000010 && - pb[2].wide[1] == 0x0080006000000200) { - - ULONG64 offset = - ((pb[0].wide[0] & 0x0000000001fc0000) >> 18) | // imm7b - ((pb[0].wide[0] & 0x000001ff00000000) >> 25) | // imm9d - ((pb[0].wide[0] & 0x00000000f8000000) >> 11); // imm5c - if (pb[0].wide[0] & 0x0000020000000000) { // sign - offset |= 0xffffffffffe00000; - } - PBYTE pbTarget = pGlobals + offset; - DETOUR_TRACE(("%p: potential import jump, target=%p\n", pb, pbTarget)); - - if (detour_is_imported(pbCode, pbTarget) && *(PBYTE*)pbTarget != NULL) { - DETOUR_TRACE(("%p: is import jump, label=%p\n", pb, *(PBYTE *)pbTarget)); - - PPLABEL_DESCRIPTOR ppld = (PPLABEL_DESCRIPTOR)*(PBYTE *)pbTarget; - pbCode = (PBYTE)ppld->EntryPoint; - pGlobals = (PBYTE)ppld->GlobalPointer; - if (ppGlobals != NULL) { - *ppGlobals = pGlobals; - } - } - } - return pbCode; -} - - -inline void detour_find_jmp_bounds(PBYTE pbCode, - PDETOUR_TRAMPOLINE *ppLower, - PDETOUR_TRAMPOLINE *ppUpper) -{ - (void)pbCode; - *ppLower = (PDETOUR_TRAMPOLINE)(ULONG_PTR)0x0000000000080000; - *ppUpper = (PDETOUR_TRAMPOLINE)(ULONG_PTR)0xfffffffffff80000; -} - -inline BOOL detour_does_code_end_function(PBYTE pbCode) -{ - // Routine not needed on IA64. - (void)pbCode; - return FALSE; -} - -inline ULONG detour_is_code_filler(PBYTE pbCode) -{ - // Routine not needed on IA64. - (void)pbCode; - return 0; -} - -#endif // DETOURS_IA64 - -#ifdef DETOURS_ARM - -struct _DETOUR_TRAMPOLINE -{ - // A Thumb-2 instruction can be 2 or 4 bytes long. - BYTE rbCode[62]; // target code + jmp to pbRemain - BYTE cbCode; // size of moved target code. - BYTE cbCodeBreak; // padding to make debugging easier. - BYTE rbRestore[22]; // original target code. - BYTE cbRestore; // size of original target code. - BYTE cbRestoreBreak; // padding to make debugging easier. - _DETOUR_ALIGN rAlign[8]; // instruction alignment array. - PBYTE pbRemain; // first instruction after moved code. [free list] - PBYTE pbDetour; // first instruction of detour function. -}; - -C_ASSERT(sizeof(_DETOUR_TRAMPOLINE) == 104); - -enum { - SIZE_OF_JMP = 8 -}; - -inline PBYTE align4(PBYTE pValue) -{ - return (PBYTE)(((ULONG)pValue) & ~(ULONG)3u); -} - -inline ULONG fetch_thumb_opcode(PBYTE pbCode) -{ - ULONG Opcode = *(UINT16 *)&pbCode[0]; - if (Opcode >= 0xe800) { - Opcode = (Opcode << 16) | *(UINT16 *)&pbCode[2]; - } - return Opcode; -} - -inline void write_thumb_opcode(PBYTE &pbCode, ULONG Opcode) -{ - if (Opcode >= 0x10000) { - *((UINT16*&)pbCode)++ = Opcode >> 16; - } - *((UINT16*&)pbCode)++ = (UINT16)Opcode; -} - -PBYTE detour_gen_jmp_immediate(PBYTE pbCode, PBYTE *ppPool, PBYTE pbJmpVal) -{ - PBYTE pbLiteral; - if (ppPool != NULL) { - *ppPool = *ppPool - 4; - pbLiteral = *ppPool; - } - else { - pbLiteral = align4(pbCode + 6); - } - - *((PBYTE*&)pbLiteral) = DETOURS_PBYTE_TO_PFUNC(pbJmpVal); - LONG delta = pbLiteral - align4(pbCode + 4); - - write_thumb_opcode(pbCode, 0xf8dff000 | delta); // LDR PC,[PC+n] - - if (ppPool == NULL) { - if (((ULONG)pbCode & 2) != 0) { - write_thumb_opcode(pbCode, 0xdefe); // BREAK - } - pbCode += 4; - } - return pbCode; -} - -inline PBYTE detour_gen_brk(PBYTE pbCode, PBYTE pbLimit) -{ - while (pbCode < pbLimit) { - write_thumb_opcode(pbCode, 0xdefe); - } - return pbCode; -} - -inline PBYTE detour_skip_jmp(PBYTE pbCode, PVOID *ppGlobals) -{ - if (pbCode == NULL) { - return NULL; - } - if (ppGlobals != NULL) { - *ppGlobals = NULL; - } - - // Skip over the import jump if there is one. - pbCode = (PBYTE)DETOURS_PFUNC_TO_PBYTE(pbCode); - ULONG Opcode = fetch_thumb_opcode(pbCode); - - if ((Opcode & 0xfbf08f00) == 0xf2400c00) { // movw r12,#xxxx - ULONG Opcode2 = fetch_thumb_opcode(pbCode+4); - - if ((Opcode2 & 0xfbf08f00) == 0xf2c00c00) { // movt r12,#xxxx - ULONG Opcode3 = fetch_thumb_opcode(pbCode+8); - if (Opcode3 == 0xf8dcf000) { // ldr pc,[r12] - PBYTE pbTarget = (PBYTE)(((Opcode2 << 12) & 0xf7000000) | - ((Opcode2 << 1) & 0x08000000) | - ((Opcode2 << 16) & 0x00ff0000) | - ((Opcode >> 4) & 0x0000f700) | - ((Opcode >> 15) & 0x00000800) | - ((Opcode >> 0) & 0x000000ff)); - if (detour_is_imported(pbCode, pbTarget)) { - PBYTE pbNew = *(PBYTE *)pbTarget; - pbNew = DETOURS_PFUNC_TO_PBYTE(pbNew); - DETOUR_TRACE(("%p->%p: skipped over import table.\n", pbCode, pbNew)); - return pbNew; - } - } - } - } - return pbCode; -} - -inline void detour_find_jmp_bounds(PBYTE pbCode, - PDETOUR_TRAMPOLINE *ppLower, - PDETOUR_TRAMPOLINE *ppUpper) -{ - // We have to place trampolines within +/- 2GB of code. - ULONG_PTR lo = detour_2gb_below((ULONG_PTR)pbCode); - ULONG_PTR hi = detour_2gb_above((ULONG_PTR)pbCode); - DETOUR_TRACE(("[%p..%p..%p]\n", lo, pbCode, hi)); - - *ppLower = (PDETOUR_TRAMPOLINE)lo; - *ppUpper = (PDETOUR_TRAMPOLINE)hi; -} - - -inline BOOL detour_does_code_end_function(PBYTE pbCode) -{ - ULONG Opcode = fetch_thumb_opcode(pbCode); - if ((Opcode & 0xffffff87) == 0x4700 || // bx - (Opcode & 0xf800d000) == 0xf0009000) { // b - return TRUE; - } - if ((Opcode & 0xffff8000) == 0xe8bd8000) { // pop {...,pc} - __debugbreak(); - return TRUE; - } - if ((Opcode & 0xffffff00) == 0x0000bd00) { // pop {...,pc} - __debugbreak(); - return TRUE; - } - return FALSE; -} - -inline ULONG detour_is_code_filler(PBYTE pbCode) -{ - if (pbCode[0] == 0x00 && pbCode[1] == 0xbf) { // nop. - return 2; - } - if (pbCode[0] == 0x00 && pbCode[1] == 0x00) { // zero-filled padding. - return 2; - } - return 0; -} - -#endif // DETOURS_ARM - -#ifdef DETOURS_ARM64 - -struct _DETOUR_TRAMPOLINE -{ - // An ARM64 instruction is 4 bytes long. - // - // The overwrite is always composed of 3 instructions (12 bytes) which perform an indirect jump - // using _DETOUR_TRAMPOLINE::pbDetour as the address holding the target location. - // - // Copied instructions can expand. - // - // The scheme using MovImmediate can cause an instruction - // to grow as much as 6 times. - // That would be Bcc or Tbz with a large address space: - // 4 instructions to form immediate - // inverted tbz/bcc - // br - // - // An expansion of 4 is not uncommon -- bl/blr and small address space: - // 3 instructions to form immediate - // br or brl - // - // A theoretical maximum for rbCode is thefore 4*4*6 + 16 = 112 (another 16 for jmp to pbRemain). - // - // With literals, the maximum expansion is 5, including the literals: 4*4*5 + 16 = 96. - // - // The number is rounded up to 128. m_rbScratchDst should match this. - // - BYTE rbCode[128]; // target code + jmp to pbRemain - BYTE cbCode; // size of moved target code. - BYTE cbCodeBreak[3]; // padding to make debugging easier. - BYTE rbRestore[24]; // original target code. - BYTE cbRestore; // size of original target code. - BYTE cbRestoreBreak[3]; // padding to make debugging easier. - _DETOUR_ALIGN rAlign[8]; // instruction alignment array. - PBYTE pbRemain; // first instruction after moved code. [free list] - PBYTE pbDetour; // first instruction of detour function. -}; - -C_ASSERT(sizeof(_DETOUR_TRAMPOLINE) == 184); - -enum { - SIZE_OF_JMP = 12 -}; - -inline ULONG fetch_opcode(PBYTE pbCode) -{ - return *(ULONG *)pbCode; -} - -inline void write_opcode(PBYTE &pbCode, ULONG Opcode) -{ - *(ULONG *)pbCode = Opcode; - pbCode += 4; -} - -struct ARM64_INDIRECT_JMP { - struct { - ULONG Rd : 5; - ULONG immhi : 19; - ULONG iop : 5; - ULONG immlo : 2; - ULONG op : 1; - } ardp; - - struct { - ULONG Rt : 5; - ULONG Rn : 5; - ULONG imm : 12; - ULONG opc : 2; - ULONG iop1 : 2; - ULONG V : 1; - ULONG iop2 : 3; - ULONG size : 2; - } ldr; - - ULONG br; -}; - -#pragma warning(push) -#pragma warning(disable:4201) - -union ARM64_INDIRECT_IMM { - struct { - ULONG64 pad : 12; - ULONG64 adrp_immlo : 2; - ULONG64 adrp_immhi : 19; - }; - - LONG64 value; -}; - -#pragma warning(pop) - -PBYTE detour_gen_jmp_indirect(BYTE *pbCode, ULONG64 *pbJmpVal) -{ - // adrp x17, [jmpval] - // ldr x17, [x17, jmpval] - // br x17 - - struct ARM64_INDIRECT_JMP *pIndJmp; - union ARM64_INDIRECT_IMM jmpIndAddr; - - jmpIndAddr.value = (((LONG64)pbJmpVal) & 0xFFFFFFFFFFFFF000) - - (((LONG64)pbCode) & 0xFFFFFFFFFFFFF000); - - pIndJmp = (struct ARM64_INDIRECT_JMP *)pbCode; - pbCode = (BYTE *)(pIndJmp + 1); - - pIndJmp->ardp.Rd = 17; - pIndJmp->ardp.immhi = jmpIndAddr.adrp_immhi; - pIndJmp->ardp.iop = 0x10; - pIndJmp->ardp.immlo = jmpIndAddr.adrp_immlo; - pIndJmp->ardp.op = 1; - - pIndJmp->ldr.Rt = 17; - pIndJmp->ldr.Rn = 17; - pIndJmp->ldr.imm = (((ULONG64)pbJmpVal) & 0xFFF) / 8; - pIndJmp->ldr.opc = 1; - pIndJmp->ldr.iop1 = 1; - pIndJmp->ldr.V = 0; - pIndJmp->ldr.iop2 = 7; - pIndJmp->ldr.size = 3; - - pIndJmp->br = 0xD61F0220; - - return pbCode; -} - -PBYTE detour_gen_jmp_immediate(PBYTE pbCode, PBYTE *ppPool, PBYTE pbJmpVal) -{ - PBYTE pbLiteral; - if (ppPool != NULL) { - *ppPool = *ppPool - 8; - pbLiteral = *ppPool; - } - else { - pbLiteral = pbCode + 8; - } - - *((PBYTE*&)pbLiteral) = pbJmpVal; - LONG delta = (LONG)(pbLiteral - pbCode); - - write_opcode(pbCode, 0x58000011 | ((delta / 4) << 5)); // LDR X17,[PC+n] - write_opcode(pbCode, 0xd61f0000 | (17 << 5)); // BR X17 - - if (ppPool == NULL) { - pbCode += 8; - } - return pbCode; -} - -inline PBYTE detour_gen_brk(PBYTE pbCode, PBYTE pbLimit) -{ - while (pbCode < pbLimit) { - write_opcode(pbCode, 0xd4100000 | (0xf000 << 5)); - } - return pbCode; -} - -inline INT64 detour_sign_extend(UINT64 value, UINT bits) -{ - const UINT left = 64 - bits; - const INT64 m1 = -1; - const INT64 wide = (INT64)(value << left); - const INT64 sign = (wide < 0) ? (m1 << left) : 0; - return value | sign; -} - -inline PBYTE detour_skip_jmp(PBYTE pbCode, PVOID *ppGlobals) -{ - if (pbCode == NULL) { - return NULL; - } - if (ppGlobals != NULL) { - *ppGlobals = NULL; - } - - // Skip over the import jump if there is one. - pbCode = (PBYTE)pbCode; - ULONG Opcode = fetch_opcode(pbCode); - - if ((Opcode & 0x9f00001f) == 0x90000010) { // adrp x16, IAT - ULONG Opcode2 = fetch_opcode(pbCode + 4); - - if ((Opcode2 & 0xffe003ff) == 0xf9400210) { // ldr x16, [x16, IAT] - ULONG Opcode3 = fetch_opcode(pbCode + 8); - - if (Opcode3 == 0xd61f0200) { // br x16 - -/* https://static.docs.arm.com/ddi0487/bb/DDI0487B_b_armv8_arm.pdf - The ADRP instruction shifts a signed, 21-bit immediate left by 12 bits, adds it to the value of the program counter with - the bottom 12 bits cleared to zero, and then writes the result to a general-purpose register. This permits the - calculation of the address at a 4KB aligned memory region. In conjunction with an ADD (immediate) instruction, or - a Load/Store instruction with a 12-bit immediate offset, this allows for the calculation of, or access to, any address - within +/- 4GB of the current PC. - -PC-rel. addressing - This section describes the encoding of the PC-rel. addressing instruction class. The encodings in this section are - decoded from Data Processing -- Immediate on page C4-226. - Add/subtract (immediate) - This section describes the encoding of the Add/subtract (immediate) instruction class. The encodings in this section - are decoded from Data Processing -- Immediate on page C4-226. - Decode fields - Instruction page - op - 0 ADR - 1 ADRP - -C6.2.10 ADRP - Form PC-relative address to 4KB page adds an immediate value that is shifted left by 12 bits, to the PC value to - form a PC-relative address, with the bottom 12 bits masked out, and writes the result to the destination register. - ADRP ,