Instant events
The instant event mechanism in HyperDbg
Starting from v0.7 HyperDbg supports the "instant event" mechanism. This mechanism is mainly introduced to fix a fundamental problem of immediately applying events in the Debugger Mode.
Instant events addressed this issue by providing two types of events, regular events, and big events.
Through the implementation of the instant event mechanism, our aim was to make the design complexities transparent to the user by preallocating buffers and considering some pre-defined limitations. Nevertheless, if you encounter errors or limitations, this documentation is here to assist you in resolving them. If clarification is needed, feel free to ask questions or engage in discussions.
What was the problem?
If you've previously used HyperDbg, you've probably noticed that events (e.g., EPT hooks, syscall hooks, memory monitors, etc.) continue the debugger for a short time and then break the debugger again. Thus, the target process might find a chance to continue its execution and you'll lose the current context (registers, memory). This was a fundamental problem in HyperDbg and the instant event mechanism solves this issue.
By employing instant events, now HyperDbg guarantees to keep debuggee in a halt state (in Debugger Mode); thus, nothing will change during its execution and the context is preserved.
The implementation of this mechanism involves broadcasting events to the halted cores (in the VMX root-mode), and as you might know, allocating memory is not possible in the VMX-root mode as paging is not working. Because of that, HyperDbg is not able to allocate memory to store the details of each event in the debugger, and as a result, we use a couple of pre-allocated pools to use them to store the event details on the VMX root-mode.
Two types of events refer to the size of the buffer needed for each event.
Regular Events
Regular events are those events that need a small number of bytes for the pre-allocated buffer and once you start HyperDbg, it allocates a tens of events. HyperDbg will store buffers (for scripts and event custom code) with small sizes in these events.
Big Events
Big events are those events that need a bigger number of bytes (size). For example, the script buffer or the custom code buffer is bigger than normal events. In these cases, HyperDbg needs to allocate bigger buffers for the debuggee to use in the VMX-root mode. By default, HyperDbg won't allocate any buffers for big events, because these events are not regularly used, thus, to save memory HyperDbg won't allocate them.
Enable or Disable Events
If you don't want to encounter these limitations, you can disable the instant event mechanism by using the following constant and compiling HyperDbg. If you disable this mechanism, then the context (registers and memory) will be lost (changed) when you're applying events.
Clearing Events
As a result of the instant events, clearing and terminating events are also applied immediately. However, once you clear an event or all events, HyperDbg just disables the event(s). Immediately after you continue the debuggee, HyperDbg tries to process the clear operation and removes the effect of the event in the system.
Events are also able to call the 'event_clear' function directly from the scripts to remove other events or even the current event.
Pools & Preallocations
As explained earlier, it's not possible to allocate buffers in the VMX-root mode. HyperDbg tries to allocate buffers whenever possible but if you're applying a large number of events all of them without continuing the debuggee, the 'prealloc' command is designed to make HyperDbg able to support these scenarios.
Note that, the 'prealloc' command will continue the debuggee for some time (in Debugger Mode). This means that you lose the current context (registers & memory) after executing this command. So, you need to use this command before applying events.
Event Regular Buffers
By default, HyperDbg allocates a couple of buffers for storing events. If you continue the debugger after applying events, then HyperDbg re-allocates more buffers to replace previously used buffers but if you want to apply many events instantly, you need to tell HyperDbg beforehand to allocate more buffers for your events.
The following command is used to tell HyperDbg to allocate buffers to store regular events.
In the above example, HyperDbg preallocates 10
buffers for 10 regular events.
Event Big Buffers
If you have a very long script or custom code buffer, then you can use the big events instead.
In the above example, HyperDbg preallocates 12
buffers for 12 big events. Usually, you need to use the regular events and if HyperDbg shows an error and indicates that the size of the buffer is too big and it's not able to store the action buffer, then you can use a big event.
Safe Event Buffers
By default, instant events won't support preallocated safe buffers that are accessible as $buffer
pseudo-registers but you can preallocate two types of buffers (big event-peallocation) and (regular event-preallocation) buffers.
Regular Safe Event Buffers
If you need a small buffer (explained later in the Changing Design Constants section), then you can use the following command. You can also specify the number of events that you need a regular safe buffer for them.
After that, you'll be able to use the events with the $buffer
parameter.
Big Safe Event Buffers
If you need a bigger buffer (explained later in the Changing Design Constants section), then you can use the following command. You can also specify the number of events that you need a big safe buffer for them.
After that, you'll be able to use the events with the $buffer
parameter. (Note the size of the buffer is bigger than the regular events)
Instant Events For EPT Hooks
EPT hooks need extra pre-allocated buffers. If you want to use EPT hook events (!epthook, !epthook2, and !monitor), then you need to preallocate buffers for them.
By default, if you use EPT hooks and continue the debuggee after applying events, HyperDbg tries to re-allocate more buffers for the next EPT hooks but if you want to apply all of them without continuing the debuggee, then you need to use the 'prealloc' command.
Please note that EPT hooks are events, so first you need to preallocate event buffers (explained above) and EPT hook buffers.
Memory Monitor Hooks
If you want to use memory monitor hooks, you can preallocate buffers for them. For example, assume that we want to apply fifteen '!monitor' events, first, we allocate 15
events buffer.
Then, we preallocate buffers for this specific EPT monitor event.
EPT Hooks (Hidden Breakpoints)
If you want to use classic hidden hooks, you can preallocate buffers for them. For example, assume that we want to apply fifteen '!epthook' events, first, we allocate 15
events buffer.
Then, we preallocate buffers for this specific EPT hook event.
EPT Hooks (Detours Hooks)
If you want to use detours EPT hooks, you can preallocate buffers for them. For example, assume that we want to apply fifteen '!epthook2' events, first, we allocate 15
events buffer.
Then, we preallocate buffers for this specific event EPT hook event.
Changing Design Constants
Here are a couple of design constants and their descriptions. If you want to customize HyperDbg (and compile it), you can change the following constants.
The following constant shows the maximum number of packets that can be delivered to the user-mode. For example, if you want to clear tens of events and HyperDbg shows an error message indicating that the user-mode priority buffers are full, you can increase the following constant to fix the problem.
The following constant shows the maximum number of EPT hooks that HyperDbg allocates pre-allocated buffers for them. If you want to apply more EPT hooks without continuing the debuggee, you can increase the following constant.
The following constant shows the maximum number of regular events that you can apply immediately without continuing the debuggee. If you want to apply tens of events without using the 'prealloc' command, you can increase the value of this constant.
The following constant shows the maximum number of big events that you can apply immediately without continuing the debuggee. If you want to apply tens of events without using the 'prealloc' command, you can increase the value of this constant.
The following constant shows the maximum number of bytes to store the details of a regular event. If you're using a very big condition buffer, you can increase this constant.
The following constant shows the maximum number of bytes to store the details of a big event. If you're using a very big condition buffer, you can increase this constant.
The following constant shows the maximum number of bytes that an action (script and custom codes) can be for the regular event. If you want to apply bigger scripts or custom codes, you can increase this constant.
The following constant shows the maximum number of bytes that an action (script and custom codes) can be for the big event. If you want to apply bigger scripts or custom codes, you can increase this constant.
The following constant shows the maximum number of bytes allocated for the safe pre-allocated buffer of the regular events. This is mainly used if you pass the buffer
parameter to events. By default, HyperDbg won't allocate safe buffers and you need to use the 'prealloc' command to allocate them. You can increase the size of these buffers by changing this constant.
The following constant shows the maximum number of bytes allocated for the safe pre-allocated buffer of the regular events. This is mainly used if you pass the buffer
parameter to events. By default, HyperDbg won't allocate safe buffers and you need to use the 'prealloc' command to allocate them. You can increase the size of these buffers by changing this constant.
Instant Event Errors
HyperDbg cannot allocate an infinite amount of preallocated buffers and because of this limitation, there are multiple errors related to instant events. Here these errors are described as well as the situations where these errors happen in HyperDbg and how you can fix them.
Please note that the 'prealloc' command will continue the debuggee for some time (in Debugger Mode). This means that you lose the current context (registers & memory) after executing this command. So, you need to keep in mind that in case of errors, first run the 'prealloc' command and once you have enough buffers for your events, then apply all of your events instantly.
0xc0000040
This error states that in some situations like applying '!epthook' or '!monitor', specifying the target process id is not possible, because HyperDbg cannot find the structures of the target process and perform the context switching. You need to use the '.process' or the '.thread' command to switch to the target process memory layout, then apply your hooks.
0xc0000041
This error states that the conditional buffer that you specified for the target event cannot be stored in the memory as there is not enough pre-allocated space for the target buffer. In order to fix that, you need to customize and rebuild HyperDbg. Please refer to the "Changing Design Constants" on this page.
0xc0000042
This error happens regularly and it means that HyperDbg didn't allocate enough preallocated buffer to store your event. Usually, this error happens when you apply many events (for example many EPT hooks on different functions) without continuing the debuggee for some time.
In order to fix that, you have two options. You can either continue HyperDbg by running 'g' and after some time press CTRL+C and pause the debugger again, so HyperDbg finds a chance to reallocate new preallocated pools for your events.
If you don't want to continue HyperDbg, before applying events, you can use the 'prealloc' command to allocate as many preallocated pools as you need and after that, you can pause HyperDbg and apply your events.
For example, assume that you want to apply '!epthook' for 0x50 number of functions. If you apply all of them without continuing the debuggee, you'll encounter this error but if you run the following commands beforehand, events can be applied without any problem.
0xc0000043
This error states that the conditional buffer is big and cannot be stored in the pre-allocated pools. Usually, it happens if you are passing a long buffer of conditions to the event. In order to solve that, you can run the following command and HyperDbg will allocate a bigger buffer for your event and conditions.
The above command tells HyperDbg to reserve big pools for 5 events.
0xc0000044
This error indicates that the system doesn't have enough resources (RAM) to allocate the target action in the VMI Mode.
0xc0000045
This error is the same as (0xc0000042) and it states HyperDbg didn't allocate enough preallocated buffer to store your action. Usually, this error happens when you apply many events (for example many EPT hooks on different functions) without continuing the debuggee for some time.
In order to fix that, you have two options. You can either continue HyperDbg by running 'g' and after some time press CTRL+C and pause the debugger again, so HyperDbg finds a chance to reallocate new preallocated pools for your actions.
If you don't want to continue HyperDbg, before applying events, you can use the 'prealloc' command to allocate as many preallocated pools as you need and after that, you can pause HyperDbg and apply your actions.
For example, assume that you want to apply '!epthook' for 0x50 number of functions. If you apply all of them without continuing the debuggee, you'll encounter this error but if you run the following commands beforehand, events can be applied without any problem.
0xc0000046
This error is the same as (0xc0000043). It states that the script or the custom code buffer is big and cannot be stored in the pre-allocated pools. Usually, it happens if you are passing a long script or a long buffer of custom code assemblies to the event. In order to solve that, you can run the following command and HyperDbg will allocate a bigger buffer for your event and conditions.
The above command tells HyperDbg to reserve big pools for 5 events.
0xc0000047
This error states that your script or the custom code buffer is so big that HyperDbg cannot store it. In order to fix that, you need to customize and rebuild HyperDbg. Please refer to the "Changing Design Constants" on this page.
0xc0000048
This error states that you specified a pre-allocated buffer that is bigger than the stack of HyperDbg to send/receive it. You need to specify a small safe buffer or you need to customize and rebuild HyperDbg to allocate bigger stacks for the communication. This error happens on both the Debugger Mode and the VMI Mode.
0xc0000049
By default, HyperDbg won't allocate safe requested buffers ($buffer) for instant events. If you need a safe buffer, you need to tell HyperDbg before applying the event.
The following command allocates safe buffers for three events.
After running the above command, you can use the safe buffer ($buffer) on your events.
0xc000004a
This error means that your requested safe buffer is big and cannot fit into the preallocated buffers. In order to solve that, you can tell HyperDbg to allocate bigger safe buffers for you before applying the event by using the following command.
The following command allocates a big safe buffer for one event.
0xc000004b
This error states that you specified a very big safe buffer and HyperDbg cannot store it in the memory. In order to fix that, you need to customize and rebuild HyperDbg. Please refer to the "Changing Design Constants" on this page.
0xc000004c
This error indicates that the system doesn't have enough resources (RAM) to allocate the safe buffers ($buffer) in the VMI Mode.
0xc000004f
This error typically occurs when attempting to clear a substantial number of events while the debugger is paused in Debugger Mode, and the user hasn't resumed the debuggee for an extended period. When this error happens, the targeted event(s) become disabled but are not completely removed. This is due to HyperDbg's inability to clear them during the subsequent run, as the user-mode priority buffers are already filled to capacity. Since these unserviced events remained in the queue, HyperDbg cannot eliminate them. To resolve this issue, you can continue the debuggee and wait until all queued events are cleared (usually 2 to 10 seconds). Afterward, pause the debuggee once more and request the removal of new events.
If you want to extend this capacity, you can refer to the "Changing Design Constants" on this page.
Last updated