trace function calls
An example of creating logs from NtOpenFile
Last updated
An example of creating logs from NtOpenFile
Last updated
Creating logs from different APIs and functions is one of the essential tasks in reverse engineering and program or malware analysis. HyperDbg is optimized to be fast and accurate for this case.
Assume that we want to create a log from all the files that a process wants to open. For this case, we want to hook .
From the , NtOpenFile is defined like this:
As you might know, there is no pointer to the file name in the above prototype. In fact, the file name is embedded into the ObjectAttributes parameter to this function.
If you want to see how OBJECT_ATTRIBUTES structure is defined, you can see link from MSDN.
From the relative-address point of view, this function is stored in the memory like this:
If we look at the UNICODE_STRING structure. It's defined like this:
And the compiler saves it like this:
Ok, we have all the offsets that we want to create a log from the file names.
First, the ObjectAttributes parameter is passed as the 3rd parameter to the function, and as the calling convention is Windows fastcall (rcx, rdx, r8, r9, stack), our target parameter is located at the r8 register.
In our case, r8 is a pointer to the OBJECT_ATTRIBUTES, and if we add 0x10 to it, we'll reach the ObjectName field of this structure.
ObjectName is a pointer to the UNICODE_STRING, so we'll dereference this pointer using the poi
operator to reach the top of the UNICODE_STRING.
In the UNICODE_STRING, we'll add 0x8 to get the Buffer filed of this structure, and now we dereference it again to get the pointer where the file name string is located.
You can clearly see that the computed address contains the object name.
You can see the results of how it displays every object's name when you continue the debuggee.
We can see that there is a field named ObjectName. This is the name of the object that we're trying to open using NtOpenFile. This structure is also used in .
We'll put a breakpoint on this function and use and commands to verify our computation.
Now, we'll show it using function with %ws
as the identifier to show the buffer as a unicode string.
Next, we clear all the breakpoints using the command.
At last, we set a hook to this function using command and in the script payload of the command, we use our above statement.