stevemk14ebr / polyhook_2_0 Goto Github PK
View Code? Open in Web Editor NEWC++20, x86/x64 Hooking Libary v2.0
License: MIT License
C++20, x86/x64 Hooking Libary v2.0
License: MIT License
In the CapstoneDisassembler I have a special case to read the memory destination of the jump type 0xFF25 [pointer_dest]. This was not done for Zydis because i assumed the library handled this, but have discovered a crash which suggests i need to do the same for ZydisDisassembler. Marking as todo.
Due to msvc optimizations this is essentially required when compiling in x64 Release mode due to:
PolyHook_2_0/UnitTests/TestDetourx64.cpp
Line 113 in 1acd4cb
I notice this was raised before here: #85
I believe this is a bug, I cannot get a project using x64detour to build without first including <functional>
. I can confirm the project is setup correctly and is using c++17
.
The include was removed here: a467313#diff-40ff9b9e776492b722f585ee7ec75ff6e30e2db476ce0a9ca3eb3df69d4f038e
I believe tests still pass because catch.hpp
happens to include functional
, and it's included first here and in the other test file:
Thanks for the great library.
Error C2661 'PLH::HWBreakPointHook::HWBreakPointHook': no overloaded function takes 2 arguments
hwBpHook = std::make_sharedPLH::HWBreakPointHook((char*)&hookMeCallbackHWBP, (char*)&hookMeCallbackHWBP);
Hi,
I really don't understand how the spoof of the return address is handled. I'm checking the unit test
https://github.com/stevemk14ebr/PolyHook_2_0/blob/master/UnitTests/TestDetourNoTDx86.cpp
and I've made a working example, but it is not working. Can you explain a little bit more how it is done? In my example, I've used the ILCallback as you use them on your example, but after that I'm not sure how the spoof is done.
Edit: My final interest is spoof the return address inside the image of the hooked function
Usable to fight hook restoration.
Hi, is there a similar hook in polyhook?
https://github.com/sr-tream/ClassicArrow/blob/master/ccallhook.cpp#L3-L48
Severity Code Description Project File Line Suppression State
Error (active) E1097 unknown attribute "no_init_all" ExampleProject C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\um\winnt.h 7597
Error LNK2001 unresolved external symbol "public: virtual class std::vector<class PLH::Instruction,class std::allocator<class PLH::Instruction> > __thiscall PLH::CapstoneDisassembler::disassemble(unsigned __int64,unsigned __int64,unsigned __int64)" (?disassemble@CapstoneDisassembler@PLH@@UAE?AV?$vector@VInstruction@PLH@@V?$allocator@VInstruction@PLH@@@std@@@std@@_K00@Z) ExampleProject C:\Users\mcskyblock\Desktop\nerd\PolyHook_2_0\ExampleProject\ExampleProject\build32\ExampleProject\ExampleProject.obj 1
Error LNK2019 unresolved external symbol "public: virtual bool __thiscall PLH::Detour::unHook(void)" (?unHook@Detour@PLH@@UAE_NXZ) referenced in function _main ExampleProject C:\Users\mcskyblock\Desktop\nerd\PolyHook_2_0\ExampleProject\ExampleProject\build32\ExampleProject\ExampleProject.obj 1
Error LNK2019 unresolved external symbol "public: __thiscall PLH::x86Detour::x86Detour(char const *,char const *,unsigned __int64 *,class PLH::ADisassembler &)" (??0x86Detour@PLH@@QAE@PBD0PA_KAAVADisassembler@1@@Z) referenced in function _main ExampleProject C:\Users\mcskyblock\Desktop\nerd\PolyHook_2_0\ExampleProject\ExampleProject\build32\ExampleProject\ExampleProject.obj 1
Error LNK2019 unresolved external symbol "public: virtual bool __thiscall PLH::x86Detour::hook(void)" (?hook@x86Detour@PLH@@UAE_NXZ) referenced in function _main ExampleProject C:\Users\mcskyblock\Desktop\nerd\PolyHook_2_0\ExampleProject\ExampleProject\build32\ExampleProject\ExampleProject.obj 1
Error LNK1120 4 unresolved externals ExampleProject C:\Users\mcskyblock\Desktop\nerd\PolyHook_2_0\ExampleProject\ExampleProject\build32\ExampleProject\Debug\ExampleProject.exe 1
the pollyhook works but the example project one i cant compile..
i manage to make it work on my pc.. but on my vps
Is there a reason to have m_disasm
as an ADisassembler&
, instead of a smart pointer? This will prevent any potential lifetime issues.
Hello Stevenmk14ebr, very nice library you have here. I have been using PolyHook 1.0 as a reference to enhance my memory leak detection library which hooks malloc/calloc/realloc/free. I was using your code to help write my own routines which perform the ASM relocation of the trampoline code (up till now I was using hardcoded trampolines).
In Linux32 when hooking Malloc the first instructions of the function are:
0xf7e70df0 <malloc>: push esi
0xf7e70df1 <malloc+1>: push ebx
0xf7e70df2 <malloc+2>: call 0xf7f2102b
0xf7e70df7 <malloc+7>: add ebx,0x134209
0xf7e70dfd <malloc+13>: sub esp,0x14
0xf7e70e00 <malloc+16>: mov eax,DWORD PTR [ebx-0xa4]
The function at 0xf7f2102b
is actually just a function that puts EIP into EBX:
0xf7f2102b: mov ebx,DWORD PTR [esp]
0xf7f2102e: ret
So malloc is actually grabbing an object relative to EIP -- but it's done through calling a function that moves EIP into the EBX register and then addressing relative to EBX.
The code from PolyHook 1.0 obviously didn't handle this as it only adjusted explicit EIP/RIP relative addressing, I haven't been able to test PolyHook 2.0 but it looks like it might have the same issue.
Originally I was using a hand-crafted trampoline which explicitly placed the object in question into EBX, but if I want to dynamically generate the trampoline I obviously cannot do that anymore.
Do you know of any way around this issue? Or maybe I'm just stupid and PolyHook 2.0 handles this elegantly and I'm just missing it?
I was just curious if there is a way to hook directx when an overlay already has it hooked (ie discord, steam, etc) if I do not disable these overlays then polyhook will fail with "[!] Error: Function too small to hook safely!" is there anything that I should be doing differently so that I can hook when overlays have hooked as well?
(this is currently happening on directx11 x64, doesnt seem to have any issue with directx9 and x86)
c:\users\cestl\desktop\polyhook_2_0\catch.hpp(2481): error C2220: warning treated as error - no 'object' file generated (compiling source file C:\Users\cestl\Desktop\PolyHook_2_0\UnitTests\TestDetourx64.cpp)
c:\users\cestl\desktop\polyhook_2_0\catch.hpp(2481): warning C4819: The file contains a character that cannot be represented in the current code page (936). Save the file in Unicode format to prevent data loss (compiling source file C:\Users\cestl\Desktop\PolyHook_2_0\UnitTests\TestDetourx64.cpp)
c:\users\cestl\desktop\polyhook_2_0\catch.hpp(2481): error C2220: warning treated as error - no 'object' file generated (compiling source file C:\Users\cestl\Desktop\PolyHook_2_0\UnitTests\TestMemProtector.cpp)
c:\users\cestl\desktop\polyhook_2_0\catch.hpp(2481): warning C4819: The file contains a character that cannot be represented in the current code page (936). Save the file in Unicode format to prevent data loss (compiling source file C:\Users\cestl\Desktop\PolyHook_2_0\UnitTests\TestMemProtector.cpp)
c:\users\cestl\desktop\polyhook_2_0\catch.hpp(2481): error C2220: warning treated as error - no 'object' file generated (compiling source file C:\Users\cestl\Desktop\PolyHook_2_0\UnitTests\TestDisassembler.cpp)
c:\users\cestl\desktop\polyhook_2_0\catch.hpp(2481): warning C4819: The file contains a character that cannot be represented in the current code page (936). Save the file in Unicode format to prevent data loss (compiling source file C:\Users\cestl\Desktop\PolyHook_2_0\UnitTests\TestDisassembler.cpp)
c:\users\cestl\desktop\polyhook_2_0\catch.hpp(2481): error C2220: warning treated as error - no 'object' file generated (compiling source file C:\Users\cestl\Desktop\PolyHook_2_0\UnitTests\TestVFuncSwapHook.cpp)
c:\users\cestl\desktop\polyhook_2_0\catch.hpp(2481): warning C4819: The file contains a character that cannot be represented in the current code page (936). Save the file in Unicode format to prevent data loss (compiling source file C:\Users\cestl\Desktop\PolyHook_2_0\UnitTests\TestVFuncSwapHook.cpp)
c:\users\cestl\desktop\polyhook_2_0\catch.hpp(2481): error C2220: warning treated as error - no 'object' file generated (compiling source file C:\Users\cestl\Desktop\PolyHook_2_0\UnitTests\TestVTableSwapHook.cpp)
c:\users\cestl\desktop\polyhook_2_0\catch.hpp(2481): warning C4819: The file contains a character that cannot be represented in the current code page (936). Save the file in Unicode format to prevent data loss (compiling source file C:\Users\cestl\Desktop\PolyHook_2_0\UnitTests\TestVTableSwapHook.cpp)
c:\users\cestl\desktop\polyhook_2_0\catch.hpp(2481): error C2220: warning treated as error - no 'object' file generated (compiling source file C:\Users\cestl\Desktop\PolyHook_2_0\MainTests.cpp)
c:\users\cestl\desktop\polyhook_2_0\catch.hpp(2481): warning C4819: The file contains a character that cannot be represented in the current code page (936). Save the file in Unicode format to prevent data loss (compiling source file C:\Users\cestl\Desktop\PolyHook_2_0\MainTests.cpp)
c:\users\cestl\desktop\polyhook_2_0\catch.hpp(2481): error C2220: warning treated as error - no 'object' file generated (compiling source file C:\Users\cestl\Desktop\PolyHook_2_0\UnitTests\TestIatHook.cpp)
c:\users\cestl\desktop\polyhook_2_0\catch.hpp(2481): warning C4819: The file contains a character that cannot be represented in the current code page (936). Save the file in Unicode format to prevent data loss (compiling source file C:\Users\cestl\Desktop\PolyHook_2_0\UnitTests\TestIatHook.cpp)
c:\users\cestl\desktop\polyhook_2_0\catch.hpp(2481): error C2220: warning treated as error - no 'object' file generated (compiling source file C:\Users\cestl\Desktop\PolyHook_2_0\UnitTests\TestEatHook.cpp)
c:\users\cestl\desktop\polyhook_2_0\catch.hpp(2481): warning C4819: The file contains a character that cannot be represented in the current code page (936). Save the file in Unicode format to prevent data loss (compiling source file C:\Users\cestl\Desktop\PolyHook_2_0\UnitTests\TestEatHook.cpp)
TestDetourNoTDx64.cpp
CapstoneDisassembler.cpp
c:\users\cestl\desktop\polyhook_2_0\catch.hpp(2481): error C2220: warning treated as error - no 'object' file generated (compiling source file C:\Users\cestl\Desktop\PolyHook_2_0\UnitTests\TestDetourNoTDx64.cpp)
c:\users\cestl\desktop\polyhook_2_0\catch.hpp(2481): warning C4819: The file contains a character that cannot be represented in the current code page (936). Save the file in Unicode format to prevent data loss (compiling source file C:\Users\cestl\Desktop\PolyHook_2_0\UnitTests\TestDetourNoTDx64.cpp)
MemProtector.cpp
TestEffectTracker.cpp
PageAllocator.cpp
ADetour.cpp
x64Detour.cpp
c:\users\cestl\desktop\polyhook_2_0\asmjit\src\asmjit\x86\x86globals.h(1447): warning C4819: The file contains a character that cannot be represented in the current code page (936). Save the file in Unicode format to prevent data loss (compiling source file C:\Users\cestl\Desktop\PolyHook_2_0\UnitTests\TestDetourNoTDx64.cpp)
x86Detour.cpp
AVehHook.cpp
BreakPointHook.cpp
HWBreakPointHook.cpp
VTableSwapHook.cpp
VFuncSwapHook.cpp
EatHook.cpp
IatHook.cpp
ILCallback.cpp
c:\users\cestl\desktop\polyhook_2_0\asmjit\src\asmjit\x86\x86globals.h(1447): error C2220: warning treated as error - no 'object' file generated (compiling source file C:\Users\cestl\Desktop\PolyHook_2_0\sources\ILCallback.cpp)
c:\users\cestl\desktop\polyhook_2_0\asmjit\src\asmjit\x86\x86globals.h(1447): warning C4819: The file contains a character that cannot be represented in the current code page (936). Save the file in Unicode format to prevent data loss (compiling source file C:\Users\cestl\Desktop\PolyHook_2_0\sources\ILCallback.cpp)
Build failed.
Recently I've been trying to hook winsock's connect
function to mine in order to manipulate a socket's endpoint.
In order to do that I'm using a DLL injected to Firefox's plugin-container process, that imports winsock's connect
function. I've tried to run an example with printf
instead of connect
, and that one works, unfortunately, connect
fails with Cannot fixup IP relative data operation, relocation beyond displacement size
. Is there any way to fix this or will I have to use EAT hooking?
Here's the code I'm using:
DWORD connect_hook(LPVOID lpParam) {
PLH::CapstoneDisassembler dis(PLH::Mode::x64);
auto addr = GetProcAddress(GetModuleHandle("ws2_32.dll"), "connect");
auto det = new PLH::x64Detour((char *) addr, (char *) &conn, &hookConnectTramp, dis);
if(det->hook())
MessageBox(nullptr, reinterpret_cast<LPCSTR>("OK"), reinterpret_cast<LPCSTR>("OK"), MB_OK);
else {
PLH::Error err = PLH::ErrorLog::singleton().pop();
std::string s = "FAIL: " + err.msg;
MessageBox(nullptr, reinterpret_cast<LPCSTR>(s.c_str()), reinterpret_cast<LPCSTR>("FAIL"), MB_OK);
}
return 1;
}
Some IP relative data instructions (non control flow modifying) fail to have their offset adjusted. Noticed this in x64 SIMD register accesses. Needs fixed, or at least should fail gracefully.
[+] Info: Prologue to overwrite:
7ff643d0f2c0 [3]: 0f 57 d2 xorps xmm2, xmm2
7ff643d0f2c3 [7]: 48 8d 0d 96 79 07 00 lea rcx, [rip + 0x77996] -> 7ff643d86c60
7ff643d0f2ca [4]: f3 0f 5a d0 cvtss2sd xmm2, xmm0
7ff643d0f2ce [8]: f3 0f 58 05 ea 61 07 00 addss xmm0, dword ptr [rip + 0x761ea] -> 7ff643d854c0
[+] Info: Trampoline:
1877c6f9910 [3]: 0f 57 d2 xorps xmm2, xmm2
1877c6f9913 [7]: 48 8d 0d 96 79 07 00 lea rcx, [rip + 0x77996] -> 1877c7712b0
1877c6f991a [4]: f3 0f 5a d0 cvtss2sd xmm2, xmm0
1877c6f991e [8]: f3 0f 58 05 ea 61 07 00 addss xmm0, dword ptr [rip + 0x761ea] -> 1877c76fb10
1877c6f9926 [6]: ff 25 46 00 00 00 jmp qword ptr [rip + 0x46] -> 1877c6f9972
My game crashes when I load my dll. I tried using PageGuard hook using other lib and it works but it makes the game very slow. Now im trying to use polyhook’s breakpoint.
`#include <windows.h>
#include "polyhook/include/polyhook2/Exceptions/AVehHook.hpp"
#include "polyhook/include/polyhook2/Exceptions/BreakPointHook.hpp"
#include "polyhook/include/polyhook2/Exceptions/HWBreakPointHook.hpp"
#include "polyhook/include/polyhook2/TestEffectTracker.hpp"
#include
#pragma comment(lib, "polyhook/lib/PolyHook_2.lib")
DWORD norecoil = 0x00853B30;
DWORD jmpnorecoil = 0x00853B35;
float ChingCho = 0;
std::shared_ptrPLH::BreakPointHook BPHook;
EffectTracker effects3;
using namespace std;
_declspec (naked) NOINLINE int Kongchi()
{
printf("Nodelay Activated.. \n");
_asm
{
movss xmm0, ChingCho
movss[esi + 0x58], xmm0
jmp jmpNDL2
}
}
NOINLINE int HookCallBackHWBP()
{
auto protObj = BPHook->getProtectionObject();
//effects3.PeakEffect().trigger();
return Kongchi();
}
DWORD WINAPI STEB(HMODULE hModule)
{
BPHook = std::make_sharedPLH::BreakPointHook((uint32_t)norecoil, (uint32_t)HookCallBackHWBP);
cout << "Preparing" << endl;
BPHook->hook();
cout << "Hooked" << endl;
return 1;
}
BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
DisableThreadLibraryCalls(hModule);
AllocConsole();
FILE* fDummy;
freopen_s(&fDummy, "CONOUT$", "w", stdout);
freopen_s(&fDummy, "CONOUT$", "w", stderr);
freopen_s(&fDummy, "CONIN$", "r", stdin);
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)STEB, NULL, 0, NULL);
}
return TRUE;
} `
if use this way get address can I hook it?
typedef DWORD(__stdcall *pNtTerminateProcess)(HANDLE, UINT);
pNtTerminateProcess fnNtTerminateProcess = (pNtTerminateProcess)GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")), "NtTerminateProcess");
my code:
typedef NTSTATUS(WINAPI tNtTerminateProcess)
(
HANDLE ProcessHandle,
NTSTATUS ExitStatus
);
tNtTerminateProcess oNtTerminateProcessFunc;
NTSTATUS WINAPI hkNtTerminateProcess(HANDLE ProcessHandle,NTSTATUS ExitStatus)
{
printf("11111");
MessageBox(NULL, L"I'm alive!", L"Hello", 0);
return 0;
}
PLH::IatHook hook("ntdll.dll", "NtTerminateProcess", (uint64_t)&hkNtTerminateProcess, (uint64_t)&oNtTerminateProcessFunc, L"NtTerminateProcess");
I use it hook internetConnectW bug have some problem
// ExampleProject.cpp : Defines the entry point for the application.
//
#include
#include <windows.h>
#include <Wininet.h>
#include
#include "polyhook2/CapstoneDisassembler.hpp"
#include "polyhook2/Detour/x64Detour.hpp"
#include "polyhook2/PE/IATHook.hpp"
using std::string;
using namespace std;
#pragma comment(lib,"asmjit.lib")
#pragma comment(lib,"capstone.lib")
#pragma comment(lib,"PolyHook_2.lib")
#pragma comment(lib,"Zycore.lib")
#pragma comment(lib,"Zydis.lib")
#include
string WCharToMByte(LPCWSTR lpcwszStr)
{
string str;
DWORD dwMinSize = 0;
LPSTR lpszStr = NULL;
dwMinSize = WideCharToMultiByte(CP_OEMCP, NULL, lpcwszStr, -1, NULL, 0, NULL, FALSE);
if (0 == dwMinSize)
{
return FALSE;
}
lpszStr = new char[dwMinSize];
WideCharToMultiByte(CP_OEMCP, NULL, lpcwszStr, -1, lpszStr, dwMinSize, NULL, FALSE);
str = lpszStr;
delete[] lpszStr;
return str;
}
typedef HINTERNET(WINAPI *tInternetConnectWFunc)
(
HINTERNET hInternet,
LPCWSTR lpszServerName,
INTERNET_PORT nServerPort,
LPCWSTR lpszUserName,
LPCWSTR lpszPassword,
DWORD dwService,
DWORD dwFlags,
DWORD_PTR dwContext
);
//tInternetConnectWFunc oInternetConnectW;
tInternetConnectWFunc oInterConnectWFunc;
uint64_t oInternetConnectW;
uint64_t oGetCurrentThreadID;
NOINLINE DWORD __stdcall hkGetCurrentThreadId() {
return 0;
}
HINTERNET WINAPI hkInternetConnectW(
HINTERNET hInternet,
LPCWSTR lpszServerName,
INTERNET_PORT nServerPort,
LPCWSTR lpszUserName,
LPCWSTR lpszPassword,
DWORD dwService,
DWORD dwFlags,
DWORD_PTR dwContext
)
{
LPCWSTR url = lpszServerName;
MessageBox(NULL, L"I'm alive!", L"Hello", 0);
if (WCharToMByte(url).find("baidu.com") >= 0)
{
url = L"www.sogou.com";
}
oInterConnectWFunc(hInternet, url, nServerPort, lpszUserName, lpszPassword, dwService, dwFlags, dwContext);
}
PLH::CapstoneDisassembler dis(PLH::Mode::x64);
//PLH::IatHook hook("kernel32.dll", "GetCurrentThreadId", (char*)&hkGetCurrentThreadId, (uint64_t*)&oGetCurrentThreadID, L"");
PLH::IatHook hook("wininet.dll", "InternetConnectW", (uint64_t)&hkInternetConnectW, (uint64_t*)&oInterConnectWFunc, L"");
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
MessageBox(NULL, L"IN HOOK", L"HOOK", 0);
if (hook.hook() == true) {
MessageBox(NULL, L"hook success", L"HOOKED", 0);
//std::cout << "hook success." << std::endl;
}
else
{
MessageBox(NULL, L"hook error", L"HOOKED", 0);
}
}
break;
case DLL_PROCESS_DETACH:
hook.unHook();
break;
}
return TRUE;
}
hook error I dont know why
I am testing PLH::detour::hook() to hook kernel32::BindIoCompletionCallback() api on Win10.
On 32bit code, everything works fine, however, on Win64, the api BindIoCompletionCallback() can be hooked successfully ( PLH::x64Detour::hook() returns true), but the app crashes immediately when calling the original /detoured api.
00007FFA69484260 | 48:83EC 28 | sub rsp,28 | kernel32::BindIoCompletionCallback
00007FFA69484264 | 48:FF15 BDEB0500 | call qword ptr ds:[<&RtlSetIoCompletionCallback>] |
00007FFA6948426B | 0F1F4400 00 | nop dword ptr ds:[rax+rax],eax |
00007FFA69484270 | 85C0 | test eax,eax |
00007FFA69484272 | 0F88 24230100 | js kernel32.7FFA6949659C |
00007FFA69484278 | B8 01000000 | mov eax,1 |
00007FFA6948427D | 48:83C4 28 | add rsp,28 |
00007FFA69484281 | C3 | ret
00007FFA69484260 | FF25 85FFFFFF | jmp qword ptr ds:[&my_hooked_api]
00007FFA69484266 | 66:90 | nop |
00007FFA69484268 | 66:90 | nop |
00007FFA6948426A | 90 | nop |
00007FFA6948426B | 0F1F4400 00 | nop dword ptr ds:[rax+rax],eax |
00007FFA69484270 | 85C0 | test eax,eax |
00007FFA69484272 | 0F88 24230100 | js kernel32.7FFA6949659C |
00007FFA69484278 | B8 01000000 | mov eax,1 |
00007FFA6948427D | 48:83C4 28 | add rsp,28 |
00007FFA69484281 | C3 | ret
The original code:
0000018BB4ACB430 | 48:83EC 28 | sub rsp,28 |
0000018BB4ACB434 | 48:FF15 06000000 | call qword ptr ds:[18BB4ACB441] |
0000018BB4ACB43B | FF25 46000000 | jmp qword ptr ds:[18BB4ACB487] |
0000018BB4ACB441 | FF25 38000000 | jmp qword ptr ds:[18BB4ACB47F] |
0000018BB4ACB447 | CD CD | int CD |
0000018BB4ACB449 | CD CD | int CD |
0000018BB4ACB44B | CD CD | int CD |
0000018BB4ACB44D | CD CD | int CD |
0000018BB4ACB44F | CD CD | int CD |
0000018BB4ACB451 | CD CD | int CD |
0000018BB4ACB453 | CD CD | int CD |
0000018BB4ACB455 | CD CD | int CD |
0000018BB4ACB457 | CD CD | int CD |
0000018BB4ACB459 | CD CD | int CD |
When running the hooked api, the memory access violation exception occurs.
SIGSEGV - Segmentation violation signal
From the debugger, the code hits invalid region:
qword ptr ds:[0000018BB4ACB441]=CDCD0000003825FF
There is nothing special in my_hooked_api test, just calling the original code.
The same test code works fine on Win32, and the 32bit kernel32::BindIoCompletionCallback code looks normal and easy to be detoured.
I am not sure if this api's code pattern is supported by the current detour-hook algorithm?
Hey, was playing with the zydis branch, and noticed that one of the unit tests is failing in Release build mode.
Here is some of the output I snipped:
[+] Info: Original function:
7ff693f93470 [3]: 0f 57 d2 xorps xmm2, xmm2
7ff693f93473 [7]: 48 8d 0d f6 62 13 00 lea rcx, [rip + 0x1362f6] -> 7ff6940c9770
7ff693f9347a [4]: f3 0f 5a d0 cvtss2sd xmm2, xmm0
7ff693f9347e [8]: f3 0f 58 05 22 65 13 00 addss xmm0, dword ptr [rip + 0x136522] -> 7ff6940c99a8
7ff693f93486 [3]: 0f 57 c9 xorps xmm1, xmm1
7ff693f93489 [5]: 66 49 0f 7e d0 movq r8, xmm2
7ff693f9348e [4]: f3 0f 5a c8 cvtss2sd xmm1, xmm0
7ff693f93492 [5]: 66 48 0f 7e ca movq rdx, xmm1
7ff693f93497 [5]: e9 14 43 ff ff jmp 0x7ff693f877b0 -> 7ff693f877b0
7ff693f9349c [1]: cc int3
7ff693f9349d [1]: cc int3
7ff693f9349e [1]: cc int3
7ff693f9349f [1]: cc int3
7ff693f934a0 [8]: c7 44 24 08 01 00 00 00 mov dword ptr [rsp + 8], 1
7ff693f934a8 [5]: 44 8b 44 24 08 mov r8d, dword ptr [rsp + 8]
7ff693f934ad [4]: 4c 8b 0c 24 mov r9, qword ptr [rsp]
7ff693f934b1 [3]: 44 03 c1 add r8d, ecx
7ff693f934b4 [4]: 8b 54 24 08 mov edx, dword ptr [rsp + 8]
7ff693f934b8 [7]: 48 8d 0d a1 62 13 00 lea rcx, [rip + 0x1362a1] -> 7ff6940c9760
7ff693f934bf [5]: e9 ec 42 ff ff jmp 0x7ff693f877b0 -> 7ff693f877b0
7ff693f934c4 [1]: cc int3
7ff693f934c5 [1]: cc int3
7ff693f934c6 [1]: cc int3
7ff693f934c7 [1]: cc int3
7ff693f934c8 [1]: cc int3
7ff693f934c9 [1]: cc int3
7ff693f934ca [1]: cc int3
7ff693f934cb [1]: cc int3
7ff693f934cc [1]: cc int3
7ff693f934cd [1]: cc int3
7ff693f934ce [1]: cc int3
7ff693f934cf [1]: cc int3
7ff693f934d0 [4]: 48 83 ec 48 sub rsp, 0x48
[+] Info: Prologue to overwrite:
7ff693f93470 [3]: 0f 57 d2 xorps xmm2, xmm2
7ff693f93473 [7]: 48 8d 0d f6 62 13 00 lea rcx, [rip + 0x1362f6] -> 7ff6940c9770
7ff693f9347a [4]: f3 0f 5a d0 cvtss2sd xmm2, xmm0
7ff693f9347e [8]: f3 0f 58 05 22 65 13 00 addss xmm0, dword ptr [rip + 0x136522] -> 7ff6940c99a8
[!] Error: Cannot fixup IP relative data operation, needed disp. beyond max disp range: lea rcx, [rip + 0x1362f6] needed: 0x00007dc53f591820 raw: 0xffff823ac0a6e7e0 max: 0x000000007fffffff
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PolyHook_2.exe is a Catch v2.6.0 host application.
Run with -? for options
-------------------------------------------------------------------------------
Minimal ILCallback
Floating argument
-------------------------------------------------------------------------------
..\UnitTests\TestDetourNoTDx64.cpp(99)
...............................................................................
..\UnitTests\TestDetourNoTDx64.cpp(105): FAILED:
REQUIRE( detour.hook() == true )
with expansion:
false == true
===============================================================================
test cases: 19 | 18 passed | 1 failed
assertions: 974 | 973 passed | 1 failed
Note that this does not happen with Debug builds.
Here are the commands I used to configure and build PolyHook:
cd PolyHook_2_-
mkdir build
cd build
cmake -GNinja -DCMAKE_BUILD_TYPE=Release ..
cmake --build .
.\PolyHook_2.exe
PLH::CapstoneDisassembler dis(PLH::Mode::x64); PLH::x64Detour detour((uint64_t)pInterface[42], (uint64_t)hkEndScene, (uint64_t*)&EndScene, dis); detour.hook();
crash game:
[+] pInterface[42] Addr: 0x7ffd2350d3a0
[+] Info: Original function:
7ffd2350d3a0 [2]: 40 57 push rdi
7ffd2350d3a2 [4]: 48 83 ec 40 sub rsp, 0x40
7ffd2350d3a6 [9]: 48 c7 44 24 28 fe ff ff ff mov qword ptr [rsp + 0x28], -2
7ffd2350d3af [5]: 48 89 5c 24 50 mov qword ptr [rsp + 0x50], rbx
7ffd2350d3b4 [3]: 48 8b f9 mov rdi, rcx
7ffd2350d3b7 [3]: 48 8b c1 mov rax, rcx
7ffd2350d3ba [4]: 48 8d 51 08 lea rdx, [rcx + 8]
7ffd2350d3be [3]: 48 f7 d8 neg rax
7ffd2350d3c1 [3]: 48 1b db sbb rbx, rbx
7ffd2350d3c4 [3]: 48 23 da and rbx, rdx
7ffd2350d3c7 [5]: 48 89 5c 24 30 mov qword ptr [rsp + 0x30], rbx
7ffd2350d3cc [5]: 83 64 24 38 00 and dword ptr [rsp + 0x38], 0
7ffd2350d3d1 [4]: 83 7b 28 00 cmp dword ptr [rbx + 0x28], 0
7ffd2350d3d5 [6]: 0f 85 67 9b 03 00 jne 0x7ffd23546f42 -> 7ffd23546f42
7ffd2350d3db [3]: 8b 47 4c mov eax, dword ptr [rdi + 0x4c]
7ffd2350d3de [3]: 83 e0 02 and eax, 2
7ffd2350d3e1 [2]: 84 c0 test al, al
7ffd2350d3e3 [6]: 0f 85 68 9b 03 00 jne 0x7ffd23546f51 -> 7ffd23546f51
7ffd2350d3e9 [6]: 8b 87 0c 41 00 00 mov eax, dword ptr [rdi + 0x410c]
7ffd2350d3ef [2]: a8 01 test al, 1
7ffd2350d3f1 [6]: 0f 84 6e 9b 03 00 je 0x7ffd23546f65 -> 7ffd23546f65
7ffd2350d3f7 [7]: f6 87 08 41 00 00 04 test byte ptr [rdi + 0x4108], 4
7ffd2350d3fe [6]: 0f 85 94 9b 03 00 jne 0x7ffd23546f98 -> 7ffd23546f98[+] Info: Prologue to overwrite:
7ffd2350d3a0 [2]: 40 57 push rdi
7ffd2350d3a2 [4]: 48 83 ec 40 sub rsp, 0x40
7ffd2350d3a6 [9]: 48 c7 44 24 28 fe ff ff ff mov qword ptr [rsp + 0x28], -2
7ffd2350d3af [5]: 48 89 5c 24 50 mov qword ptr [rsp + 0x50], rbx[+] Info: Jmp To Prol:
1e048a3f204 [6]: ff 25 46 00 00 00 jmp [1e048a3f250] ->7ffd2350d3b4
1e048a3f250 [8]: b4 d3 50 23 fd 7f 00 00 dest holder[+] Info: Trampoline:
1e048a3f1f0 [2]: 40 57 push rdi
1e048a3f1f2 [4]: 48 83 ec 40 sub rsp, 0x40
1e048a3f1f6 [9]: 48 c7 44 24 28 fe ff ff ff mov qword ptr [rsp + 0x28], -2
1e048a3f1ff [5]: 48 89 5c 24 50 mov qword ptr [rsp + 0x50], rbx
1e048a3f204 [6]: ff 25 46 00 00 00 jmp qword ptr [rip + 0x46] -> 1e048a3f250
1e048a3f20a [3]: 30 42 e0 xor byte ptr [rdx - 0x20], al
1e048a3f20d [2]: 01 00 add dword ptr [rax], eax
1e048a3f20f [2]: 00 01 add byte ptr [rcx], al
1e048a3f211 [2]: 00 00 add byte ptr [rax], al
1e048a3f213 [2]: 00 fc add ah, bh
1e048a3f215 [2]: 7f 00 jg 0x1e048a3f217 -> 1e048a3f217
1e048a3f217 [2]: 00 00 add byte ptr [rax], al
1e048a3f219 [2]: 00 00 add byte ptr [rax], al
1e048a3f21b [2]: 00 00 add byte ptr [rax], al
1e048a3f21d [2]: 00 00 add byte ptr [rax], al
1e048a3f21f [2]: 00 00 add byte ptr [rax], al
1e048a3f221 [2]: 00 00 add byte ptr [rax], al
1e048a3f223 [2]: 00 01 add byte ptr [rcx], al
1e048a3f225 [2]: 00 00 add byte ptr [rax], al
1e048a3f227 [2]: 00 01 add byte ptr [rcx], al
1e048a3f229 [2]: 00 00 add byte ptr [rax], al
1e048a3f22b [2]: 00 00 add byte ptr [rax], al
1e048a3f22d [2]: 00 00 add byte ptr [rax], al
1e048a3f22f [2]: 00 00 add byte ptr [rax], al
1e048a3f231 [2]: 00 00 add byte ptr [rax], al
1e048a3f233 [2]: 00 00 add byte ptr [rax], al
1e048a3f235 [2]: 00 00 add byte ptr [rax], al
1e048a3f237 [2]: 00 00 add byte ptr [rax], al
1e048a3f239 [2]: 00 00 add byte ptr [rax], al
1e048a3f23b [2]: 00 00 add byte ptr [rax], al
1e048a3f23d [2]: 00 00 add byte ptr [rax], al
1e048a3f23f [2]: 00 00 add byte ptr [rax], al
1e048a3f241 [2]: 00 00 add byte ptr [rax], al
1e048a3f243 [2]: 00 00 add byte ptr [rax], al
1e048a3f245 [2]: 00 00 add byte ptr [rax], al
1e048a3f247 [2]: 00 00 add byte ptr [rax], al
1e048a3f249 [2]: 00 00 add byte ptr [rax], al
1e048a3f24b [2]: 00 00 add byte ptr [rax], al
1e048a3f24d [2]: 00 00 add byte ptr [rax], al
1e048a3f24f [7]: 00 b4 d3 50 23 fd 7f add byte ptr [rbx + rdx*8 + 0x7ffd2350], dh
1e048a3f256 [2]: 00 00 add byte ptr [rax], al[+] Info: Trampoline Jmp Tbl:
any way to get it fixed?
*same with Present..
In the for-loop searching for allocatable memory there is a possible infinite loop. In case the memory region is either not free of is smaller than the size required, continue
is executed without incrementing the address.
Lines 127 to 128 in 64ca107
Because the PLH::ErrorLog class is retreived through a static local variable by the singleton() method it was expected that only one instance could ever exist. However, C++ doesn't define any guarantees across module (dll) boundaries and so in practice two instances can exist. Therefore setting the log level may fail to set the level on the correct instance, and the desirable instance cannot be retreived.
This may be fixed by moving the implementation to a source file so the implementation is shared.
Hello, just real quick thank you for this amazing repository.
I have built PolyHook in x64-Release mode and now I'm attempting to include it into my project, but whenever I attempt to build the project I get this build output:
ILCallback.cpp
ILCallback.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: unsigned int __cdecl asmjit::BaseCompiler::_newStack(class asmjit::BaseMem &,unsigned int,unsigned int,char const *)" (__imp_?_newStack@BaseCompiler@asmjit@@QEAAIAEAVBaseMem@2@IIPEBD@Z)
ILCallback.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: unsigned int __cdecl asmjit::BaseCompiler::_newReg(class asmjit::BaseReg &,unsigned int,char const *)" (__imp_?_newReg@BaseCompiler@asmjit@@QEAAIAEAVBaseReg@2@IPEBD@Z)
ILCallback.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: unsigned int __cdecl asmjit::BaseCompiler::_newReg(class asmjit::BaseReg &,unsigned int,char const *,char *)" (__imp_?_newReg@BaseCompiler@asmjit@@QEAAIAEAVBaseReg@2@IPEBDPEAD@Z)
ILCallback.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: class asmjit::FuncCallNode * __cdecl asmjit::BaseCompiler::addCall(unsigned int,struct asmjit::Operand_ const &,struct asmjit::FuncSignature const &)" (__imp_?addCall@BaseCompiler@asmjit@@QEAAPEAVFuncCallNode@2@IAEBUOperand_@2@AEBUFuncSignature@2@@Z)
ILCallback.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: class asmjit::FuncRetNode * __cdecl asmjit::BaseCompiler::addRet(struct asmjit::Operand_ const &,struct asmjit::Operand_ const &)" (__imp_?addRet@BaseCompiler@asmjit@@QEAAPEAVFuncRetNode@2@AEBUOperand_@2@0@Z)
ILCallback.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: unsigned int __cdecl asmjit::BaseCompiler::setArg(unsigned int,class asmjit::BaseReg const &)" (__imp_?setArg@BaseCompiler@asmjit@@QEAAIIAEBVBaseReg@2@@Z)
ILCallback.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: unsigned int __cdecl asmjit::BaseCompiler::endFunc(void)" (__imp_?endFunc@BaseCompiler@asmjit@@QEAAIXZ)
ILCallback.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: class asmjit::FuncNode * __cdecl asmjit::BaseCompiler::addFunc(struct asmjit::FuncSignature const &)" (__imp_?addFunc@BaseCompiler@asmjit@@QEAAPEAVFuncNode@2@AEBUFuncSignature@2@@Z)
ILCallback.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: void __cdecl asmjit::ArchInfo::init(unsigned int,unsigned int)" (__imp_?init@ArchInfo@asmjit@@QEAAXII@Z)
ILCallback.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: bool __cdecl asmjit::FuncCallNode::_setArg(unsigned int,struct asmjit::Operand_ const &)" (__imp_?_setArg@FuncCallNode@asmjit@@QEAA_NIAEBUOperand_@2@@Z)
ILCallback.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: virtual __cdecl asmjit::StringLogger::~StringLogger(void)" (__imp_??1StringLogger@asmjit@@UEAA@XZ)
ILCallback.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __cdecl asmjit::StringLogger::StringLogger(void)" (__imp_??0StringLogger@asmjit@@QEAA@XZ)
ILCallback.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: virtual __cdecl asmjit::x86::Assembler::~Assembler(void)" (__imp_??1Assembler@x86@asmjit@@UEAA@XZ)
ILCallback.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __cdecl asmjit::x86::Assembler::Assembler(class asmjit::CodeHolder *)" (__imp_??0Assembler@x86@asmjit@@QEAA@PEAVCodeHolder@2@@Z)
ILCallback.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: virtual __cdecl asmjit::x86::Compiler::~Compiler(void)" (__imp_??1Compiler@x86@asmjit@@UEAA@XZ)
ILCallback.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __cdecl asmjit::x86::Compiler::Compiler(class asmjit::CodeHolder *)" (__imp_??0Compiler@x86@asmjit@@QEAA@PEAVCodeHolder@2@@Z)
ILCallback.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: unsigned int __cdecl asmjit::CodeHolder::copyFlattenedData(void *,unsigned __int64,unsigned int)" (__imp_?copyFlattenedData@CodeHolder@asmjit@@QEAAIPEAX_KI@Z)
ILCallback.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: unsigned int __cdecl asmjit::CodeHolder::relocateToBase(unsigned __int64)" (__imp_?relocateToBase@CodeHolder@asmjit@@QEAAI_K@Z)
ILCallback.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: unsigned __int64 __cdecl asmjit::CodeHolder::codeSize(void)const " (__imp_?codeSize@CodeHolder@asmjit@@QEBA_KXZ)
ILCallback.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: unsigned int __cdecl asmjit::CodeHolder::flatten(void)" (__imp_?flatten@CodeHolder@asmjit@@QEAAIXZ)
ILCallback.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: unsigned int __cdecl asmjit::CodeHolder::resolveUnresolvedLinks(void)" (__imp_?resolveUnresolvedLinks@CodeHolder@asmjit@@QEAAIXZ)
ILCallback.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: void __cdecl asmjit::CodeHolder::setLogger(class asmjit::Logger *)" (__imp_?setLogger@CodeHolder@asmjit@@QEAAXPEAVLogger@2@@Z)
ILCallback.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: unsigned int __cdecl asmjit::CodeHolder::init(class asmjit::CodeInfo const &)" (__imp_?init@CodeHolder@asmjit@@QEAAIAEBVCodeInfo@2@@Z)
ILCallback.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __cdecl asmjit::CodeHolder::~CodeHolder(void)" (__imp_??1CodeHolder@asmjit@@QEAA@XZ)
ILCallback.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __cdecl asmjit::CodeHolder::CodeHolder(void)" (__imp_??0CodeHolder@asmjit@@QEAA@XZ)
ILCallback.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: unsigned int __cdecl asmjit::BaseBuilder::serialize(class asmjit::BaseEmitter *)" (__imp_?serialize@BaseBuilder@asmjit@@QEAAIPEAVBaseEmitter@2@@Z)
ILCallback.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: unsigned int __cdecl asmjit::BaseBuilder::runPasses(void)" (__imp_?runPasses@BaseBuilder@asmjit@@QEAAIXZ)
C:\Users\alxbrn\Desktop\plh\x64\Release\plh.dll : fatal error LNK1120: 27 unresolved externals
Aditional Dependencies:
capstone.lib;asmjit.lib;polyhook_2.lib;
I believe that I have missed some crucial information about how to use PolyHook correctly, any help is appreciated. (If full project is needed / more information, then please tell me)
#include <string>
#include <cstdio>
#include <Windows.h>
#include <polyhook2/Exceptions/BreakPointHook.hpp>
std::shared_ptr<PLH::BreakPointHook> bpHook;
DWORD NodelayBaseAddress = 0x009D5447;
DWORD returnAdress = 0x009D544C;
float delay = 0.0f;
NOINLINE _declspec(naked) void NodelayASM()
{
_asm
{
movss xmm0 , delay
movss[esi + 0x58], xmm0
jmp returnAdress
}
}
NOINLINE void NodelayCallBack()
{
auto protObj = bpHook->getProtectionObject();
NodelayASM();
}
void HookFunction()
{
bpHook = std::make_shared<PLH::BreakPointHook>(reinterpret_cast<char*>(&NodelayBaseAddress), reinterpret_cast<char*>(&NodelayCallBack));
bpHook->hook();
}
BOOL WINAPI DllMain(HINSTANCE hInstDll, DWORD dwReason, LPVOID lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
AllocConsole();
FILE* fDummy;
freopen_s(&fDummy, "CONOUT$", "w", stdout);
freopen_s(&fDummy, "CONOUT$", "w", stderr);
freopen_s(&fDummy, "CONIN$", "r", stdin);
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)HookFunction, NULL, 0, NULL);
}
return TRUE;
}
When i injecting the dll to the game its crashing i dont think its on BaseAddress or maybe im doing wrong?
I saw an issue like this before, but I seem to have the same issue. I use a very simple console application, that just prints a line with 1 extra character everytime... No threads or anything. Using a BreakPointHook, it works perfectly. Using HWBreakPointHook, not at all. Even though ->hook() returns true, it just doesn't get triggered... Is this a bug, or does something different need to be done when using HWBreakPointHook as opposed to BreakPointHook?
This "error" keeps popping up on hooking endscene, however everything works fine and as intended, just wondering if it is something I'm doing wrong? Not sure if this is related to #14 or not.
EffectTracker eatEffectTracker;
typedef void(__stdcall*tEatTestExport)(int a);
tEatTestExport oEatTestExport;
extern "C" __declspec(dllexport) int __stdcall EatTestExport(int a)
{
return a;
}
int __stdcall hkEatTestExport(int a)
{
MessageBox(0, "0", "0", 0);
eatEffectTracker.PeakEffect().trigger();
}
void main()
{
PLH::EatHook hook("EatTestExport", L"test.exe", (char*)&hkEatTestExport, (uint64_t*)&oEatTestExport);
hook.hook();
tEatTestExport pExport = (tEatTestExport)GetProcAddress(GetModuleHandle(nullptr), "EatTestExport");
eatEffectTracker.PushEffect();
pExport(1);
eatEffectTracker.PopEffect().didExecute();
hook.unHook();
}
Hey, I tried to Hook wglSwapBuffers (changing from MinHook to PolyHook, so nothing can get wrong huh), but ye - got hooked and literally nothing changed In process asm and it just doesnt work.
Used vcpkg.exe install polyhook2:x64-windows-static
to install this.
Then added VcpkgTriplet
in .vcxproj file.. Changed to Multi-threaded..
#include <windows.h>
#include <iostream>
#include <cstdarg>
#include <gl/gl.h>
#pragma comment(lib,"opengl32.lib")
#pragma comment(lib,"asmjit.lib")
#pragma comment(lib,"capstone.lib")
#pragma comment(lib,"PolyHook_2.lib")
#pragma comment(lib,"Zycore.lib")
#pragma comment(lib,"Zydis.lib")
#include <polyhook2/Detour/x64Detour.hpp>
#include <polyhook2/CapstoneDisassembler.hpp>
#include <fstream>
typedef BOOL(__stdcall * twglSwapBuffers) (_In_ HDC hDc);
twglSwapBuffers xwglSwapBuffers;
BOOL __stdcall hwglSwapBuffers(_In_ HDC hDc)
{
std::cout << "Hooked\n";
return xwglSwapBuffers(hDc);
}
DWORD WINAPI OpenglInit(__in LPVOID lpParameter)
{
AllocConsole();
FILE* in;
FILE* out;
freopen_s(&in, "conin$", "r", stdin);
freopen_s(&out, "conout$", "w", stdout);
freopen_s(&out, "conout$", "w", stderr);
PLH::CapstoneDisassembler dis(PLH::Mode::x64);
while (!GetModuleHandleW(L"OPENGL32.dll"))
{
std::cout << "Not found\n";
Sleep(100);
}
HMODULE hMod = GetModuleHandleW(L"OPENGL32.dll");
if (hMod)
{
void* ptr = GetProcAddress(hMod, "wglSwapBuffers");
uint64_t owglSwapBuffers = NULL;
std::cout << ptr << std::endl << &ptr;
PLH::x64Detour detour((char*)ptr, (char*)&hwglSwapBuffers, &owglSwapBuffers, dis);
if (detour.hook()) {
std::cout << "Hooked\n";
}
else {
std::cout << "Failed\n";
}
}
return 1;
}
BOOL __stdcall DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved)
{
switch(fdwReason)
{
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls (hinstDll);
CreateThread(0, 0, OpenglInit, 0, 0, 0);
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
Hi, I tried installing this using vcpkg and getting the following error when including x64Detour.hpp
:
I:\vcpkg\installed\x64-windows\include\x64Detour.hpp(13,10): fatal error C1083: Cannot open include file: 'headers/Detour/ADetour.hpp': No such file or directory
Looking at the include
folder of vcpkg:
and the content of x64Detour.hpp:
...
#include "headers/Detour/ADetour.hpp"
...
the Problem seems to be that files from headers/Detour/...
are here, but the folder structure was flattened (into vcpkg's include directory)?
If I somehow messed up any installation part, I'd appreciate a hint (I'm new to using vcpkg)
I want hook taskmgr.exe's NtTerminateProcess, i don't why it's not work(messagebox show hook success)
typedef NTSTATUS(WINAPI *tNtTerminateProcess)
(
HANDLE ProcessHandle,
NTSTATUS ExitStatus
);
tNtTerminateProcess oNtTerminateProcessFunc;
NTSTATUS WINAPI hkNtTerminateProcess(HANDLE ProcessHandle,NTSTATUS ExitStatus)
{
//g_inlineHookObj7.UnHook();
MessageBox(NULL, L"I'm alive!", L"Hello", 0);
return oNtTerminateProcessFunc(ProcessHandle, ExitStatus);
}
void PolyHook2Hook()
{
oNtTerminateProcessFunc = (tNtTerminateProcess)GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")), "NtTerminateProcess");
printf("123");
PLH::IatHook hook("ntdll.dll", "NtTerminateProcess", (uint64_t)&hkNtTerminateProcess, (uint64_t*)&oNtTerminateProcessFunc, L"NtTerminateProcess");
if (hook.hook() == true) {
MessageBox(NULL, L"hook success", L"HOOKED", 0);
std::cout << "hook success." << std::endl;
}
else
{
MessageBox(NULL, L"hook error", L"HOOKED", 0);
}
}
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
PolyHook2Hook();
//InlineHook();
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
When m_fnCallback in x86Detour points to a callback function that instead of traditional prologue begins with call unrelated_function
or jmp unrelated_function
, m_fnCallback is updated to point to unrelated_function
, causing the detour to be wrong.
m_fnCallback is updated to an incorrect resolved address here:
PolyHook_2_0/sources/x86Detour.cpp
Line 36 in 9455df9
Example code to reproduce the bug under MSVC (compiled in RelWithDebInfo cmake target. Debug target works as intended due to extended function prologue in h_hookPrintf):
// ExampleProject.cpp : Defines the entry point for the application.
//
#include "ExampleProject.h"
#include "polyhook2/CapstoneDisassembler.hpp"
#include "polyhook2/Detour/x86Detour.hpp"
#include <cstdarg>
bool someFlag = true;
bool someFlagGetter() {
return someFlag;
}
uint64_t hookPrintfTramp = NULL;
char buffer[512];
NOINLINE int __cdecl h_hookPrintf(const char* format, ...) {
if(!someFlagGetter()) {
puts("someFlag is disabled, returning early");
return 0;
}
puts("someFlag is enabled, continuing the hook");
va_list args;
va_start(args, format);
vsprintf_s(buffer, format, args);
va_end(args);
return PLH::FnCast(hookPrintfTramp, &printf)("INTERCEPTED YO:%s", buffer);
}
/** THIS EXAMPLE IS SETUP FOR x86. IT WILL CRASH IF YOU COMPILE IN x64**/
int main()
{
// Switch modes for x64
PLH::CapstoneDisassembler dis(PLH::Mode::x86);
PLH::x86Detour detour((char*)&printf, (char*)&h_hookPrintf, &hookPrintfTramp, dis);
detour.hook();
puts("calling hooked printf");
printf("%s %f\n", "hi", .5f);
detour.unHook();
puts("end");
getchar();
return 0;
}
Output in Debug target:
calling hooked printf
someFlag is enabled, continuing the hook
INTERCEPTED YO:hi 0.500000
end
Output in Release/RelWithDebInfo target:
calling hooked printf
end
What is the current alternative to the error "Cannot fixup IP relative data operation, needed disp. beyond max disp range: "?
I checked polyhook's "ADetour.cpp" and saw it is not yet ready to handle my target's pesky "lea r8,qword ptr ds:[rip + 0x603CF6]".
I want to patch a nullsub function in a process (address is base + 0x254b0):
004254b0 c3 RET
004254b1 cc ?? CCh
004254b2 cc ?? CCh
004254b3 cc ?? CCh
004254b4 cc ?? CCh
004254b5 cc ?? CCh
004254b6 cc ?? CCh
004254b7 cc ?? CCh
004254b8 cc ?? CCh
004254b9 cc ?? CCh
004254ba cc ?? CCh
004254bb cc ?? CCh
004254bc cc ?? CCh
004254bd cc ?? CCh
004254be cc ?? CCh
004254bf cc ?? CCh
PolyHook fails to hook the function (x86Detour returns false); my guess is that it needs to be padded so there is enough space to insert the jmp
instruction. How might I go about doing that without patching the binary file on disk?
PolyHook_2_0/sources/EatHook.cpp
Lines 101 to 106 in 007ce9d
std::wstring_view
in combination with std::wstring_view::compare
here?std::wstring_view baseModuleName(dte->BaseDllName.Buffer, dte->BaseDllName.Length / sizeof(wchar_t));
auto const icmp = [](wchar_t const& a, wchar_t const& b) noexcept -> bool { return towlower(a) == towlower(b); };
// try all modules if none given, otherwise only try specified
if (!moduleName.empty() && !std::equal(moduleName.cbegin(), moduleName.cend(), baseModuleName.cbegin(),
baseModuleName.cend(), icmp))
continue;
Haven't tested how it compares performance wise.
This is an excellent one in what I think is an open source hook library, but when I try to use it, I find that the project directory is confusing, and the complie script has some bugs on windows, can I reorganize and submit a PR?
cmake 太操蛋了,能不能转换成vs项目
When returning from main and with a logger set up, Polyhook2 will cause a crash which seems to originate from the PLH::Instruction vector.
I am building a 64 bit app that hooks LoadLibraryExW and I have built the 64 bit version of PLH which is linked against this app. It seems to occur with both Zydis and Capstone. I pasted my code from the project below, and the repo is here: https://github.com/m3chanical/LoadLibraryHook
I'm on Win 10 with 64gb ram and a Ryzen 5 2600. I'm building this within Visual Studio 2019 with the cmake project type.
In particular, the crashes will occur in two situations:
Here's a link to a pair of screenshots with the call stack from VS: https://imgur.com/a/AZimbEo
I'm not sure if these are two separate problems I'm having, but they both seem to be related to the instruction vector. I'm in the process of troubleshooting it, but I figured I'd create an issue in case there's something obvious I'm missing or something. I looked through the previous issues and didn't see anything related.
// LoadLibraryHook.cpp : Defines the entry point for the application.
//
#include <Windows.h>
#include <LoadLibraryHook.h>
#include <polyhook2/ZydisDisassembler.hpp>
#include <polyhook2/Detour/x64Detour.hpp>
#include <cstdarg>
#include <conio.h>
uint64_t hookLoadLibrary = NULL; // original LoadLibrary
// IDA: LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
HMODULE WINAPI hk_LoadLibrary(LPCWSTR lpLibFileName, HANDLE hfile, DWORD dwFlags)
{
printf("Loading file: %ws\n", lpLibFileName);
return PLH::FnCast(hookLoadLibrary, &LoadLibraryExW)(lpLibFileName, hfile, dwFlags);
}
int getch_noblock()
{
if (_kbhit())
return _getch();
return -1;
}
int main()
{
auto error_log = std::make_shared<PLH::ErrorLog>();
PLH::Log::registerLogger(error_log);
PLH::ZydisDisassembler dis(PLH::Mode::x64);
HMODULE k32 = GetModuleHandle("kernelbase.dll");
if (k32 == NULL)
return 0;
// all of the loadlibrary functions in kernel32/kernelbase end up calling LoadLibraryExW, which is the last step before ntdll.
auto load_lib_addr = GetProcAddress(k32, "LoadLibraryExW");
if (load_lib_addr == NULL)
return 0;
printf("LoadLibraryExW address in kernelbase.dll: %p\n", load_lib_addr);
PLH::x64Detour loadlib_detour(reinterpret_cast<uint64_t>(load_lib_addr), reinterpret_cast<uint64_t>(&hk_LoadLibrary), &hookLoadLibrary, dis);
loadlib_detour.hook();
LoadLibraryA("F:\\vs_projects\\test_inject\\x64\\Debug\\test_inject.dll");
while (true)
{
if (getch_noblock() != -1)
break;
}
loadlib_detour.unHook();
return 0;
}
I don't know, but the next RVA2VA looks unnecessary.
PolyHook_2_0/sources/EatHook.cpp
Line 150 in 8f8ad15
PLH::BreakPointHook crashes the program when the hooked function is called.
OS: Windows 10 Pro (20H2)
Memory: 32,0 GB
Processor: AMD Ryzen 7 3700X
#include <string>
#include <cstdio>
#include <Windows.h>
#include <polyhook2/Exceptions/BreakPointHook.hpp>
std::shared_ptr<PLH::BreakPointHook> bpHook;
NOINLINE int hookMe() {
volatile int i = 0;
i += 1;
i += 2;
return i;
}
NOINLINE int hookMeCallback() {
auto protObj = bpHook->getProtectionObject();
volatile int i = 0;
i += 1;
return hookMe();
}
int main(int, const char*[])
{
bpHook = std::make_shared<PLH::BreakPointHook>(reinterpret_cast<char*>(&hookMe), reinterpret_cast<char*>(&hookMeCallback));
if (!bpHook->hook())
{
std::cout << "[!] hook failed" << std::endl;
return 1;
}
std::cout << "[+] calling hooked fn" << std::endl;
// >>> Crash
const int result = hookMe();
if (result == 3) {
std::cout << "[+] test succeeded" << std::endl;
}
bpHook->unHook();
getchar();
return 0;
}
Repository: https://github.com/automata172/polyhook-veh-crash
LONG PLH::HWBreakPointHook::OnException(EXCEPTION_POINTERS* ExceptionInfo) {
if (ExceptionInfo->ExceptionRecord->ExceptionCode != EXCEPTION_SINGLE_STEP)
return EXCEPTION_CONTINUE_EXECUTION;
ExceptionInfo->ContextRecord->Dr7 &= ~(1ULL << (2 * m_regIdx));
ExceptionInfo->ContextRecord->XIP = (decltype(ExceptionInfo->ContextRecord->XIP))m_fnCallback;
return EXCEPTION_CONTINUE_EXECUTION;
}
I'd do if (ExceptionInfo->ExceptionRecord->ExceptionCode != EXCEPTION_SINGLE_STEP) return EXCEPTION_CONTINUE_SEARCH;
instead. Someone asked me why their hw:bp is crashing the application, after i looked at this code it was obvious because the application is intentionally triggering exceptions with instructions like hlt
or wbinvd
to change control flow to their VEH's, this here however will prevent those Exceptionhandlers from being called.
https://github.com/stevemk14ebr/PolyHook_2_0/blob/master/sources/ADetour.cpp
bool PLH::Detour::expandProlSelfJmps(insts_t& prol,
const insts_t& func,
uint64_t& minProlSz,
uint64_t& roundProlSz) {
const uint64_t prolStart = prol.front().getAddress();
branch_map_t branchMap = m_disasm.getBranchMap();
for (size_t i = 0; i < prol.size(); i++) {
auto inst = prol.at(i);
// is there a jump pointing at the current instruction?
if (branchMap.find(inst.getAddress()) == branchMap.end())
continue;
insts_t srcs = branchMap.at(inst.getAddress());
uint64_t maxAddr = 0;
for (const auto& src : srcs) {
const uint64_t srcEndAddr = src.getAddress() + src.size();
if (srcEndAddr > maxAddr)
maxAddr = srcEndAddr;
}
minProlSz = maxAddr - prolStart;
// expand prol by one entry size, may fail if prol too small
auto prolOpt = calcNearestSz(func, minProlSz, roundProlSz);
if (!prolOpt)
return false;
prol = *prolOpt;
}
return true;
}
Hello I have a question about this function.
My english is bad so I try to make a pseudo-example:
In this function what happens if:
prol[1] has a re-entrant jump at 0x22222222
prol[2] has a re-entrant jump at 0x11111111
when you are iterating prol[1] the minProlSz will be bigger than when iterating prol[2], but at the end of the loop minProlSz (and roundProlSz) will have the smaller size because prol[2] is the last of them and it just overrides it.
Can this happen or I'm missing something?
I really have no clue how to write this code. (Not good at learning...)
I want to use Capstone to implement a HOOK detection (to check if a particular function has an wrong jmp or others).
For example, if I want to check if GetCommandLineW is HOOK, what should I do? I tried a few methods, but it didn't seem to work. Going deeper, it was beyond the control of my brain.
So I can only come for help. Maybe you can give me some sample code ... or some tips. Thank you very much.
On x86 machines, the case where m_fnCallback < m_moduleBase
causes an integer underflow that leads to an unnecessary allocation of a trampoline.
PolyHook_2_0/sources/EatHook.cpp
Line 24 in 64ca107
Environment: Windows10 Visual Studio 2019 Community
I succeeded in compiling by adding "#include ", but I am having trouble because other users need to change the header when building.
How to use vmt hook? I have a pDevice (DirectX) address, how can I get present?
Hi. How to use polyhook to hook recv, which is by import ordinal?
What title says
include(ExternalProject)
ExternalProject_Add(polyhook
GIT_REPOSITORY https://github.com/stevemk14ebr/PolyHook_2_0
GIT_TAG "00709c8621af8a6f9e91200088178e6d9f751097"
INSTALL_COMMAND ""
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/external/polyhook
)
I can't seem to find a way to include the include dirs and link the outputted libs. No matter what I do, VS always puts the .lib in a Debug/Release folder.
Please propose new milestones and features for the project here. I want to create a queue of actionable tickets for myself and contributors to work on. What do you all want next, and in what order? Some potential ideas:
When running release version of PolyHook2_2.exe on Win10/x64, it crashes on section:
PolyHook_2_0/UnitTests/TestDetourNoTDx64.cpp
Line 102 in 146c97e
It is weird that if executing the single test case "Minimal ILCallback", it just works fine, but if running the whole test cases, it crashes (SIGSEG), the debug version also works fine.
After debugging the release version of binary, I found the memset() function is modified at runtime because of a code-cave-too-small issue. Other parts of unit-tests have corrupted the code before the test section is executed.
ref: randydu#2 (comment)
Cave finder only finds caves with contiguous 0x90 bytes. Extend it to find segments with multi-byte nops using ADisassembler::isPadBytes.
This is hard to solve generically as sequences that look like multi-byte nops can occur in the middle of functions or in data.
https://github.com/zyantific/zydis
Capstone has a very big size. It was used in x64dbg first and it was replaced with zydis.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.