From 24f2317d6d00a736f6eb313379aff1cbce4eb750 Mon Sep 17 00:00:00 2001 From: physics-sp Date: Thu, 12 Aug 2021 14:16:53 -0300 Subject: [PATCH] find all import addresses dinamically --- DarkLoadLibrary/include/darkloadlibrary.h | 12 +++ DarkLoadLibrary/include/ldrutils.h | 2 + DarkLoadLibrary/include/pebutils.h | 10 +- DarkLoadLibrary/src/darkloadlibrary.c | 73 ++++++++----- DarkLoadLibrary/src/ldrutils.c | 18 ++-- DarkLoadLibrary/src/main.c | 11 +- DarkLoadLibrary/src/pebutils.c | 123 +++++++++++++++------- 7 files changed, 168 insertions(+), 81 deletions(-) diff --git a/DarkLoadLibrary/include/darkloadlibrary.h b/DarkLoadLibrary/include/darkloadlibrary.h index 771d3ee..219f660 100644 --- a/DarkLoadLibrary/include/darkloadlibrary.h +++ b/DarkLoadLibrary/include/darkloadlibrary.h @@ -6,6 +6,18 @@ #define LOAD_MEMORY 0x00000003 #define NO_LINK 0x00010000 +typedef LPVOID(WINAPI* HEAPALLOC)(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes); +typedef HANDLE(WINAPI* GETPROCESSHEAP)(VOID); +typedef HANDLE(WINAPI* CREATEFILEW)(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); +typedef LPVOID(WINAPI* VIRTUALALLOC)(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect); +typedef DWORD(WINAPI* GETFILESIZE)(HANDLE hFile, LPDWORD lpFileSizeHigh); +typedef BOOL(WINAPI* READFILE)(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped); +typedef BOOL(WINAPI* CLOSEHANDLE)(HANDLE hObject); +typedef BOOL(WINAPI* HEAPFREE)(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem); +typedef void(__cdecl* _WSPLITPATH)(const wchar_t* _FullPath, wchar_t* _Drive, wchar_t* _Dir, wchar_t* _Filename, wchar_t* _Ext); +typedef wchar_t*(_cdecl* WCSCPY)(wchar_t* Dest, const wchar_t* _Source); +typedef wchar_t* (__cdecl* WCSCAT)(wchar_t* _dst, const wchar_t* __src); + #pragma once typedef struct _DARKMODULE { BOOL bSuccess; diff --git a/DarkLoadLibrary/include/ldrutils.h b/DarkLoadLibrary/include/ldrutils.h index 510f94d..cc7080c 100644 --- a/DarkLoadLibrary/include/ldrutils.h +++ b/DarkLoadLibrary/include/ldrutils.h @@ -7,6 +7,8 @@ typedef BOOL(WINAPI * DLLMAIN)(HINSTANCE, DWORD, LPVOID); typedef HMODULE(WINAPI* LOADLIBRARYA)(LPCSTR); +typedef BOOL(WINAPI* VIRTUALPROTECT)(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect); +typedef BOOL(WINAPI* FLUSHINSTRUCTIONCACHE)(HANDLE hProcess, LPCVOID lpBaseAddress, SIZE_T dwSize); BOOL IsValidPE(PBYTE pbData); BOOL MapSections(PDARKMODULE pdModule); diff --git a/DarkLoadLibrary/include/pebutils.h b/DarkLoadLibrary/include/pebutils.h index f0f1488..5bf1f41 100644 --- a/DarkLoadLibrary/include/pebutils.h +++ b/DarkLoadLibrary/include/pebutils.h @@ -10,6 +10,14 @@ typedef NTSTATUS(WINAPI* LDRGETPROCADDRESS)(HMODULE, PANSI_STRING, WORD, PVOID*); typedef VOID(WINAPI* RTLRBINSERTNODEEX)(_In_ PRTL_RB_TREE Tree, _In_opt_ PRTL_BALANCED_NODE Parent, _In_ BOOLEAN Right, _Out_ PRTL_BALANCED_NODE Node); +typedef VOID(NTAPI* RTLINITUNICODESTRING)(PUNICODE_STRING DestinationString, PCWSTR SourceString); +typedef NTSTATUS(NTAPI* NTQUERYSYSTEMTIME)(PLARGE_INTEGER SystemTime); +typedef NTSTATUS(NTAPI* RTLHASHUNICODESTRING)(UNICODE_STRING* String, BOOLEAN CaseInSensitive, ULONG HashAlgorithm, ULONG* HashValue); +typedef SIZE_T(NTAPI* RTLCOMPAREMEMORY)(const VOID* Source1, const VOID* Source2, SIZE_T Length); +typedef int(__cdecl* _WCSNICMP)(const wchar_t* _Str1, const wchar_t* _Str2, size_t _MaxCount); +typedef int(__cdecl* STRCMP)(const char* _Str1, const char* _Str2); +typedef size_t(__cdecl* MBSTOWCS)(wchar_t* Dest, const char* _Source, size_t _MaxCount); +typedef int(__cdecl* _WCSICMP)(const wchar_t* _Str1, const wchar_t* _Str2); #ifdef _WIN64 #define PEB_OFFSET 0x60 @@ -36,6 +44,6 @@ NTSYSAPI VOID NTAPI RtlRbInsertNodeEx(_In_ PRTL_RB_TREE Tree, _In_opt_ PRTL_BALA HMODULE IsModulePresent(LPCWSTR lpwName); HMODULE IsModulePresentA(char* Name); BOOL LinkModuleToPEB(PDARKMODULE pdModule); -FARPROC GetFunctionAddress(HMODULE hModule, char* ProcName); +PVOID GetFunctionAddress(HMODULE hModule, char* ProcName); BOOL LocalLdrGetProcedureAddress(HMODULE hLibrary, PANSI_STRING ProcName, WORD Ordinal, PVOID* FunctionAddress); BOOL _LocalLdrGetProcedureAddress(HMODULE hLibrary, PANSI_STRING ProcName, WORD Ordinal, PVOID* FunctionAddress); \ No newline at end of file diff --git a/DarkLoadLibrary/src/darkloadlibrary.c b/DarkLoadLibrary/src/darkloadlibrary.c index 0cd3568..4b18c5a 100644 --- a/DarkLoadLibrary/src/darkloadlibrary.c +++ b/DarkLoadLibrary/src/darkloadlibrary.c @@ -6,6 +6,12 @@ BOOL ParseFileName( LPWSTR lpwFileName ) { + HEAPALLOC pHeapAlloc = (HEAPALLOC)GetFunctionAddress(IsModulePresent(L"Kernel32.dll"), "HeapAlloc"); + GETPROCESSHEAP pGetProcessHeap = (GETPROCESSHEAP)GetFunctionAddress(IsModulePresent(L"Kernel32.dll"), "GetProcessHeap"); + _WSPLITPATH p_wsplitpath = (_WSPLITPATH)GetFunctionAddress(IsModulePresent(L"ucrtbased.dll"), "_wsplitpath"); + WCSCPY pwcscpy = (WCSCPY)GetFunctionAddress(IsModulePresent(L"ucrtbased.dll"), "wcscpy"); + WCSCAT pwcscat = (WCSCAT)GetFunctionAddress(IsModulePresent(L"ucrtbased.dll"), "wcscat"); + if (lpwFileName == NULL) { pdModule->ErrorMsg = L"Invalid filename"; @@ -14,26 +20,26 @@ BOOL ParseFileName( pdModule->LocalDLLName = lpwFileName; - HANDLE hHeap = GetProcessHeap(); + HANDLE hHeap = pGetProcessHeap(); if (!hHeap) { pdModule->ErrorMsg = L"Failed to find valid heap"; return FALSE; } - pdModule->CrackedDLLName = (PWCHAR)HeapAlloc( + pdModule->CrackedDLLName = (PWCHAR)pHeapAlloc( hHeap, HEAP_ZERO_MEMORY, MAX_PATH * 2 ); - PWCHAR lpwExt = (PWCHAR)HeapAlloc( + PWCHAR lpwExt = (PWCHAR)pHeapAlloc( hHeap, HEAP_ZERO_MEMORY, MAX_PATH ); - PWCHAR lpwFilename = (PWCHAR)HeapAlloc( + PWCHAR lpwFilename = (PWCHAR)pHeapAlloc( hHeap, HEAP_ZERO_MEMORY, MAX_PATH @@ -45,7 +51,7 @@ BOOL ParseFileName( return FALSE; } - _wsplitpath( + p_wsplitpath( lpwFileName, NULL, NULL, @@ -59,12 +65,12 @@ BOOL ParseFileName( return FALSE; } - PCHAR lpCpy = (PCHAR)wcscpy( + PCHAR lpCpy = (PCHAR)pwcscpy( pdModule->CrackedDLLName, lpwFilename ); - PCHAR lpCat = (PCHAR)wcscat( + PCHAR lpCat = (PCHAR)pwcscat( pdModule->CrackedDLLName, lpwExt ); @@ -82,7 +88,14 @@ BOOL ReadFileToBuffer( PDARKMODULE pdModule ) { - HANDLE hFile = CreateFileW( + HEAPALLOC pHeapAlloc = (HEAPALLOC)GetFunctionAddress(IsModulePresent(L"Kernel32.dll"), "HeapAlloc"); + CREATEFILEW pCreateFileW = (CREATEFILEW)GetFunctionAddress(IsModulePresent(L"Kernel32.dll"), "CreateFileW"); + VIRTUALALLOC pVirtualAlloc = (VIRTUALALLOC)GetFunctionAddress(IsModulePresent(L"Kernel32.dll"), "VirtualAlloc"); + GETFILESIZE pGetFileSize = (GETFILESIZE)GetFunctionAddress(IsModulePresent(L"Kernel32.dll"), "GetFileSize"); + READFILE pReadFile = (READFILE)GetFunctionAddress(IsModulePresent(L"Kernel32.dll"), "ReadFile"); + CLOSEHANDLE pCloseHandle = (CLOSEHANDLE)GetFunctionAddress(IsModulePresent(L"Kernel32.dll"), "CloseHandle"); + + HANDLE hFile = pCreateFileW( pdModule->LocalDLLName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, @@ -98,7 +111,7 @@ BOOL ReadFileToBuffer( return FALSE; } - DWORD dwSize = GetFileSize( + DWORD dwSize = pGetFileSize( hFile, NULL ); @@ -109,7 +122,7 @@ BOOL ReadFileToBuffer( return FALSE; } - pdModule->pbDllData = VirtualAlloc( + pdModule->pbDllData = pVirtualAlloc( NULL, dwSize, MEM_COMMIT | MEM_RESERVE, @@ -122,7 +135,7 @@ BOOL ReadFileToBuffer( return FALSE; } - if (!ReadFile( + if (!pReadFile( hFile, pdModule->pbDllData, dwSize, @@ -133,7 +146,7 @@ BOOL ReadFileToBuffer( return FALSE; } - if (!CloseHandle(hFile)) + if (!pCloseHandle(hFile)) { pdModule->ErrorMsg = L"Failed to close handle on DLL file"; return FALSE; @@ -150,7 +163,11 @@ PDARKMODULE DarkLoadLibrary( LPCWSTR lpwName ) { - PDARKMODULE dModule = (DARKMODULE*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DARKMODULE)); + HEAPALLOC pHeapAlloc = (HEAPALLOC)GetFunctionAddress(IsModulePresent(L"Kernel32.dll"), "HeapAlloc"); + GETPROCESSHEAP pGetProcessHeap = (GETPROCESSHEAP)GetFunctionAddress(IsModulePresent(L"Kernel32.dll"), "GetProcessHeap"); + WCSCAT pwcscat = (WCSCAT)GetFunctionAddress(IsModulePresent(L"ucrtbased.dll"), "wcscat"); + + PDARKMODULE dModule = (DARKMODULE*)pHeapAlloc(pGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DARKMODULE)); if (!dModule) return NULL; @@ -210,36 +227,36 @@ PDARKMODULE DarkLoadLibrary( // make sure the PE we are about to load is valid if (!IsValidPE(dModule->pbDllData)) { - dModule->ErrorMsg = (wchar_t*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 500); + dModule->ErrorMsg = (wchar_t*)pHeapAlloc(pGetProcessHeap(), HEAP_ZERO_MEMORY, 500); if (!dModule->ErrorMsg) goto Cleanup; - wcscat(dModule->ErrorMsg, L"Data is an invalid PE: "); - wcscat(dModule->ErrorMsg, lpwName); + pwcscat(dModule->ErrorMsg, L"Data is an invalid PE: "); + pwcscat(dModule->ErrorMsg, lpwName); goto Cleanup; } // map the sections into memory if (!MapSections(dModule)) { - dModule->ErrorMsg = (wchar_t*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 500); + dModule->ErrorMsg = (wchar_t*)pHeapAlloc(pGetProcessHeap(), HEAP_ZERO_MEMORY, 500); if (!dModule->ErrorMsg) goto Cleanup; - wcscat(dModule->ErrorMsg, L"Failed to map sections: "); - wcscat(dModule->ErrorMsg, lpwName); + pwcscat(dModule->ErrorMsg, L"Failed to map sections: "); + pwcscat(dModule->ErrorMsg, lpwName); goto Cleanup; } // handle the import tables if (!ResolveImports(dModule)) { - dModule->ErrorMsg = (wchar_t*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 500); + dModule->ErrorMsg = (wchar_t*)pHeapAlloc(pGetProcessHeap(), HEAP_ZERO_MEMORY, 500); if (!dModule->ErrorMsg) goto Cleanup; - wcscat(dModule->ErrorMsg, L"Failed to resolve imports: "); - wcscat(dModule->ErrorMsg, lpwName); + pwcscat(dModule->ErrorMsg, L"Failed to resolve imports: "); + pwcscat(dModule->ErrorMsg, lpwName); goto Cleanup; } @@ -248,12 +265,12 @@ PDARKMODULE DarkLoadLibrary( { if (!LinkModuleToPEB(dModule)) { - dModule->ErrorMsg = (wchar_t*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 500); + dModule->ErrorMsg = (wchar_t*)pHeapAlloc(pGetProcessHeap(), HEAP_ZERO_MEMORY, 500); if (!dModule->ErrorMsg) goto Cleanup; - wcscat(dModule->ErrorMsg, L"Failed to link module to PEB: "); - wcscat(dModule->ErrorMsg, lpwName); + pwcscat(dModule->ErrorMsg, L"Failed to link module to PEB: "); + pwcscat(dModule->ErrorMsg, lpwName); goto Cleanup; } } @@ -261,12 +278,12 @@ PDARKMODULE DarkLoadLibrary( // trigger tls callbacks, set permissions and call the entry point if (!BeginExecution(dModule)) { - dModule->ErrorMsg = (wchar_t*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 500); + dModule->ErrorMsg = (wchar_t*)pHeapAlloc(pGetProcessHeap(), HEAP_ZERO_MEMORY, 500); if (!dModule->ErrorMsg) goto Cleanup; - wcscat(dModule->ErrorMsg, L"Failed to execute: "); - wcscat(dModule->ErrorMsg, lpwName); + pwcscat(dModule->ErrorMsg, L"Failed to execute: "); + pwcscat(dModule->ErrorMsg, lpwName); goto Cleanup; } diff --git a/DarkLoadLibrary/src/ldrutils.c b/DarkLoadLibrary/src/ldrutils.c index a56e854..63264d4 100644 --- a/DarkLoadLibrary/src/ldrutils.c +++ b/DarkLoadLibrary/src/ldrutils.c @@ -32,6 +32,8 @@ BOOL MapSections( PIMAGE_BASE_RELOCATION pRelocation; PIMAGE_SECTION_HEADER pSectionHeader; + VIRTUALALLOC pVirtualAlloc = (VIRTUALALLOC)GetFunctionAddress(IsModulePresent(L"Kernel32.dll"), "VirtualAlloc"); + pNtHeaders = RVA( PIMAGE_NT_HEADERS, pdModule->pbDllData, @@ -68,7 +70,7 @@ BOOL MapSections( return FALSE; } #else - pdModule->ModuleBase = (ULONG_PTR)VirtualAlloc( + pdModule->ModuleBase = (ULONG_PTR)pVirtualAlloc( (LPVOID)(pNtHeaders->OptionalHeader.ImageBase), (SIZE_T)pNtHeaders->OptionalHeader.SizeOfImage, MEM_RESERVE | MEM_COMMIT, @@ -77,7 +79,7 @@ BOOL MapSections( if (!pdModule->ModuleBase) { - pdModule->ModuleBase = (ULONG_PTR)VirtualAlloc( + pdModule->ModuleBase = (ULONG_PTR)pVirtualAlloc( 0, (SIZE_T)pNtHeaders->OptionalHeader.SizeOfImage, MEM_RESERVE | MEM_COMMIT, @@ -167,10 +169,7 @@ BOOL ResolveImports( PIMAGE_THUNK_DATA pFirstThunk, pOrigFirstThunk; BOOL ok; - LOADLIBRARYA pLoadLibraryA = (LOADLIBRARYA)GetFunctionAddress( - IsModulePresentA("Kernel32.dll"), - "LoadLibraryA" - ); + LOADLIBRARYA pLoadLibraryA = (LOADLIBRARYA)GetFunctionAddress(IsModulePresent(L"Kernel32.dll"), "LoadLibraryA"); STRING aString = { 0 }; @@ -359,6 +358,9 @@ BOOL BeginExecution( PIMAGE_SECTION_HEADER pSectionHeader; //PIMAGE_RUNTIME_FUNCTION_ENTRY pFuncEntry; + VIRTUALPROTECT pVirtualProtect = (VIRTUALPROTECT)GetFunctionAddress(IsModulePresent(L"Kernel32.dll"), "VirtualProtect"); + FLUSHINSTRUCTIONCACHE pFlushInstructionCache = (FLUSHINSTRUCTIONCACHE)GetFunctionAddress(IsModulePresent(L"Kernel32.dll"), "FlushInstructionCache"); + DLLMAIN DllMain = NULL; pNtHeaders = RVA( @@ -406,7 +408,7 @@ BOOL BeginExecution( return FALSE; } #else - VirtualProtect( + pVirtualProtect( (LPVOID)(pdModule->ModuleBase + pSectionHeader->VirtualAddress), pSectionHeader->SizeOfRawData, dwProtect, @@ -417,7 +419,7 @@ BOOL BeginExecution( } // flush the instruction cache - FlushInstructionCache((HANDLE)-1, NULL, 0); + pFlushInstructionCache((HANDLE)-1, NULL, 0); // execute the TLS callbacks pDataDir = &pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS]; diff --git a/DarkLoadLibrary/src/main.c b/DarkLoadLibrary/src/main.c index 1ee16b9..014e32c 100644 --- a/DarkLoadLibrary/src/main.c +++ b/DarkLoadLibrary/src/main.c @@ -8,8 +8,11 @@ typedef DWORD (WINAPI * _ThisIsAFunction) (LPCWSTR); VOID main() { + GETPROCESSHEAP pGetProcessHeap = (GETPROCESSHEAP)GetFunctionAddress(IsModulePresent(L"Kernel32.dll"), "GetProcessHeap"); + HEAPFREE pHeapFree = (HEAPFREE)GetFunctionAddress(IsModulePresent(L"Kernel32.dll"), "HeapFree"); + PDARKMODULE DarkModule = DarkLoadLibrary( - LOAD_LOCAL_FILE | NO_LINK, + LOAD_LOCAL_FILE, L"TestDLL.dll", NULL, 0, @@ -19,8 +22,8 @@ VOID main() if (!DarkModule->bSuccess) { printf("load failed: %S\n", DarkModule->ErrorMsg); - HeapFree(GetProcessHeap(), 0, DarkModule->ErrorMsg); - HeapFree(GetProcessHeap(), 0, DarkModule); + pHeapFree(pGetProcessHeap(), 0, DarkModule->ErrorMsg); + pHeapFree(pGetProcessHeap(), 0, DarkModule); return; } @@ -28,7 +31,7 @@ VOID main() (HMODULE)DarkModule->ModuleBase, "CallThisFunction" ); - HeapFree(GetProcessHeap(), 0, DarkModule); + pHeapFree(pGetProcessHeap(), 0, DarkModule); if (!ThisIsAFunction) { diff --git a/DarkLoadLibrary/src/pebutils.c b/DarkLoadLibrary/src/pebutils.c index ebc82ee..55aba36 100644 --- a/DarkLoadLibrary/src/pebutils.c +++ b/DarkLoadLibrary/src/pebutils.c @@ -2,8 +2,9 @@ ULONG LdrHashEntry(UNICODE_STRING UniName, BOOL XorHash) { ULONG ulRes = 0; + RTLHASHUNICODESTRING pRtlHashUnicodeString = (RTLHASHUNICODESTRING)GetFunctionAddress(IsModulePresent(L"ntdll.dll"), "RtlHashUnicodeString"); - RtlHashUnicodeString( + pRtlHashUnicodeString( &UniName, TRUE, 0, @@ -25,6 +26,8 @@ PLDR_DATA_TABLE_ENTRY2 FindLdrTableEntry( PPEB2 pPeb; PLDR_DATA_TABLE_ENTRY2 pCurEntry; PLIST_ENTRY pListHead, pListEntry; + + _WCSNICMP p_wcsnicmp = (_WCSNICMP)GetFunctionAddress(IsModulePresent(L"ucrtbased.dll"), "_wcsnicmp"); pPeb = (PPEB2)READ_MEMLOC(PEB_OFFSET); @@ -38,12 +41,11 @@ PLDR_DATA_TABLE_ENTRY2 FindLdrTableEntry( do { - pCurEntry = CONTAINING_RECORD(pListEntry, LDR_DATA_TABLE_ENTRY2, InLoadOrderLinks); pListEntry = pListEntry->Flink; - INT BaseName1 = _wcsnicmp(BaseName, pCurEntry->BaseDllName.Buffer, (pCurEntry->BaseDllName.Length / sizeof(wchar_t)) - 4); - INT BaseName2 = _wcsnicmp(BaseName, pCurEntry->BaseDllName.Buffer, pCurEntry->BaseDllName.Length / sizeof(wchar_t)); + INT BaseName1 = p_wcsnicmp(BaseName, pCurEntry->BaseDllName.Buffer, (pCurEntry->BaseDllName.Length / sizeof(wchar_t)) - 4); + INT BaseName2 = p_wcsnicmp(BaseName, pCurEntry->BaseDllName.Buffer, pCurEntry->BaseDllName.Length / sizeof(wchar_t)); if (!BaseName1 || !BaseName2) { @@ -62,6 +64,9 @@ PRTL_RB_TREE FindModuleBaseAddressIndex() PRTL_BALANCED_NODE pNode = NULL; PRTL_RB_TREE pModBaseAddrIndex = NULL; + RTLCOMPAREMEMORY pRtlCompareMemory = (RTLCOMPAREMEMORY)GetFunctionAddress(IsModulePresent(L"ntdll.dll"), "RtlCompareMemory"); + STRCMP pstrcmp = (STRCMP)GetFunctionAddress(IsModulePresent(L"ntdll.dll"), "strcmp"); + PLDR_DATA_TABLE_ENTRY2 pLdrEntry = FindLdrTableEntry(L"ntdll.dll"); pNode = &pLdrEntry->BaseAddressIndexNode; @@ -86,7 +91,7 @@ PRTL_RB_TREE FindModuleBaseAddressIndex() for (INT i = 0; i < pNtHeaders->FileHeader.NumberOfSections; i++) { - if (!strcmp(".data", (LPCSTR)pSection->Name)) + if (!pstrcmp(".data", (LPCSTR)pSection->Name)) { stBegin = (SIZE_T)pLdrEntry->DllBase + pSection->VirtualAddress; dwLen = pSection->Misc.VirtualSize; @@ -100,7 +105,7 @@ PRTL_RB_TREE FindModuleBaseAddressIndex() for (DWORD i = 0; i < dwLen - sizeof(SIZE_T); ++stBegin, ++i) { - SIZE_T stRet = RtlCompareMemory( + SIZE_T stRet = pRtlCompareMemory( (PVOID)stBegin, (PVOID)&pNode, sizeof(SIZE_T) @@ -134,7 +139,7 @@ BOOL AddBaseAddressEntry( PVOID lpBaseAddr ) { - + RTLRBINSERTNODEEX pRtlRbInsertNodeEx = (RTLRBINSERTNODEEX)GetFunctionAddress(IsModulePresent(L"ntdll.dll"), "RtlRbInsertNodeEx"); PRTL_RB_TREE pModBaseAddrIndex = FindModuleBaseAddressIndex(); if (!pModBaseAddrIndex) @@ -175,10 +180,6 @@ BOOL AddBaseAddressEntry( } } while (TRUE); - RTLRBINSERTNODEEX pRtlRbInsertNodeEx = (RTLRBINSERTNODEEX)GetFunctionAddress( - IsModulePresent(L"ntdll.dll"), - "RtlRbInsertNodeEx" - ); pRtlRbInsertNodeEx(pModBaseAddrIndex, &pLdrNode->BaseAddressIndexNode, bRight, &pLdrEntry->BaseAddressIndexNode); return TRUE; @@ -306,8 +307,10 @@ HMODULE IsModulePresentA( char* Name ) { + MBSTOWCS pmbstowcs = (MBSTOWCS)GetFunctionAddress(IsModulePresent(L"ucrtbased.dll"), "mbstowcs"); + wchar_t wtext[500]; - mbstowcs(wtext, Name, strlen(Name) + 1); + pmbstowcs(wtext, Name, strlen(Name) + 1); return IsModulePresent(wtext); } @@ -333,10 +336,23 @@ HMODULE IsModulePresent( pLdrTbl = (PLDR_DATA_TABLE_ENTRY2)ucModPtrOff; - if (!_wcsicmp( - pLdrTbl->BaseDllName.Buffer, - (PWSTR)lpwName) - ) + BOOL match = TRUE; + for (int i = 0; i < pLdrTbl->BaseDllName.Length/2; i++) + { + char a, b; + a = pLdrTbl->BaseDllName.Buffer[i]; + b = lpwName[i]; + if (a >= 'A' && a <= 'Z') + a += 32; + if (b >= 'A' && b <= 'Z') + b += 32; + if (a != b) + { + match = FALSE; + break; + } + } + if (match) { // already loaded, so return the base address return (HMODULE)pLdrTbl->DllBase; @@ -348,7 +364,7 @@ HMODULE IsModulePresent( return (HMODULE)NULL; } -FARPROC GetFunctionAddress( +PVOID GetFunctionAddress( HMODULE hModule, char* ProcName ) @@ -454,6 +470,37 @@ BOOL LocalLdrGetProcedureAddress( return *FunctionAddress != NULL; } +BOOL my_strncmp(char* s1, char* s2, size_t n) +{ + BOOL match = TRUE; + for (size_t i = 0; i < n; i++) + { + if (s1[i] != s2[i]) + { + match = FALSE; + break; + } + } + return match; +} + +size_t my_strlen(char* s) +{ + size_t size = -1; + while (s[++size]); + return size; +} + +void my_strncpy(char* dst, char* src, size_t size) +{ + for (size_t i = 0; i < size; i++) + { + dst[i] = src[i]; + if (!src[i]) + break; + } +} + BOOL _LocalLdrGetProcedureAddress( HMODULE hLibrary, PANSI_STRING ProcName, @@ -492,7 +539,7 @@ BOOL _LocalLdrGetProcedureAddress( &pNtHeaders->OptionalHeader, pNtHeaders->FileHeader.SizeOfOptionalHeader + i * IMAGE_SIZEOF_SECTION_HEADER ); - if (strncmp(".text", pSecHeader->Name, 6) == 0) + if (my_strncmp(".text", pSecHeader->Name, 6)) { startValidSection = RVA( PVOID, @@ -538,9 +585,9 @@ BOOL _LocalLdrGetProcedureAddress( hLibrary, *pRVA ); - if (strlen(functionName) != ProcName->Length) + if (my_strlen(functionName) != ProcName->Length) continue; - if (strncmp(functionName, ProcName->Buffer, ProcName->Length) == 0) + if (my_strncmp(functionName, ProcName->Buffer, ProcName->Length)) { // found it found = TRUE; @@ -583,7 +630,7 @@ BOOL _LocalLdrGetProcedureAddress( if (startValidSection > FunctionPtr || FunctionPtr > endValidSection) { // this is not a pointer to a function, but a reference to another library with the real address - size_t full_length = strlen((char*)FunctionPtr); + size_t full_length = my_strlen((char*)FunctionPtr); int lib_length = 0; for (int j = 0; j < full_length; j++) { @@ -597,15 +644,9 @@ BOOL _LocalLdrGetProcedureAddress( { size_t func_length = full_length - lib_length - 1; - char* libname = HeapAlloc( - GetProcessHeap(), - HEAP_ZERO_MEMORY, - lib_length + 5 - ); - if (!libname) - return FALSE; - strncpy(libname, (char*)FunctionPtr, lib_length); - strncpy(libname + lib_length, ".dll", 5); + char libname[256]; + my_strncpy(libname, (char*)FunctionPtr, lib_length); + my_strncpy(libname + lib_length, ".dll", 5); char* funcname = (char*)FunctionPtr + lib_length + 1; STRING funcname_s = { 0 }; FILL_STRING( @@ -615,7 +656,6 @@ BOOL _LocalLdrGetProcedureAddress( PVOID lib_addr = IsModulePresentA(libname); if (lib_addr == NULL || lib_addr == hLibrary) { - HeapFree(GetProcessHeap(), 0, libname); libname = NULL; return FALSE; } @@ -630,10 +670,8 @@ BOOL _LocalLdrGetProcedureAddress( if (!ok) { printf("LocalLdrGetProcedureAddress: failed to resolve address of: %s!%s\n", libname, funcname); - HeapFree(GetProcessHeap(), 0, libname); libname = NULL; return FALSE; } - HeapFree(GetProcessHeap(), 0, libname); libname = NULL; } } *FunctionAddress = FunctionPtr; @@ -652,6 +690,11 @@ BOOL LinkModuleToPEB( UNICODE_STRING FullDllName, BaseDllName; PLDR_DATA_TABLE_ENTRY2 pLdrEntry = NULL; + GETPROCESSHEAP pGetProcessHeap = (GETPROCESSHEAP)GetFunctionAddress(IsModulePresent(L"Kernel32.dll"), "GetProcessHeap"); + HEAPALLOC pHeapAlloc = (HEAPALLOC)GetFunctionAddress(IsModulePresent(L"Kernel32.dll"), "HeapAlloc"); + RTLINITUNICODESTRING pRtlInitUnicodeString = (RTLINITUNICODESTRING)GetFunctionAddress(IsModulePresent(L"ntdll.dll"), "RtlInitUnicodeString"); + NTQUERYSYSTEMTIME pNtQuerySystemTime = (NTQUERYSYSTEMTIME)GetFunctionAddress(IsModulePresent(L"ntdll.dll"), "NtQuerySystemTime"); + pNtHeaders = RVA( PIMAGE_NT_HEADERS, pdModule->pbDllData, @@ -659,19 +702,19 @@ BOOL LinkModuleToPEB( ); // convert the names to unicode - RtlInitUnicodeString( + pRtlInitUnicodeString( &FullDllName, pdModule->LocalDLLName ); - RtlInitUnicodeString( + pRtlInitUnicodeString( &BaseDllName, pdModule->CrackedDLLName ); // link the entry to the PEB - pLdrEntry = (PLDR_DATA_TABLE_ENTRY2)HeapAlloc( - GetProcessHeap(), + pLdrEntry = (PLDR_DATA_TABLE_ENTRY2)pHeapAlloc( + pGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LDR_DATA_TABLE_ENTRY2) ); @@ -682,7 +725,7 @@ BOOL LinkModuleToPEB( } // start setting the values in the entry - NtQuerySystemTime(&pLdrEntry->LoadTime); + pNtQuerySystemTime(&pLdrEntry->LoadTime); // do the obvious ones pLdrEntry->ReferenceCount = 1; @@ -718,8 +761,8 @@ BOOL LinkModuleToPEB( pLdrEntry->Flags = LDRP_IMAGE_DLL | LDRP_ENTRY_INSERTED | LDRP_ENTRY_PROCESSED | LDRP_PROCESS_ATTACH_CALLED; // set the correct values in the Ddag node struct - pLdrEntry->DdagNode = (PLDR_DDAG_NODE)HeapAlloc( - GetProcessHeap(), + pLdrEntry->DdagNode = (PLDR_DDAG_NODE)pHeapAlloc( + pGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LDR_DDAG_NODE) );