Closed BullyWiiPlaza closed 1 year ago
In this case I need you to get the assembly of the function you're trying to hook on that random french guys machine.
If the logging is insufficient please submit a PR that adds it or debug the hooking under a debugger.
Since the default logging does not show any assembly, I'd have to make some changes for outputting the assembly.
Debugging directly on his machine would be troublesome but I might be able to achieve it if he's still interested in helping me out. However, we already know it fails at following the jmp: https://github.com/stevemk14ebr/PolyHook_2_0/blob/fecf3261d4fea2a448924df592179c9b0d7003ed/sources/x64Detour.cpp#L329 Disassembling does work successfully. Now that I think about it, it seems to be a similar issue as https://github.com/stevemk14ebr/PolyHook_2_0/pull/183. Maybe your thorough unit tests will have to be extended to catch more use cases.
Here's the improved logging output pull request: https://github.com/stevemk14ebr/PolyHook_2_0/pull/185
Here's the French guy's output with the logging changes applied:
[+] Info: m_fnAddress: 0x00007ff8341b4660
[+] Info: Original function:
7ff8341b4660 [5]: e9 69 c9 fc ff jmp 0x00007FF834180FCE -> 7ff834180fce
7ff8341b4665 [5]: 48 89 74 24 20 mov qword ptr ss:[rsp+0x20], rsi
7ff8341b466a [1]: 55 push rbp
7ff8341b466b [1]: 57 push rdi
7ff8341b466c [2]: 41 56 push r14
7ff8341b466e [5]: 48 8d 6c 24 90 lea rbp, ss:[rsp-0x70]
7ff8341b4673 [7]: 48 81 ec 70 01 00 00 sub rsp, 0x170
7ff8341b467a [7]: 48 8b 05 d7 ed 0b 00 mov rax, qword ptr ds:[0x00007FF834273458] -> 7ff834273458
7ff8341b4681 [3]: 48 33 c4 xor rax, rsp
7ff8341b4684 [4]: 48 89 45 60 mov qword ptr ss:[rbp+0x60], rax
7ff8341b4688 [3]: 45 33 f6 xor r14d, r14d
7ff8341b468b [5]: 44 89 44 24 48 mov dword ptr ss:[rsp+0x48], r8d
7ff8341b4690 [7]: 44 39 35 8d e9 0b 00 cmp dword ptr ds:[0x00007FF834273024], r14d -> 7ff834273024
7ff8341b4697 [3]: 41 8b f0 mov esi, r8d
7ff8341b469a [2]: 8b fa mov edi, edx
7ff8341b469c [4]: 89 54 24 40 mov dword ptr ss:[rsp+0x40], edx
7ff8341b46a0 [3]: 48 8b d9 mov rbx, rcx
7ff8341b46a3 [4]: 48 89 4d 20 mov qword ptr ss:[rbp+0x20], rcx
7ff8341b46a7 [5]: c6 44 24 50 00 mov byte ptr ss:[rsp+0x50], 0x00
7ff8341b46ac [6]: 0f 85 9e b4 02 00 jnz 0x00007FF8341DFB50 -> 7ff8341dfb50
7ff8341b46b2 [7]: f6 05 47 2b 0c 00 02 test byte ptr ds:[0x00007FF834277200], 0x02 -> 7ff834277200
7ff8341b46b9 [6]: 0f 85 1a b5 02 00 jnz 0x00007FF8341DFBD9 -> 7ff8341dfbd9
7ff8341b46bf [3]: 0f 57 c0 xorps xmm0, xmm0
[!] Warn: Couldn't decompile instructions at followed jmp
[!] Error: Prologue jmp resolution failed
Successfully hooked: 0
SEV: Prologue jmp resolution failed
Called count: 0
Called count: 0
Called count: 0
Called count: 0
Called count: 0
Unhooking...
[!] Error: Detour unhook failed: no hook present
Successfully unhooked: 0
SEV: Detour unhook failed: no hook present
Appuyez sur une touche pour continuer...
Full logging output on my PC:
[+] Info: m_fnAddress: 0x00007ffa567414c0
[+] Info: Original function:
7ffa567414c0 [5]: e9 05 f2 11 04 jmp 0x00007FFA5A8606CA -> 7ffa5a8606ca
7ffa567414c5 [5]: 48 89 74 24 20 mov qword ptr ss:[rsp+0x20], rsi
7ffa567414ca [1]: 55 push rbp
7ffa567414cb [1]: 57 push rdi
7ffa567414cc [2]: 41 56 push r14
7ffa567414ce [5]: 48 8d 6c 24 90 lea rbp, ss:[rsp-0x70]
7ffa567414d3 [7]: 48 81 ec 70 01 00 00 sub rsp, 0x170
7ffa567414da [7]: 48 8b 05 b7 8f 0c 00 mov rax, qword ptr ds:[0x00007FFA5680A498] -> 7ffa5680a498
7ffa567414e1 [3]: 48 33 c4 xor rax, rsp
7ffa567414e4 [4]: 48 89 45 60 mov qword ptr ss:[rbp+0x60], rax
7ffa567414e8 [3]: 45 33 f6 xor r14d, r14d
7ffa567414eb [5]: 44 89 44 24 48 mov dword ptr ss:[rsp+0x48], r8d
7ffa567414f0 [7]: 44 39 35 2d 8b 0c 00 cmp dword ptr ds:[0x00007FFA5680A024], r14d -> 7ffa5680a024
7ffa567414f7 [3]: 41 8b f0 mov esi, r8d
7ffa567414fa [2]: 8b fa mov edi, edx
7ffa567414fc [4]: 89 54 24 40 mov dword ptr ss:[rsp+0x40], edx
7ffa56741500 [3]: 48 8b d9 mov rbx, rcx
7ffa56741503 [4]: 48 89 4d 20 mov qword ptr ss:[rbp+0x20], rcx
7ffa56741507 [5]: c6 44 24 50 00 mov byte ptr ss:[rsp+0x50], 0x00
7ffa5674150c [6]: 0f 85 e2 a7 03 00 jnz 0x00007FFA5677BCF4 -> 7ffa5677bcf4
7ffa56741512 [7]: f6 05 a7 bf 0c 00 02 test byte ptr ds:[0x00007FFA5680D4C0], 0x02 -> 7ffa5680d4c0
7ffa56741519 [6]: 0f 85 64 a8 03 00 jnz 0x00007FFA5677BD83 -> 7ffa5677bd83
7ffa5674151f [3]: 0f 57 c9 xorps xmm1, xmm1
[+] Info: Prologue to overwrite:
7ff9a9d48f10 [5]: 48 89 6c 24 18 mov qword ptr ss:[rsp+0x18], rbp
7ff9a9d48f15 [5]: 48 89 74 24 20 mov qword ptr ss:[rsp+0x20], rsi
[+] Info: Trampoline address: 0x000001c094103000
[+] Info: Jmp To Prol:
1c09410300a [6]: ff 25 48 00 00 00 jmp [1c094103058] ->7ff9a9d48f1a
1c094103058 [8]: 1a 8f d4 a9 f9 7f 00 00 dest holder
[+] Info: m_trampoline: 0x000001c094103000
[+] Info: m_trampolineSz: 0x0065
[+] Info: Trampoline:
1c094103000 [5]: 48 89 6c 24 18 mov qword ptr ss:[rsp+0x18], rbp
1c094103005 [5]: 48 89 74 24 20 mov qword ptr ss:[rsp+0x20], rsi
1c09410300a [6]: ff 25 48 00 00 00 jmp qword ptr ds:[0x000001C094103058] -> 7ff9a9d48f1a
[+] Info: Hook instructions:
7ff9a9d48f10 [6]: ff 25 ea 70 08 80 jmp [7ff929dd0000] ->7ff971ad3d00
7ff929dd0000 [8]: 00 3d ad 71 f9 7f 00 00 dest holder
[+] Info: Hook size: 10
[+] Info: Prologue offset: 6
Successfully hooked: 1
Called count: 0
Called count: 60
Called count: 119
Called count: 178
Called count: 238
Unhooking...
Successfully unhooked: 1
Press any key to continue . . .
"Maybe your thorough unit tests will have to be extended to catch more use cases."
Your snarkiness is becoming annoying. For help, I suggest not doing that or I'll just ban you. I do this for free in my own time for fun.
I need you to post the assembly of the function you are trying to hook. The failure case is likely exercising an uncovered case. There's many reasons hooks can fail, for example this french mans machine may be using an external software which already hooks the function you're targeting. This would potentially insert a jmp in the prologue which polyhook may attempt to follow and fail for many different reasons.
I appreciate you providing your hooking code but it's the target assembly code you're trying to hook that is the information I need. You could grab this via a debugger or something if you don't wish you extend the logging, otherwise you could extend the logging temporary to print all the instructions that polyhook attempts to disassemble while following jumps in the prologue.
Yes, I understand, sorry for the inconvenience. If any other software is already hooking this function I'd still assume that PolyHook2 would find a way to still hook it without any issues. I decided to extend the logging further inside followJmp()
and it was quite interesting how often the code would follow a jmp on my machine:
[+] Info: Front instruction: 7ffa567414c0 [5]: e9 05 f2 11 04 jmp 0x00007FFA5A8606CA -> 7ffa5a8606ca
[+] Info: Destination: 0x00007ffa5a8606ca
[+] Info: Destination function instruction(s):
7ffa5a8606ca [5]: e9 41 88 47 99 jmp 0x00007FF9F3CD8F10 -> 7ff9f3cd8f10
7ffa5a8606cf [2]: 00 00 add byte ptr ds:[rax], al
7ffa5a8606d1 [2]: 00 00 add byte ptr ds:[rax], al
7ffa5a8606d3 [2]: 00 00 add byte ptr ds:[rax], al
7ffa5a8606d5 [2]: 00 00 add byte ptr ds:[rax], al
7ffa5a8606d7 [2]: 00 00 add byte ptr ds:[rax], al
7ffa5a8606d9 [2]: 00 00 add byte ptr ds:[rax], al
7ffa5a8606db [2]: 00 00 add byte ptr ds:[rax], al
7ffa5a8606dd [2]: 00 00 add byte ptr ds:[rax], al
7ffa5a8606df [2]: 00 00 add byte ptr ds:[rax], al
7ffa5a8606e1 [2]: 00 00 add byte ptr ds:[rax], al
7ffa5a8606e3 [2]: 00 00 add byte ptr ds:[rax], al
7ffa5a8606e5 [2]: 00 00 add byte ptr ds:[rax], al
7ffa5a8606e7 [2]: 00 00 add byte ptr ds:[rax], al
7ffa5a8606e9 [2]: 00 00 add byte ptr ds:[rax], al
7ffa5a8606eb [2]: 00 00 add byte ptr ds:[rax], al
7ffa5a8606ed [2]: 00 00 add byte ptr ds:[rax], al
7ffa5a8606ef [2]: 00 00 add byte ptr ds:[rax], al
7ffa5a8606f1 [2]: 00 00 add byte ptr ds:[rax], al
7ffa5a8606f3 [2]: 00 00 add byte ptr ds:[rax], al
7ffa5a8606f5 [2]: 00 00 add byte ptr ds:[rax], al
7ffa5a8606f7 [2]: 00 00 add byte ptr ds:[rax], al
7ffa5a8606f9 [2]: 00 00 add byte ptr ds:[rax], al
7ffa5a8606fb [2]: 00 00 add byte ptr ds:[rax], al
7ffa5a8606fd [2]: 00 00 add byte ptr ds:[rax], al
7ffa5a8606ff [6]: 00 89 54 24 10 53 add byte ptr ds:[rcx+0x53102454], cl
7ffa5a860705 [5]: e9 db 86 f0 fb jmp 0x00007FFA56768DE5 -> 7ffa56768de5
[+] Info: Front instruction: 7ffa5a8606ca [5]: e9 41 88 47 99 jmp 0x00007FF9F3CD8F10 -> 7ff9f3cd8f10
[+] Info: Destination: 0x00007ff9f3cd8f10
[+] Info: Destination function instruction(s):
7ff9f3cd8f10 [5]: 48 89 6c 24 18 mov qword ptr ss:[rsp+0x18], rbp
7ff9f3cd8f15 [5]: 48 89 74 24 20 mov qword ptr ss:[rsp+0x20], rsi
7ff9f3cd8f1a [2]: 41 56 push r14
7ff9f3cd8f1c [4]: 48 83 ec 20 sub rsp, 0x20
7ff9f3cd8f20 [3]: 41 8b e8 mov ebp, r8d
7ff9f3cd8f23 [2]: 8b f2 mov esi, edx
7ff9f3cd8f25 [3]: 4c 8b f1 mov r14, rcx
7ff9f3cd8f28 [4]: 41 f6 c0 01 test r8b, 0x01
7ff9f3cd8f2c [2]: 74 17 jz 0x00007FF9F3CD8F45 -> 7ff9f3cd8f45
7ff9f3cd8f2e [5]: 48 8b 6c 24 40 mov rbp, qword ptr ss:[rsp+0x40]
7ff9f3cd8f33 [5]: 48 8b 74 24 48 mov rsi, qword ptr ss:[rsp+0x48]
7ff9f3cd8f38 [4]: 48 83 c4 20 add rsp, 0x20
7ff9f3cd8f3c [2]: 41 5e pop r14
7ff9f3cd8f3e [7]: 48 ff 25 ab 96 0b 00 jmp qword ptr ds:[0x00007FF9F3D925F0] -> 7ff9f3d925f0
[+] Info: Front instruction: 7ff9f3cd8f10 [5]: 48 89 6c 24 18 mov qword ptr ss:[rsp+0x18], rbp
[+] Info: Instruction is NOT branching...
[+] Info: Prologue to overwrite:
7ff9f3cd8f10 [5]: 48 89 6c 24 18 mov qword ptr ss:[rsp+0x18], rbp
7ff9f3cd8f15 [5]: 48 89 74 24 20 mov qword ptr ss:[rsp+0x20], rsi
Here's my tester's output:
[+] Info: m_fnAddress: 0x00007ff8341b4660
[+] Info: Original function:
7ff8341b4660 [5]: e9 69 c9 fc ff jmp 0x00007FF834180FCE -> 7ff834180fce
7ff8341b4665 [5]: 48 89 74 24 20 mov qword ptr ss:[rsp+0x20], rsi
7ff8341b466a [1]: 55 push rbp
7ff8341b466b [1]: 57 push rdi
7ff8341b466c [2]: 41 56 push r14
7ff8341b466e [5]: 48 8d 6c 24 90 lea rbp, ss:[rsp-0x70]
7ff8341b4673 [7]: 48 81 ec 70 01 00 00 sub rsp, 0x170
7ff8341b467a [7]: 48 8b 05 d7 ed 0b 00 mov rax, qword ptr ds:[0x00007FF834273458] -> 7ff834273458
7ff8341b4681 [3]: 48 33 c4 xor rax, rsp
7ff8341b4684 [4]: 48 89 45 60 mov qword ptr ss:[rbp+0x60], rax
7ff8341b4688 [3]: 45 33 f6 xor r14d, r14d
7ff8341b468b [5]: 44 89 44 24 48 mov dword ptr ss:[rsp+0x48], r8d
7ff8341b4690 [7]: 44 39 35 8d e9 0b 00 cmp dword ptr ds:[0x00007FF834273024], r14d -> 7ff834273024
7ff8341b4697 [3]: 41 8b f0 mov esi, r8d
7ff8341b469a [2]: 8b fa mov edi, edx
7ff8341b469c [4]: 89 54 24 40 mov dword ptr ss:[rsp+0x40], edx
7ff8341b46a0 [3]: 48 8b d9 mov rbx, rcx
7ff8341b46a3 [4]: 48 89 4d 20 mov qword ptr ss:[rbp+0x20], rcx
7ff8341b46a7 [5]: c6 44 24 50 00 mov byte ptr ss:[rsp+0x50], 0x00
7ff8341b46ac [6]: 0f 85 9e b4 02 00 jnz 0x00007FF8341DFB50 -> 7ff8341dfb50
7ff8341b46b2 [7]: f6 05 47 2b 0c 00 02 test byte ptr ds:[0x00007FF834277200], 0x02 -> 7ff834277200
7ff8341b46b9 [6]: 0f 85 1a b5 02 00 jnz 0x00007FF8341DFBD9 -> 7ff8341dfbd9
7ff8341b46bf [3]: 0f 57 c0 xorps xmm0, xmm0
[+] Info: Front instruction: 7ff8341b4660 [5]: e9 69 c9 fc ff jmp 0x00007FF834180FCE -> 7ff834180fce
[+] Info: Destination: 0x00007ff834180fce
[+] Info: Destination function instruction(s):
[!] Warn: Couldn't decompile instructions at followed jmp
[!] Error: Prologue jmp resolution failed
Successfully hooked: 0
SEV: Prologue jmp resolution failed
Called count: 0
Called count: 0
Called count: 0
Called count: 0
Called count: 0
Unhooking...
[!] Error: Detour unhook failed: no hook present
Successfully unhooked: 0
SEV: Detour unhook failed: no hook present
Appuyez sur une touche pour continuer...
Would you be okay with also extending the logging in the followJmp()
code by default? I think that it's a great idea for other people who may want to debug issues or just for learning.
I'm really ripping my hair out here. I just investigated the issue on the French guy's machine using Cheat Engine and I noticed his address 0x00007ff834180fce
points to DiscordHook64.dll
:
7FF834180FCE - FF25 00000000 607852F5FF7F0000 - jmp DiscordHook64.dll+17860
One remarkable thing here is that this is an absolute jmp. For me at the same spot in the call chain, I see something like:
7FFA5A8606CA - E9 4188C6E9 - jmp gameoverlayrenderer64.dll+88F10
This is a relative jmp. For testing, I rewrote mine to be an absolute jmp as well:
7FFA5A8606CA - FF25 00000000 108F4C44FA7F0000 - jmp gameoverlayrenderer64.dll+88F10
The disassembler logging then said the following:
[+] Info: Destination function instruction(s):
7ffa5a8606ca [6]: ff 25 00 00 00 00 jmp qword ptr ds:[0x00007FFA5A8606D0] -> 7ffa444c8f10
7ffa5a8606d0 [6]: 10 8f 4c 44 fa 7f adc byte ptr ds:[rdi+0x7FFA444C], cl
It seems like Zydis disassembles absolute jmps wrongly in this context. However, resolving the jmp works as expected. I'd assume the output to only be a jmp instruction though. Does that really never cause any other problems?
I also checked the code at DiscordHook64.dll+17860 (7FFFF5527860)
and it seemed like normal code starting the stack frame with DiscordHook64.dll+17860 - 55 - push rbp
so this could've been hooked then if all would've went well.
At the end of the day I still couldn't reproduce the issue on my machine: The French guy's machine refuses to disassemble the jmp DiscordHook64.dll
instruction part and therefore fails to hook, while mine disassembles wrongly, but hooks correctly and all that. It's truly very strange to me. I hope you still have any ideas what the issue could be. Is it a Zydis bug? Do you call Zydis wrong? Is Zydis up-to-date? Is it a problem with the vcpkg port or my local setup?
The adc instruction you see following the ff25 is the immediate value encoding the final destination of the ff25. FF25 differs from E9 style jmp in how the destination is encoded.
FF25 goes to [destination] E9 goes to destination
Notice the brackets, it dereferenced the pointed to thing. So in this case FF2500000 says the pointer is immediately next, and the dereferenced value is stored there.
Specifically what is wrong I'm not sure I will have to test, I'm unfortunately not able to work on this until 2 weeks from now at the earliest.
It's good to know this is an external software causing the issue. As a temporary workaround the discord overlay can be disabled. I also would be curious to see if detours follows that ff25 or if it overwrites it (thus breaking discords hook)
If you could please have the Frenchman create a dump of the full process that will be enough information to triage this when I am free in the coming weeks.
https://www.ibm.com/support/pages/how-manually-generate-process-dump-using-process-explorer
Can be followed as a reference, be sure to make a full process dump. This would be done on the target process you are hooking/injecting into (likely a game as you're hooking directx and discord overlay is involved)
I think I fixed that problem in #186. I'm waiting for OP to test. The discord hook is at the very end of a memory region and polyhook attempts to read 100 = 0x64 bytes with ReadProcessMemory. It returns a failure "ERROR_PARTIAL_COPY", that is just skipped, but it doesn't actually read any bytes, even though it could've read 10-15 bytes. I've added some code to check for the end of a memory region and read less bytes. Of course, I maintained the pattern of not throwing any error/exception.
I can confirm via the French guy's machine that the fix by @BritishPiper works! Thanks again.
Hi,
I'm attempting to hook the function
D3D11Present
which works fine on my machine but a few users seem to run into the errorReproduction DLL code for DirectX11 hooking:
If I compile this simple C++ DLL code and inject it into some DirectX11 game, it fails with the error above for a French guy's machine. It seems like Zydis does not disassemble the code correctly but I don't have any further information. The
PolyHook2
logging seems to be fairly lacking, e.g. it does not mention the address at which disassembling was attempted or other useful details.Pre-compiled release build of the above DLL: PolyHook2D3D11PresentHookingBug.zip
In either case,
Microsoft Detours
is working flawlessly (also confirmed on the French guy's machine).If you have any idea what could be causing this issue with
PolyHook2
and how to fix it, it would be much appreciated.