WinAPI Hooking Using FRIDA
In this tutorial, we will create a custom C++ executable with call to Sleep API from kernel32.dll and NtDelayExecution API from ntdll.dll…
WinAPI Hooking Using FRIDA
In this tutorial, we will create a custom C++ executable with call to Sleep API from kernel32.dll and NtDelayExecution API from ntdll.dll and hook both this API call separetely. By the end of the tutorial we will achieve the following objectives -
- Build an executable with Sleep API and NtDelayExecution API. This API are also the common target that is hooked by well-known malware sandbox environment to eliminate dormant and delayed malware execution.
- Use FRIDA to overwrite execution patterns of this two APIs.
Since we want to keep this tutorial beginner friendly, we will discuss all the tools that we will be using to achieve this but at the same time not make this tutorial extra lengthy.
Prerequisites
A running Windows 11 VM. It can also be Windows 10 but since world is moving towards Windows 11, it is recommended to learn in the latest. Some important configuration to keep in mind for this VM are -
- Disabled Tamper Protection, Real-time Protection and all Windows Defender features (even from GPO).
- Installed Visual Studio Community 2022 with package for Desktop Application using C++ selected.
- Installed Python Interpreter with pip and python added to environment.
- Good Internet Connection.
- Prior knowledge of basic and elementary C++/C is recommended.
Building the Executable
In Visual Studio, we create a new Console Application Project. We can give any name to the project that we seem fit. Once the project opens and the editor shows the base template code for cpp file, we start coding.
- Code for using Sleep API provided by kernel32.dll
#include <iostream> // for basic io apis
#include <windows.h> // for the sleep api and other windows basic apis
int main(){ // main entry point
Sleep(30000); // sleep for 30s
}
- Code for using NtDelayExecution API provided by ntdll.dll. This API is used in lower-level programming so is not part of standard library support of Visual Studio.
#include <iostream>
#include <windows.h>
typedef LONG NTSTATUS; // P1
extern "C" NTSTATUS NTAPI NtDelayExecution(
BOOLEAN Alertable,
PLARGE_INTEGER DelayInterval
); // P2
int main(){
LARGE_INTEGER int_val;
int_val.QuadPart = -30000000; // P3
NTSTATUS ntstatus = NtDelayExecution(FALSE,&integer_val);
}
- P1: ntdll APIs uses NTSTATUS as return data type which is just alternative representation of an Int32 number. So, we type-define NTSTATUS as LONG datatype.
- P2: Since ntdll APIs are not natively support, we need to define the API by using extern macro. “C” means this API definition is based on C code. NTSTATUS is the return data type, NTAPI is the calling convention which is representation of __stdcall. NtDelayExecution is the name of the API. This API has two arguments —
- Alertable: this makes the function go to Alertable Wait state during Sleep for Asynchronous Procedure Call (APC) functions to be executed from the queue. For this case, we will not use this functionality and hence will pass False as value.
- DelayInterval: Time delay in nanoseconds
C++ has 2 calling conventions -
- __stdcall: calling convention where callee manages the stack memory, the function does not allow dynamic number of arguments and are used in all Win32 API. NTAPI is typedef of __stdcall.
- __cdecl: calling convention where caller manages the stack memory, the function does allow dynamic number of arguments and is default convention for C and C++ functions.
- P3: LARGE_INTEGER is a structure that has lower part and higher part but also quad part for 64-bit numbers. The delay value can be provided in both relative or fixed number. A negative number is relative value while a positive value is a fixed value. In this case, relative wait for 30s is done.
We can merge the both way of Sleep together into single piece of code and add some debugging print statements.
#include <iostream>
#include <windows.h>
typedef LONG NTSTATUS; // ntdll API uses 32 bit status code called NTSTATUS which is same as LONG datatype
extern "C" NTSTATUS NTAPI NtDelayExecution(
// undocumented API needs to be defined with the calling convention -
// NTAPI is a calling convention for NTDLL APIs equivalent to __stdcall (WINAPI uses this calling convention)
// another type of calling convention is __cdecl which is the default for C and C++
BOOLEAN Alertable, // If we want this call to move into Alertable Wait state for APC Function Call
PLARGE_INTEGER DelayInterval // wait time
);
int main()
{
std::cout << "Program starts\n";
std::cout << "kernel32.dll Sleep API delay starts\n";
Sleep(30'000LL); // 30s delay using kernel32 Sleep API
std::cout << "kernel32.dll Sleep API delay ends\n";
LARGE_INTEGER integer_val;
integer_val.QuadPart = -30 * 10'00'000LL; // 30s delay
std::cout << "ntdll.dll Sleep API delay starts\n";
NTSTATUS ntstatus = NtDelayExecution(FALSE, &integer_val); // call to ntdll delay execution API
std::cout << "ntdll.dll Sleep API delay ends\n";
std::cout << "End of program\n";
return 0;
}
Note: for easier understanding, the number can be written with comma-separation by using ‘ in place of comma and end with LL.
This is just the code but in order to build and compile it, we need to take additional steps to create the library file for ntdll and add it to the project configuration.
Create lib file of ntdll and change project configuration
In Visual Studio UI, we go to Tools>Command Line>Developer Powershell. This is a special Visual Studio configured terminal for using some special tools provided along with the Visual Studio.
In the Explorer section of the Visual Studio UI, we create a new project item called ntdll.def.
We add the following code to that file -
LIBRARY ntdll.dll
EXPORTS
NtDelayExecution
Whatever functions/APIs we want to export from ntdll.dll can be added here. For this tutorial, we need only the NtDelayExecution API.
In the Developer Powershell Terminal, we write -
lib /deb:ntdll.deb /out:ntdll.lib /machine:x64
We should make sure that the above code is executed from the directory where the .deb file is also present.
This will create a .lib file based on the .deb configuration.
We move the .lib file to any empty folder or shared folder. We also copy the path of the empty or shared folder.
We right-click on the project in the Explorer and select Properties. After the Window opens, we make sure that the Configuration is set for all environments. (We select the environment from the top dropdown in the configuration window)
In Linker>General>Add Library Directories, we add the copied directory path. Also in Linker>Input>Additional Dependencies, we add ntdll.lib.
We can now build the project. We go to Build Tab at the top and select Build Project. This generates an executable whose location is shown in the terminal.
We will use this executable as the target for hooking.
Using FRIDA for hooking
First we install FRIDA using python.
pip install frida-tools
Once it is installed, we create the hooking instructions (the instructions to be executed during hooking). The code is self-explanatory and easy to understand —
Interceptor.attach(
Module.getExportByName("kernel32.dll", "Sleep"),
{
onEnter: function(args) {
console.log("Sleep enter for Kernel32 Sleep API hook");
},
onLeave: function(retval) {
console.log("Sleep exit for Kernel32 Sleep API hook");
}
}
);
Interceptor.attach(
Module.getExportByName("ntdll.dll", "NtDelayExecution"),
{
onEnter: function(args) {
console.log("Sleep enter for ntdll NtDelayExecution API hook");
},
onLeave: function(retval) {
console.log("Sleep exit for ntdll NtDelayExecution API hook");
}
}
);
The Interceptor.attach is used to attach/hook instructions. It takes two arguments — module address for which it is looking for to hook, the instructions to execute after hooking. Hooking instructions can be executed when execution flow of the executable enters or leaves the function.
Note: kernel32 Sleep API also uses ntdll in the background for the wait, so this code will intercept both the coded as well as kernel32 call for ntdll NtDelayExecution.
The code above is used to add instructions to hooked function. We can also overwrite the instructions already present in the functions to completely change the API behaviour during execution.
We save the code as hooking.js
We then execute the following code in terminal -
frida CodedExecutable.exe -l hooking.js

We have successfully performed API hooking!
메타데이터
- post_id
- 9eca3cd1bc65
- slug
- winapi-hooking-using-frida-9eca3cd1bc65
- url
- https://medium.com/@prajeetguha/winapi-hooking-using-frida-9eca3cd1bc65
- canonical_url
- https://medium.com/@prajeetguha/winapi-hooking-using-frida-9eca3cd1bc65
- author_url
- https://medium.com/@prajeetguha
- status
- ok
- fetched_at
- 2026-06-24 11:06:28