Comments (6)
Hi this should be supported, but it seems there may be a bug. The issue is that the call is very early in the prologue:
00007FFA69484260 | 48:83EC 28 | sub rsp,28 | kernel32::BindIoCompletionCallback
00007FFA69484264 | 48:FF15 BDEB0500 | call qword ptr ds:[<&RtlSetIoCompletionCallback>] |
This call is rewritten by polyhook to point to a jmp target that is capable of redirecting the call from the far away trampoline back to the original location the call would go to. This re-write process can be complex, i'm not sure what may be wrong here.
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] <--- point call here
Could you debug and determine which instruction faults?
from polyhook_2_0.
Here is my detailed debug info:
Before Hooking
00007FF86AC04260 | 48:83EC 28 | sub rsp,28 |
00007FF86AC04264 | 48:FF15 BDEB0500 | call qword ptr ds:[<&RtlSetIoCompletionCallback>] |
00007FF86AC0426B | 0F1F4400 00 | nop dword ptr ds:[rax+rax],eax |
00007FF86AC04270 | 85C0 | test eax,eax |
00007FF86AC04272 | 0F88 24230100 | js kernel32.7FF86AC1659C |
00007FF86AC04278 | B8 01000000 | mov eax,1 |
00007FF86AC0427D | 48:83C4 28 | add rsp,28 |
00007FF86AC04281 | C3 | ret |
00007FF86AC04282 | CC | int3
After Hooking
00007FF86AC04260 | FF25 85FFFFFF | jmp qword ptr ds:[<&int __cdecl MyBindIoCompletionCallback_Impl(void * __ptr64,void (__cdecl*)(unsigned long,unsigned long,struct _OVERLAPPED * __ptr64),unsigned long)>] |
00007FF86AC04266 | 66:90 | nop |
00007FF86AC04268 | 66:90 | nop |
00007FF86AC0426A | 90 | nop |
00007FF86AC0426B | 0F1F4400 00 | nop dword ptr ds:[rax+rax],eax |
00007FF86AC04270 | 85C0 | test eax,eax |
00007FF86AC04272 | 0F88 24230100 | js kernel32.7FF86AC1659C |
00007FF86AC04278 | B8 01000000 | mov eax,1 |
00007FF86AC0427D | 48:83C4 28 | add rsp,28 |
00007FF86AC04281 | C3 | ret |
0000028816C5B430 | 48:83EC 28 | sub rsp,28 |
0000028816C5B434 | 48:FF15 06000000 | call qword ptr ds:[28816C5B441] |
0000028816C5B43B | FF25 46000000 | jmp qword ptr ds:[28816C5B487] |
0000028816C5B441 | FF25 38000000 | jmp qword ptr ds:[28816C5B47F] |
//////////
0000028816C5B47F | 282E | sub byte ptr ds:[rsi],ch | rsi:"ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ�
0000028816C5B481 | C6 | ??? |
0000028816C5B482 | 6A F8 | push FFFFFFFFFFFFFFF8 |
0000028816C5B484 | 7F 00 | jg 28816C5B486 |
0000028816C5B486 | 006B 42 | add byte ptr ds:[rbx+42],ch |
0000028816C5B489 | C06A F8 7F | shr byte ptr ds:[rdx-8],7F | rdx-8:std::basic_string<char,std::char_traits<char>,std::allocator<char> >::insert+68
0000028816C5B48D | 0000 | add byte ptr ds:[rax],al |
0000028816C5B48F | FD | std |
0000028816C5B490 | FD | std |
0000028816C5B491 | FD | std |
IAT of kernel32.dll:
00007FF86AC62E28 30 2B D2 6B F8 7F 00 00 60 58 C9 6B F8 7F 00 00 0+Òkø...`XÉkø...
00007FF86AC62E38 70 BE C1 6B F8 7F 00 00 D0 D8 C8 6B F8 7F 00 00 p¾Ákø...ÐØÈkø...
00007FF86AC62E48 70 D1 CA 6B F8 7F 00 00 80 1E C9 6B F8 7F 00 00 pÑÊkø.....Ékø...
00007FF86AC62E58 10 D7 CA 6B F8 7F 00 00 20 06 C7 6B F8 7F 00 00 .×Êkø... .Çkø...
00007FF86AC62E68 40 E3 CA 6B F8 7F 00 00 90 74 CE 6B F8 7F 00 00 @ãÊkø....tÎkø...
00007FF86AC62E78 60 76 CE 6B F8 7F 00 00 E0 71 CE 6B F8 7F 00 00 `vÎkø...àqÎkø...
``` |
ntdll::RtlSetIoCompletionCallback:
00007FF86BD22B30 | 48:8BC4 | mov rax,rsp |
00007FF86BD22B33 | 48:8958 08 | mov qword ptr ds:[rax+8],rbx |
00007FF86BD22B37 | 48:8970 10 | mov qword ptr ds:[rax+10],rsi
00007FF86BD22B3B | 57 | push rdi
00007FF86BD22B3C | 48:83EC 30 | sub rsp,30 |
00007FF86BD22B40 | 48:8BF2 | mov rsi,rdx
00007FF86BD22B43 | 48:8BF9 | mov rdi,rcx
00007FF86BD22B46 | 48:8360 20 00 | and qword ptr ds:[rax+20],0
My question is, the call d_p [xxxx]:
0000028816C5B434 | 48:FF15 06000000 | call qword ptr ds:[28816C5B441]
will set %eip := [28816C5B441] which is { FF, 25, 38,00,00,00,CD,CD } or as address 0xCDCD0000003825FF,
it is an invalid code address and will crash immediately.
Also the code:
0000028816C5B441 | FF25 38000000 | jmp qword ptr ds:[28816C5B47F]
Even it can be executed properly, cannot lead us to the correct target, it needs two levels of dereferences:
target = * ( * ( 28816C5B47F ) )
[28816C5B47F] ==> 00007FF86AC62E28
[00007FF86AC62E28] ==> 00007FF86BD22B30 (our target ntdll::RtlSetIoCompletionCallback)
from polyhook_2_0.
I'll hopefully find some time to look into this before too long. Thank you for the detailed report I will try to replicate. As far as the jump, the FF25 jump is a bit special as it's indirect. The address it points to is a data address that it dereferences, then it jumps there. It is odd there's two levels of indirection there though, I'd expect a single de-reference. Share the c++ code you are using for this particular hook?
from polyhook_2_0.
I've fixed this issue in my forked repository.
Now after the hooking, the trampoline code looks like:
Before hooking
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 |
After hooking
Trampoline code:
0000022A1C7BEDC0 48 83 EC 28 sub rsp,28h
0000022A1C7BEDC4 48 FF 15 45 00 00 00 call qword ptr [22A1C7BEE10h]
0000022A1C7BEDCB FF 25 47 00 00 00 jmp qword ptr [22A1C7BEE18h]
0000022A1C7BEDD1 C0 0F 88 ror byte ptr [rdi],88h
0000022A1C7BEDD4 24 23 and al,23h
//////// dest holders ////////
0000022A1C7BEE10 30 2B EA 40 FC 7F 00 00 ; => &RtlSetIoCompletionCallback
0000022A1C7BEE18 6B 42 22 3F FC 7F 00 00 ; => & test eax, eax
The CALL instruction only needs a dest-holder to specify its destination.
It is odd there's two levels of indirection there though, I'd expect a single de-reference
Yes, there is a bug here that does not set the indirect flag properly:
should be:
(hasGroup(capInst, x86_insn_group::X86_GRP_CALL) && inst.size() >= 3 && inst.getBytes().at(1) == 0xff && inst.getBytes().at(2) == 0x15)
the CALL is FF15, not FF25, as a result the PLH::Instruction::getDestionation() does not dereference the correct calling target.
from polyhook_2_0.
Glad you've fixed your issues! You will want to revert your change of 0x25 -> 0x15, the 0x25 case handles an indirect jump. What you want is to introduce a second check for the additional 0x15 indirect call case which you are absolutely correct I do not handle correctly (or like, at all). Thank you for looking into this!
from polyhook_2_0.
This is resolved
from polyhook_2_0.
Related Issues (20)
- Expose m_hooked boolean HOT 1
- Non DS segment relative memory operands crash reading destination HOT 1
- Disassembler may go out of bounds into unmapped region HOT 1
- Detours getting automatically removed HOT 9
- Crash on VFuncSwapHook/VTableSwapHook Constructor HOT 1
- A windows app that uses std::stringstream crashes when PolyHook_2.lib is included in the link. HOT 8
- MessageBoxW & EatHook
- Cannot compile polyhook on linux using cmake HOT 4
- VEH Hook function HOT 1
- Stack overflow in PLH::ErrorLog::log HOT 3
- fail on link when use vcpkg with x64-windows-static HOT 17
- Does x86Detour seem not to work for external DLL calls? HOT 6
- A question about how to hook into external libraries. HOT 1
- When I tried to hook some functions, it caused the program to crash HOT 4
- Link issue with x86-windows-static HOT 1
- Calling the original function fails after hooking the same function twice or more HOT 2
- Crashes when hooking e.g. QueryPerformanceCounter in x64 but works with x86 HOT 1
- Design issues with bool hook() and bool unHook() HOT 1
- Hooking function fails with "Warn: Couldn't decompile instructions at followed jmp" and "Error: Prologue jmp resolution failed" HOT 9
- Improper hooks when RSP instructions are in the prologue HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from polyhook_2_0.