-
Notifications
You must be signed in to change notification settings - Fork 354
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
!monitor doesn't work when process is started using CREATE_SUSPENDED #252
Comments
Hi,
This is the exact reason why we designed the '.pagein command'. Unfortunately, this command only supports Debugger Mode for now. Once you start a process, Windows doesn't initially map the addresses (or make it available through the page-tables). The reason why x64dbg successfully shows you the result is that it directly accesses the address in the user-mode (PASSIVE_LEVEL) which in turn, causes a page-fault that is thrown and handled by Windows. But, in HyperDbg we cannot access a paged-out or not yet valid page entry as the paging doesn't work in VMX-root mode. You can use a trick that I previously showed in HyperDbg's telegram group:
This is quite expected as you're running HyperDbg on a relatively old processor (4th Gen), but in order to fix it, I need more details like the result of WinDbg's '!analyze -v'. But, is there any special reason why you are not using it in the Debugger Mode? |
I am not using it in debugger mode cause I think that implies to run the debugged program inside a VM, right? Please download also the .dmp file from here , in case u need it: It would be very nice to have a reliable .start in VMI mode, and even nicer to have some kind of capability to follow up Thx for the quick response. |
I think the docs state that .pagein command is just for debugger mode. I solved it in another way , I opened game in x64dbg, bp at entry point, loaded the dll I was interesting in tracing via x64dbg functionality, after that I coded a program which did OpenProcess(game.exe) and ReadProcessMemory() of the memory interval of desired dll. That got rid off the c0000005 err, but I hit another: HyperDbg> !monitor w 180307000 182BB3FFF pid 12BC script { if( $ip < 0x7FFFFFFFFFF) { printf("Writing from RIP=%llx at addr=%llx\n",$ip ,$context); } } When !monitor command was executed, game was still bp-ed in x64dbg at entry point. Can u advise? |
Thank you for providing the result of !analyze -v, it seems to be a solvable issue. But just to confirm with you. Can you reproduce this issue? I mean do you see this BSOD, each time you try to unload HyperDbg? Or it's just one time? Is there any activated event while you unload HyperDbg? I have to reproduce the error on my system, so I can further investigate it.
Sure, I will add it to the to-do list. There are some logical flaws in VMI Mode (like finding a way of halting the process), once these logical caveats are solved, I'll implement the '.start' for the VMI Mode too.
If you want to use it on both addresses, then you can put only one '!monitor' on a bigger address range and filter your results from script engine. |
I can't reproduce the issue reliably. In order to trigger this , try something like: " Is there any activated event while you unload HyperDbg?" ->no , when I tried to !monitor dll range, hyperdbg-cli took ages to finish, and after it did and spew the err,I unloaded vmm and BSOD. I put very big range adresses in !monitor command, even spanning all 350 MB range of dll mem space, I still get that c0000026 err. "Have you applied any other '!monitor' to the target address?" ->Come on , I ain't that dumb! :D "You can confirm it by using the '!pte' command, whether the PML1 entry is located on the same page or not." -> let me check this and I will get back to you. |
350 MB? 😳 That's too big. The '!monitor' isn't supposed to handle that amount of memory :) By the way, whatever address you want to put a '!monitor' on it should be valid and available in the memory. It is not surprising at all if Windows only loads a portion of your 350 MB DLL in the memory as 350 MB is too big. Furthermore, it even won't load this amount of data to the RAM. Only the portion of DLL that is used will be available in the memory. It probably occupied a lot of pages in the memory so Windows will decide to move it frequently to the disk (page-out) in order to be able to handle other processes. |
I made sure it's available by reading it often from another process using ReadProcessMemory(). Is there any hardcoded maximum limit of mem span for !monitor? I remember I found a more or less hackish way to prevent pages being swapped in Windows in another project on github(don't remember now which one, must look for it). Would be possible tom implement such a measure in HyperDbg? |
I think these are heisenbugs, cannot reproduce them anymore. But you are right indeed , !monitor fails for large mem span , it is awfully slow. However , I can report another bug I encountered: if you monitor a large mem address and process ends during/before "events c all" ., this happens: Microsoft (R) Windows Debugger Version 10.0.22621.382 AMD64 Loading Dump File [C:\Windows\MEMORY.DMP] Symbol search path is: srv* Loading unloaded module list
CLOCK_WATCHDOG_TIMEOUT (101) Debugging Details:KEY_VALUES_STRING: 1
FILE_IN_CAB: MEMORY.DMP BUGCHECK_CODE: 101 BUGCHECK_P1: 18 BUGCHECK_P2: 0 BUGCHECK_P3: ffffc2015d736180 BUGCHECK_P4: 2 FAULTING_PROCESSOR: 2 PROCESS_NAME: steamwebhelper.exe FAULTING_THREAD: ffffd401475e5080 BLACKBOXBSD: 1 (!blackboxbsd) BLACKBOXNTFS: 1 (!blackboxntfs) BLACKBOXPNP: 1 (!blackboxpnp) BLACKBOXWINLOGON: 1 BAD_STACK_POINTER: ffffd4013d050e00 STACK_TEXT: FAULTING_SOURCE_LINE: C:\games\HyperDbg\hyperdbg\hprdbghv\code\vmm\ept\Ept.c FAULTING_SOURCE_FILE: C:\games\HyperDbg\hyperdbg\hprdbghv\code\vmm\ept\Ept.c FAULTING_SOURCE_LINE_NUMBER: 693 FAULTING_SOURCE_CODE:
SYMBOL_NAME: hprdbghv!EptHandlePageHookExit+66 MODULE_NAME: hprdbghv IMAGE_NAME: hprdbghv.dll STACK_COMMAND: .process /r /p 0xffffd401472b6080; .thread 0xffffd401475e5080 ; kb BUCKET_ID_FUNC_OFFSET: 66 FAILURE_BUCKET_ID: CLOCK_WATCHDOG_TIMEOUT_INTERRUPTS_DISABLED_STACKPTR_ERROR_hprdbghv!EptHandlePageHookExit OS_VERSION: 10.0.19041.1 BUILDLAB_STR: vb_release OSPLATFORM_TYPE: x64 OSNAME: Windows 10 FAILURE_ID_HASH: {33a0d65a-1fe3-e344-e050-df931ac4b9e0} Followup: MachineOwnerSina, are you kind enough to suggest me any other possible FAST alternative to log self-modifying code of process in real time from ring-0 for a huge memory adress range? What approach should I take? Is it possible to remove W page rights of all mem area and then intercept exceptions in ring-0 and turn on/off W rights transparently from ring-3? I dont want ring-3 to handle the exceptions. Thanks |
Sure. Generally, the best way to have a detector for memory READ/WRITE detection is hypervisors, but as you can see, monitoring a large amount of memory (like 350 MB) is problematic, the other option might be using CPU emulators like QEMU, Bochs, which I'm not sure if it works for your case or not.
It's theoretically possible, but when it comes to the implementation, no it's not possible. Because by doing something like this, you also prevent the memory manager of the process itself from modifying the page-table bit. Other than that, there are plenty of processor events like exceptions that directly write content on the stack and by removing READ/WRITE bits, you also prevent the processors' capability of modifying memory and there are thousands of reasons and considerations that might BSOD your computer.
You can do it by HyperDbg's exception command. Use the event short-circuiting mechanism of HyperDbg to ignore re-injecting exceptions/faults/interrupts to the guest. Other than that, you can also inject interrupts/faults/execptions in any situations by using a not yet documented function in HyperDbg, called 'event_inject()' or 'event_inject_error_code()'. |
Sina , I don't have anything relevant to add to this Issue, you can close it if you want. Best regards |
Hi, So that you know, the previous bug that you mentioned at #91 is now fixed at multiple-eptp branch. |
Really? You implemented multi-EPTP? Wow , man, you're my personal hero! ;-) |
Yes, but please give me some time to make further tests to make sure that it's stable, once I merge it to the 'dev' branch, it would be good to use. Right now, if you really need to use this feature, you can compile and use the 'multiple-eptp' branch. But I recommend not to use it before the merge. |
Hi, I would appreciate it if you could re-test your scenario by using the '!monitor' command on HyperDbg v0.8.1 and let me know if the problem is fixed or not. |
I will retest, but it will take a while, please don't close this bugreport yet. Thanks for your effort! |
Hello Sina
I am using Hyperdbg in VMI mode. HyperDbg Debugger [version: v0.5.0, build: 20230824.2026]
Since .start command is not yet functional for this mode , I implemented some kind of ugly solution
to help me !monitor the process quite from beginning.
I coded a program which basically does this:
if (CreateProcessA(NULL, (LPSTR)(argv[1]), NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, filepath.parent_path().string().c_str(), &si, &pi))
{
cout << "Type HyperDbg command: .attach " << std::hex << pi.dwProcessId << endl;
cout << "and after that press [Enter] " << pi.dwProcessId << endl;
I create process in suspended mode, retrieve its PID , then I go to Hyperdbg and type:
!monitor r 0x7ffe0000 0x7ffe0fff pid 0x8d0 script { if( $ip < 0x7FFFFFFFFFF) { printf("RIP=%llx,PID=%d,KUSD_offset=%llx\n",$ip,$pid,$context); } }
and after that I resume the suspended process.
Hyperdbg prints the following err: "err, invalid address (c0000005)"
The event is not created.
Why HyperDbg cannot create events for suspended processes, when I look in x64dbg , KUSER_SHARED_DATA is mapped already.
Also in the moment I unload the vmm , Windows goes BSOD.
Culprit: hprdbgkd.sys , reason : DRIVER_IRQL_NOT_LESS_OR_EQUAL
Thanks
The text was updated successfully, but these errors were encountered: