In the windows malware development world or rather windows internal world we have a table named IAT which holds the functions that are used in the applicaiton. to bypass AV/EDR people often try to hide these function names by means of obfuscation.
This repository tries to make obfuscating WINAPI/NTAPI calls easier. note that it is for educational purposes and I'm not responsible for any harm that is caused by using this repository!
usage:
winapi-obfuscator.py [-h] --windows-sdk WINDOWS_SDK --function-names FUNCTION_NAMES [--key-length KEY_LENGTH] [--encrypt-only]
options:
-h, --help show this help message and exit
--windows-sdk WINDOWS_SDK, -s WINDOWS_SDK
Windows SDK path which is usually located at 'C:\Program Files (x86)\Windows Kits\<windows version>\Include\<version>'.
--function-names FUNCTION_NAMES, -f FUNCTION_NAMES
function names separated by ','.
--key-length KEY_LENGTH, -l KEY_LENGTH
XOR key length. default is '10'.
--encrypt-only, -o only return encrypted function/library names and their keys.
Note: due to the nature of the regexp in use, some signatures may not be grepped! if you have found any problems please do inform me through issues.
grepper functionality finds function signatures in the windows SDK folder you specify which is usually located in C:\Program Files (x86)\Windows Kits\<windows version>\Include\<version>
.
after grepping through all the defined windows header files it generates a data.json
file which contains all the signatures.
data.json
{
"MessageBoxA": {"signature": "int WINAPI MessageBoxA( _In_opt_ HWND hWnd, _In_opt_ LPCSTR lpText, _In_opt_ LPCSTR lpCaption, _In_ UINT uType);", "library": "user32.dll"},
"VirtualAlloc": {"signature": "LPVOID WINAPI VirtualAlloc( _In_opt_ LPVOID lpAddress, _In_ SIZE_T dwSize, _In_ DWORD flAllocationType, _In_ DWORD flProtect ) ;", "library": "kernel32.dll"},
"VirtualProtect": {"signature": "BOOL WINAPI VirtualProtect( _In_ LPVOID lpAddress, _In_ SIZE_T dwSize, _In_ DWORD flNewProtect, _Out_ PDWORD lpflOldProtect ) ;", "library": "kernel32.dll"},
"VirtualFree": {
"signature": "BOOL WINAPI VirtualFree( _Pre_notnull_ _When_(dwFreeType == MEM_DECOMMIT,_Post_invalid_) _When_(dwFreeType == MEM_RELEASE,_Post_ptr_invalid_) LPVOID lpAddress, _In_ SIZE_T dwSize, _In_ DWORD dwFreeType );",
"library": "kernel32.dll"
},
"WriteProcessMemory": {
"signature": "BOOL WINAPI WriteProcessMemory( _In_ HANDLE hProcess, _In_ LPVOID lpBaseAddress, _In_reads_bytes_(nSize) LPCVOID lpBuffer, _In_ SIZE_T nSize, _Out_opt_ SIZE_T* lpNumberOfBytesWritten );",
"library": "kernel32.dll"
},
...
}
list of windows header files i've found till now(not at all complete):
__header_files = [
[r"\um\winuser.h","user32.dll"],
[r"\um\memoryapi.h","kernel32.dll"],
[r"\um\psapi.h","kernel32.dll"],
[r"\um\tlhelp32.h","kernel32.dll"],
[r"\um\debugapi.h","kernel32.dll"],
[r"\um\processthreadsapi.h","kernel32.dll"],
[r"\um\fileapi.h","kernel32.dll"],
[r"\um\libloaderapi.h","kernel32.dll"],
[r"\um\WtsApi32.h","wtsapi32.dll"],
[r"\um\shellapi.h","shell32.dll"],
[r"\um\Shlwapi.h","Shlwapi.dll"],
[r"\um\wincrypt.h","Crypt32.dll"],
[r"\um\winbase.h","kernel32.dll"]
]
the script greps through these header files for function signatures.
and using this functionality you can easily obfuscate the functions that you want and it gives you the new function definitions, encrypted function names, encrypted DLL names, different XOR keys and finally the code to resolve them. you can copy and paste these into c/c++ and use them.
all.txt
unsigned char sMessageBoxA[] = {0x20, 0x6, 0x3f, 0x27, 0x56, 0x50, 0x52, 0x10, 0x17, 0x0, 0x2c, 0x63};
unsigned char sUser32[] = {0x2d, 0x31, 0x7, 0x37, 0x50, 0x59, 0x74, 0x5c, 0x59, 0x34, 0x58};
char kMessageBoxA[] = {0x6d, 0x63, 0x4c, 0x54, 0x37, 0x37, 0x37, 0x52, 0x78, 0x78, 0x0};
char kUser32[] = {0x58, 0x42, 0x62, 0x45, 0x63, 0x6b, 0x5a, 0x38, 0x35, 0x58, 0x0};
XOR(sMessageBoxA, sizeof(sMessageBoxA), kMessageBoxA, sizeof(kMessageBoxA));
XOR(sUser32, sizeof(sUser32), kUser32, sizeof(kUser32));
pMessageBoxA messageBoxA = (pMessageBoxA)GetProcAddress(LoadLibraryA((LPCSTR)sUser32),(LPCSTR)sMessageBoxA);
python winapi-obfuscator.py -s "C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0" -f MessageBoxA
data.json
{
"MessageBoxA": {"signature": "int WINAPI MessageBoxA( _In_opt_ HWND hWnd, _In_opt_ LPCSTR lpText, _In_opt_ LPCSTR lpCaption, _In_ UINT uType);", "library": "user32.dll"},
"VirtualAlloc": {"signature": "LPVOID WINAPI VirtualAlloc( _In_opt_ LPVOID lpAddress, _In_ SIZE_T dwSize, _In_ DWORD flAllocationType, _In_ DWORD flProtect ) ;", "library": "kernel32.dll"},
"VirtualProtect": {"signature": "BOOL WINAPI VirtualProtect( _In_ LPVOID lpAddress, _In_ SIZE_T dwSize, _In_ DWORD flNewProtect, _Out_ PDWORD lpflOldProtect ) ;", "library": "kernel32.dll"},
"VirtualFree": {
"signature": "BOOL WINAPI VirtualFree( _Pre_notnull_ _When_(dwFreeType == MEM_DECOMMIT,_Post_invalid_) _When_(dwFreeType == MEM_RELEASE,_Post_ptr_invalid_) LPVOID lpAddress, _In_ SIZE_T dwSize, _In_ DWORD dwFreeType );",
"library": "kernel32.dll"
},
"WriteProcessMemory": {
"signature": "BOOL WINAPI WriteProcessMemory( _In_ HANDLE hProcess, _In_ LPVOID lpBaseAddress, _In_reads_bytes_(nSize) LPCVOID lpBuffer, _In_ SIZE_T nSize, _Out_opt_ SIZE_T* lpNumberOfBytesWritten );",
"library": "kernel32.dll"
},
...
}
all.txt
typedef int (WINAPI * pMessageBoxA)( _In_opt_ HWND hWnd, _In_opt_ LPCSTR lpText, _In_opt_ LPCSTR lpCaption, _In_ UINT uType);
unsigned char sMessageBoxA[] = {0x21, 0x3, 0xa, 0x10, 0x1b, 0x9, 0x3, 0x2f, 0x16, 0x14, 0x2d, 0x66};
unsigned char sUser32[] = {0x10, 0x19, 0x7, 0x3, 0x5a, 0x5e, 0x45, 0x1d, 0x15, 0x1b, 0x65};
char kMessageBoxA[] = {0x6c, 0x66, 0x79, 0x63, 0x7a, 0x6e, 0x66, 0x6d, 0x79, 0x6c, 0x0};
char kUser32[] = {0x65, 0x6a, 0x62, 0x71, 0x69, 0x6c, 0x6b, 0x79, 0x79, 0x77, 0x0};
XOR(sMessageBoxA, sizeof(sMessageBoxA), kMessageBoxA, sizeof(kMessageBoxA));
XOR(sUser32, sizeof(sUser32), kUser32, sizeof(kUser32));
pMessageBoxA messageBoxA = (pMessageBoxA)GetProcAddress(LoadLibraryA((LPCSTR)sUser32),(LPCSTR)sMessageBoxA);
your/cpp/file.cpp - copy all.txt
content into your cpp
file.
void XOR(unsigned char data[], int dataSize, char key[], int keySize) {
for (int i = 0; i < (dataSize / sizeof(unsigned char)); i++) {
char currentKey = key[i % (keySize - 1)];
data[i] ^= currentKey;
}
}
typedef int (WINAPI * pMessageBoxA)( _In_opt_ HWND hWnd, _In_opt_ LPCSTR lpText, _In_opt_ LPCSTR lpCaption, _In_ UINT uType);
int main(){
unsigned char sMessageBoxA[] = {0x21, 0x3, 0xa, 0x10, 0x1b, 0x9, 0x3, 0x2f, 0x16, 0x14, 0x2d, 0x66};
unsigned char sUser32[] = {0x10, 0x19, 0x7, 0x3, 0x5a, 0x5e, 0x45, 0x1d, 0x15, 0x1b, 0x65};
char kMessageBoxA[] = {0x6c, 0x66, 0x79, 0x63, 0x7a, 0x6e, 0x66, 0x6d, 0x79, 0x6c, 0x0};
char kUser32[] = {0x65, 0x6a, 0x62, 0x71, 0x69, 0x6c, 0x6b, 0x79, 0x79, 0x77, 0x0};
XOR(sMessageBoxA, sizeof(sMessageBoxA), kMessageBoxA, sizeof(kMessageBoxA));
XOR(sUser32, sizeof(sUser32), kUser32, sizeof(kUser32));
pMessageBoxA messageBoxA = (pMessageBoxA)GetProcAddress(LoadLibraryA((LPCSTR)sUser32),(LPCSTR)sMessageBoxA);
messageBoxA(NULL, "hello", "hello", MB_OK);
}