@@ -1,10 +1,15 @@
#include <Windows.h>
#include <winternl.h>
#include <stdio.h>
/* Define the overloaded hashing function you want to use */
#pragma comment(linker, "/ENTRY:entry")
// Define hashing algorithm to use
#define HASHALGO HashStringDjb2
// Define how large you'd like cache to be
#define CACHE 50
#pragma region hashes
// https://github.com/vxunderground/VX-API/blob/main/VX-API/MalwareStrings.h
#pragma region HashStringDjb2
constexpr DWORD HashStringDjb2 (const char * String )
@@ -61,43 +66,57 @@ constexpr ULONG HashStringFowlerNollVoVariant1a(const wchar_t* String)
}
#pragma endregion
#pragma endregion
void * GetProcAddrH (UINT moduleHash , UINT funcHash );
void InitModules ();
#pragma region macros
#define TOKENIZE ( x ) #x
#define TOKENIZEW ( x ) L#x
#define CONCAT ( x , y ) x##y
#define hash ( VAL ) constexpr auto CONCAT( hash, VAL ) = HASHALGO( TOKENIZE( VAL ) );
#define dllhash (DLL , VAL ) constexpr auto CONCAT( hash, DLL ) = HASHALGO( VAL );
#define hashFunc ( FUNCNAME , RETTYPE , ...) \
#define hashFunc ( FUNCNAME , RETTYPE , ...) \
hash( FUNCNAME ) typedef RETTYPE( WINAPI* CONCAT( type, FUNCNAME ) )( __VA_ARGS__ );
#define API ( DLL , FUNCNAME ) ( ( CONCAT( type, FUNCNAME ))GetProcAddrH( CONCAT( hash, DLL ) , \
#define API ( DLL , FUNCNAME ) ( ( CONCAT( type, FUNCNAME ))GetProcAddrH( CONCAT( hash, DLL ) ,\
CONCAT( hash,FUNCNAME ) ) )
#pragma region dlls
dllhash (KERNEL32 , L"KERNEL32.DLL" )
dllhash (NTDLL , L"ntdll.dll" )
dllhash (KERNELBASE , L"KERNELBASE.dll" )
dllhash (UCRTBASE , L"ucrtbase.dll" )
/* funcName , rettype , parameters */
hashFunc (NtWriteVirtualMemory , NTSTATUS , HANDLE , PVOID , PVOID , ULONG , PULONG )
hashFunc (VirtualProtect , BOOL , LPVOID , SIZE_T , DWORD , PDWORD )
#pragma endregion
hashFunc (CloseHandle , BOOL , HANDLE );
#pragma region functions
// Example functions funcName , rettype , parameters
//hashFunc(NtWriteVirtualMemory, NTSTATUS, HANDLE, PVOID, PVOID, ULONG, PULONG)
hashFunc (VirtualProtect , BOOL , LPVOID , SIZE_T , DWORD , PDWORD )
hashFunc (VirtualAlloc , LPVOID , LPVOID , SIZE_T , DWORD , DWORD );
hashFunc (CreateProcessA , BOOL , LPCSTR , LPSTR , LPSECURITY_ATTRIBUTES , LPSECURITY_ATTRIBUTES , BOOL , DWORD , LPVOID , LPCSTR , LPSTARTUPINFOA , LPPROCESS_INFORMATION );
hashFunc (LoadLibraryA , HMODULE , LPCSTR );
hashFunc (LoadLibraryW , HMODULE , LPCWSTR );
hashFunc (CloseHandle , BOOL , HANDLE );
#pragma endregion
#pragma endregion
struct ModuleHash
#pragma function(memset)
void * memset (void * dest , int c , size_t count );
__forceinline char Upper (char c );
void * GetProcAddrH (UINT moduleHash , UINT funcHash );
void InitModules ();
struct HashStruct
{
UINT moduleHash ;
PVOID module ;
UINT Hash ;
PVOID addr ;
};
ModuleHash ModuleHashes [] =
HashStruct ModuleHashes [] =
{
{ hashNTDLL , nullptr },
{ hashKERNEL32 , nullptr },
@@ -106,34 +125,44 @@ ModuleHash ModuleHashes[] =
{ hashUCRTBASE , nullptr },
};
int main ()
#ifdef CACHE
HashStruct HashCache [CACHE ];
DWORD hashPointer ;
#endif
int entry ()
{
InitModules ();
do
{
STARTUPINFOA si = { sizeof (si ) };
PROCESS_INFORMATION pi ;
if (API (KERNEL32 , CreateProcessA )(nullptr , (LPSTR )R "(c:\windows\system32\calc.exe)" , nullptr , nullptr , 0 , 0 , nullptr , nullptr , & si , & pi ) == 0 ) {
break ;
}
API (KERNEL32 , CloseHandle )(pi .hProcess );
API (KERNEL32 , CloseHandle )(pi .hThread );
} while (FALSE);
STARTUPINFOA si = { sizeof (si ) };
PROCESS_INFORMATION pi ;
API (KERNEL32 , CreateProcessA )(nullptr , (LPSTR )R "(c:\windows\system32\calc.exe)" , nullptr , nullptr , 0 , 0 , nullptr , nullptr , & si , & pi );
API (KERNEL32 , CloseHandle )(pi .hProcess );
API (KERNEL32 , CloseHandle )(pi .hThread );
return 0 ;
}
void * GetProcAddrH (UINT moduleHash , UINT funcHash )
{
void * base = nullptr ;
for (auto i : ModuleHashes ) {
if (i .moduleHash == moduleHash ) {
base = i .module ;
if (i .Hash == moduleHash ) {
base = i .addr ;
}
}
if (base == nullptr ) {
return nullptr ;
}
#ifdef CACHE
for (auto i = 0 ; i < CACHE ; i ++ )
{
if (funcHash == HashCache [i ].Hash ) {
return HashCache [i ].addr ;
}
}
#endif
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER )base ;
PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS )((PBYTE )base + dos -> e_lfanew );
@@ -149,6 +178,12 @@ void* GetProcAddrH(UINT moduleHash, UINT funcHash)
auto name = (LPSTR )((PBYTE )base + names [i ]);
if (HASHALGO (name ) == funcHash ) {
auto function = ((PBYTE )base + functions [ordinals [i ]]);
#ifdef CACHE
// Cache result
HashCache [hashPointer % CACHE ].addr = function ;
HashCache [hashPointer % CACHE ].Hash = funcHash ;
hashPointer = (hashPointer + 1 ) % CACHE ;
#endif
return function ;
}
}
@@ -172,12 +207,48 @@ void InitModules()
UNICODE_STRING * fullname = & entry -> FullDllName ;
UNICODE_STRING * basename = (UNICODE_STRING * )((PBYTE )fullname + sizeof (UNICODE_STRING ));
UINT hash = HASHALGO (basename -> Buffer );
for (auto & i : ModuleHashes ) {
if (i .moduleHash == hash ) {
i .module = entry -> DllBase ;
char name [64 ];
if (basename -> Length < sizeof (name ) - 1 )
{
int i = 0 ;
while (basename -> Buffer [i ] && i < sizeof (name ) - 1 )
{
name [i ] = Upper ((char )basename -> Buffer [i ]); // can never be sure so uppercase
i ++ ;
}
name [i ] = 0 ;
UINT hash = HASHALGO (name );
for (auto & i : ModuleHashes ) {
if (i .Hash == hash ) {
i .addr = entry -> DllBase ;
}
}
}
next = next -> Flink ;
}
#ifdef CACHE
RtlSecureZeroMemory (HashCache , sizeof (HashCache ));
hashPointer = 0 ;
#endif
}
char Upper (char c )
{
if (c >= 'a' && c <= 'z' ) {
return c - 'a' + 'A' ;
}
return c ;
}
void * memset (void * dest , int c , size_t count )
{
char * bytes = (char * )dest ;
while (count -- )
{
* bytes ++ = (char )c ;
}
return dest ;
}