mirror of
https://github.com/bats3c/DarkLoadLibrary
synced 2026-06-06 15:14:33 +00:00
Merge pull request #10 from physics-sp/find-import-addresses
find all import addresses dinamically
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user