mirror of
https://github.com/bats3c/DarkLoadLibrary
synced 2026-06-06 15:14:33 +00:00
Merge pull request #13 from hypervis0r/fix-release
Fix release builds by removing all instances of ucrtbased.dll
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -1,6 +1,8 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
|
#pragma comment(lib, "Shlwapi.lib")
|
||||||
|
|
||||||
#define LOAD_LOCAL_FILE 0x00000001
|
#define LOAD_LOCAL_FILE 0x00000001
|
||||||
#define LOAD_REMOTE_FILE 0x00000002
|
#define LOAD_REMOTE_FILE 0x00000002
|
||||||
#define LOAD_MEMORY 0x00000003
|
#define LOAD_MEMORY 0x00000003
|
||||||
@@ -14,9 +16,8 @@ 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* READFILE)(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped);
|
||||||
typedef BOOL(WINAPI* CLOSEHANDLE)(HANDLE hObject);
|
typedef BOOL(WINAPI* CLOSEHANDLE)(HANDLE hObject);
|
||||||
typedef BOOL(WINAPI* HEAPFREE)(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem);
|
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 LPCWSTR(WINAPI *PATHFINDFILENAMEW)(LPCWSTR pszPath);
|
||||||
typedef wchar_t*(_cdecl* WCSCPY)(wchar_t* Dest, const wchar_t* _Source);
|
typedef int(__cdecl *WSPRINTFW)(LPWSTR, LPCWSTR, ...);
|
||||||
typedef wchar_t* (__cdecl* WCSCAT)(wchar_t* _dst, const wchar_t* __src);
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
typedef struct _DARKMODULE {
|
typedef struct _DARKMODULE {
|
||||||
@@ -37,3 +38,6 @@ PDARKMODULE DarkLoadLibrary(
|
|||||||
DWORD dwLen,
|
DWORD dwLen,
|
||||||
LPCWSTR lpwName
|
LPCWSTR lpwName
|
||||||
);
|
);
|
||||||
|
|
||||||
|
SIZE_T WideStringLength(LPWSTR str);
|
||||||
|
BOOL WideStringCompare(LPWSTR lpwStr1, LPWSTR lpwStr2, SIZE_T cbMaxCount);
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
#include "pebstructs.h"
|
#include "pebstructs.h"
|
||||||
#include "darkloadlibrary.h"
|
#include "darkloadlibrary.h"
|
||||||
@@ -16,7 +17,14 @@ typedef NTSTATUS(NTAPI* RTLHASHUNICODESTRING)(UNICODE_STRING* String, BOOLEAN Ca
|
|||||||
typedef SIZE_T(NTAPI* RTLCOMPAREMEMORY)(const VOID* Source1, const VOID* Source2, SIZE_T Length);
|
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* _WCSNICMP)(const wchar_t* _Str1, const wchar_t* _Str2, size_t _MaxCount);
|
||||||
typedef int(__cdecl* STRCMP)(const char* _Str1, const char* _Str2);
|
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(WINAPI *MULTIBYTETOWIDECHAR)(
|
||||||
|
UINT CodePage,
|
||||||
|
DWORD dwFlags,
|
||||||
|
LPCCH lpMultiByteStr,
|
||||||
|
int cbMultiByte,
|
||||||
|
LPWSTR lpWideCharStr,
|
||||||
|
int cchWideChar
|
||||||
|
);
|
||||||
typedef int(__cdecl* _WCSICMP)(const wchar_t* _Str1, const wchar_t* _Str2);
|
typedef int(__cdecl* _WCSICMP)(const wchar_t* _Str1, const wchar_t* _Str2);
|
||||||
|
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
|
|||||||
@@ -1,6 +1,40 @@
|
|||||||
#include "darkloadlibrary.h"
|
#include "darkloadlibrary.h"
|
||||||
#include "ldrutils.h"
|
#include "ldrutils.h"
|
||||||
|
|
||||||
|
SIZE_T WideStringLength(LPWSTR str)
|
||||||
|
{
|
||||||
|
SIZE_T len = 0;
|
||||||
|
SIZE_T i = 0;
|
||||||
|
|
||||||
|
while (str[i++])
|
||||||
|
++len;
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WideStringCompare(LPWSTR lpwStr1, LPWSTR lpwStr2, SIZE_T cbMaxCount)
|
||||||
|
{
|
||||||
|
BOOL match = TRUE;
|
||||||
|
|
||||||
|
for (SIZE_T i = 0; i < cbMaxCount; i++)
|
||||||
|
{
|
||||||
|
WCHAR a, b;
|
||||||
|
a = lpwStr1[i];
|
||||||
|
b = lpwStr2[i];
|
||||||
|
if (a >= 'A' && a <= 'Z')
|
||||||
|
a += 32;
|
||||||
|
if (b >= 'A' && b <= 'Z')
|
||||||
|
b += 32;
|
||||||
|
if (a != b)
|
||||||
|
{
|
||||||
|
match = FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
|
||||||
BOOL ParseFileName(
|
BOOL ParseFileName(
|
||||||
PDARKMODULE pdModule,
|
PDARKMODULE pdModule,
|
||||||
LPWSTR lpwFileName
|
LPWSTR lpwFileName
|
||||||
@@ -8,9 +42,7 @@ BOOL ParseFileName(
|
|||||||
{
|
{
|
||||||
HEAPALLOC pHeapAlloc = (HEAPALLOC)GetFunctionAddress(IsModulePresent(L"Kernel32.dll"), "HeapAlloc");
|
HEAPALLOC pHeapAlloc = (HEAPALLOC)GetFunctionAddress(IsModulePresent(L"Kernel32.dll"), "HeapAlloc");
|
||||||
GETPROCESSHEAP pGetProcessHeap = (GETPROCESSHEAP)GetFunctionAddress(IsModulePresent(L"Kernel32.dll"), "GetProcessHeap");
|
GETPROCESSHEAP pGetProcessHeap = (GETPROCESSHEAP)GetFunctionAddress(IsModulePresent(L"Kernel32.dll"), "GetProcessHeap");
|
||||||
_WSPLITPATH p_wsplitpath = (_WSPLITPATH)GetFunctionAddress(IsModulePresent(L"ucrtbased.dll"), "_wsplitpath");
|
PATHFINDFILENAMEW pPathFindFileNameW = (PATHFINDFILENAMEW)GetFunctionAddress(IsModulePresent(L"Shlwapi.dll"), "PathFindFileNameW");
|
||||||
WCSCPY pwcscpy = (WCSCPY)GetFunctionAddress(IsModulePresent(L"ucrtbased.dll"), "wcscpy");
|
|
||||||
WCSCAT pwcscat = (WCSCAT)GetFunctionAddress(IsModulePresent(L"ucrtbased.dll"), "wcscat");
|
|
||||||
|
|
||||||
if (lpwFileName == NULL)
|
if (lpwFileName == NULL)
|
||||||
{
|
{
|
||||||
@@ -33,53 +65,21 @@ BOOL ParseFileName(
|
|||||||
MAX_PATH * 2
|
MAX_PATH * 2
|
||||||
);
|
);
|
||||||
|
|
||||||
PWCHAR lpwExt = (PWCHAR)pHeapAlloc(
|
if (!pdModule->CrackedDLLName)
|
||||||
hHeap,
|
|
||||||
HEAP_ZERO_MEMORY,
|
|
||||||
MAX_PATH
|
|
||||||
);
|
|
||||||
|
|
||||||
PWCHAR lpwFilename = (PWCHAR)pHeapAlloc(
|
|
||||||
hHeap,
|
|
||||||
HEAP_ZERO_MEMORY,
|
|
||||||
MAX_PATH
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!pdModule->CrackedDLLName || !lpwExt || !lpwFilename)
|
|
||||||
{
|
{
|
||||||
pdModule->ErrorMsg = L"Failed to allocate memory";
|
pdModule->ErrorMsg = L"Failed to allocate memory";
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
p_wsplitpath(
|
LPWSTR lpwFileNameLocation = pPathFindFileNameW(lpwFileName);
|
||||||
lpwFileName,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
lpwFilename,
|
|
||||||
lpwExt
|
|
||||||
);
|
|
||||||
|
|
||||||
if (lpwFilename == NULL || lpwExt == NULL)
|
/*
|
||||||
{
|
Copy the length of the filename modulo sizeof pdModule->CrackedDLLName - 1 for null byte.
|
||||||
pdModule->ErrorMsg = L"Failed to crack filename";
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
PCHAR lpCpy = (PCHAR)pwcscpy(
|
TODO:
|
||||||
pdModule->CrackedDLLName,
|
Get a working wstrcpy implementation
|
||||||
lpwFilename
|
*/
|
||||||
);
|
memcpy(pdModule->CrackedDLLName, lpwFileNameLocation, (WideStringLength(lpwFileNameLocation) % (MAX_PATH - 1)) * 2);
|
||||||
|
|
||||||
PCHAR lpCat = (PCHAR)pwcscat(
|
|
||||||
pdModule->CrackedDLLName,
|
|
||||||
lpwExt
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!lpCpy || !lpCat)
|
|
||||||
{
|
|
||||||
pdModule->ErrorMsg = L"Failed to format cracked path";
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -170,7 +170,16 @@ PDARKMODULE DarkLoadLibrary(
|
|||||||
{
|
{
|
||||||
HEAPALLOC pHeapAlloc = (HEAPALLOC)GetFunctionAddress(IsModulePresent(L"Kernel32.dll"), "HeapAlloc");
|
HEAPALLOC pHeapAlloc = (HEAPALLOC)GetFunctionAddress(IsModulePresent(L"Kernel32.dll"), "HeapAlloc");
|
||||||
GETPROCESSHEAP pGetProcessHeap = (GETPROCESSHEAP)GetFunctionAddress(IsModulePresent(L"Kernel32.dll"), "GetProcessHeap");
|
GETPROCESSHEAP pGetProcessHeap = (GETPROCESSHEAP)GetFunctionAddress(IsModulePresent(L"Kernel32.dll"), "GetProcessHeap");
|
||||||
WCSCAT pwcscat = (WCSCAT)GetFunctionAddress(IsModulePresent(L"ucrtbased.dll"), "wcscat");
|
|
||||||
|
/*
|
||||||
|
TODO:
|
||||||
|
I would really love to stop using error messages that need this.
|
||||||
|
All the other safe versions of wsprintfW are located in the CRT,
|
||||||
|
which is an issue if there is no CRT in the process.
|
||||||
|
|
||||||
|
For now let us hope nobody will pass a name larger than 500 bytes. :/
|
||||||
|
*/
|
||||||
|
WSPRINTFW pwsprintfW = (WSPRINTFW)GetFunctionAddress(IsModulePresent(L"User32.dll"), "wsprintfW");
|
||||||
|
|
||||||
PDARKMODULE dModule = (DARKMODULE*)pHeapAlloc(pGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DARKMODULE));
|
PDARKMODULE dModule = (DARKMODULE*)pHeapAlloc(pGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DARKMODULE));
|
||||||
if (!dModule)
|
if (!dModule)
|
||||||
@@ -217,9 +226,7 @@ PDARKMODULE DarkLoadLibrary(
|
|||||||
lpwName = dModule->CrackedDLLName;
|
lpwName = dModule->CrackedDLLName;
|
||||||
}
|
}
|
||||||
|
|
||||||
HMODULE hModule = IsModulePresent(
|
HMODULE hModule = IsModulePresent(lpwName);
|
||||||
lpwName
|
|
||||||
);
|
|
||||||
|
|
||||||
if (hModule != NULL)
|
if (hModule != NULL)
|
||||||
{
|
{
|
||||||
@@ -236,8 +243,7 @@ PDARKMODULE DarkLoadLibrary(
|
|||||||
if (!dModule->ErrorMsg)
|
if (!dModule->ErrorMsg)
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
|
|
||||||
pwcscat(dModule->ErrorMsg, L"Data is an invalid PE: ");
|
pwsprintfW(dModule->ErrorMsg, TEXT("Data is an invalid PE: %s"), lpwName);
|
||||||
pwcscat(dModule->ErrorMsg, lpwName);
|
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,8 +254,7 @@ PDARKMODULE DarkLoadLibrary(
|
|||||||
if (!dModule->ErrorMsg)
|
if (!dModule->ErrorMsg)
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
|
|
||||||
pwcscat(dModule->ErrorMsg, L"Failed to map sections: ");
|
pwsprintfW(dModule->ErrorMsg, TEXT("Failed to map sections: %s"), lpwName);
|
||||||
pwcscat(dModule->ErrorMsg, lpwName);
|
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,8 +265,7 @@ PDARKMODULE DarkLoadLibrary(
|
|||||||
if (!dModule->ErrorMsg)
|
if (!dModule->ErrorMsg)
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
|
|
||||||
pwcscat(dModule->ErrorMsg, L"Failed to resolve imports: ");
|
pwsprintfW(dModule->ErrorMsg, TEXT("Failed to resolve imports: %s"), lpwName);
|
||||||
pwcscat(dModule->ErrorMsg, lpwName);
|
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,8 +278,7 @@ PDARKMODULE DarkLoadLibrary(
|
|||||||
if (!dModule->ErrorMsg)
|
if (!dModule->ErrorMsg)
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
|
|
||||||
pwcscat(dModule->ErrorMsg, L"Failed to link module to PEB: ");
|
pwsprintfW(dModule->ErrorMsg, TEXT("Failed to link module to PEB: %s"), lpwName);
|
||||||
pwcscat(dModule->ErrorMsg, lpwName);
|
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -287,8 +290,7 @@ PDARKMODULE DarkLoadLibrary(
|
|||||||
if (!dModule->ErrorMsg)
|
if (!dModule->ErrorMsg)
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
|
|
||||||
pwcscat(dModule->ErrorMsg, L"Failed to execute: ");
|
pwsprintfW(dModule->ErrorMsg, TEXT("Failed to execute: %s"), lpwName);
|
||||||
pwcscat(dModule->ErrorMsg, lpwName);
|
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ VOID main()
|
|||||||
|
|
||||||
PDARKMODULE DarkModule = DarkLoadLibrary(
|
PDARKMODULE DarkModule = DarkLoadLibrary(
|
||||||
LOAD_LOCAL_FILE,
|
LOAD_LOCAL_FILE,
|
||||||
L"TestDLL.dll",
|
L".\\amsi.dll",
|
||||||
NULL,
|
NULL,
|
||||||
0,
|
0,
|
||||||
NULL
|
NULL
|
||||||
|
|||||||
@@ -27,8 +27,6 @@ PLDR_DATA_TABLE_ENTRY2 FindLdrTableEntry(
|
|||||||
PLDR_DATA_TABLE_ENTRY2 pCurEntry;
|
PLDR_DATA_TABLE_ENTRY2 pCurEntry;
|
||||||
PLIST_ENTRY pListHead, pListEntry;
|
PLIST_ENTRY pListHead, pListEntry;
|
||||||
|
|
||||||
_WCSNICMP p_wcsnicmp = (_WCSNICMP)GetFunctionAddress(IsModulePresent(L"ucrtbased.dll"), "_wcsnicmp");
|
|
||||||
|
|
||||||
pPeb = (PPEB2)READ_MEMLOC(PEB_OFFSET);
|
pPeb = (PPEB2)READ_MEMLOC(PEB_OFFSET);
|
||||||
|
|
||||||
if (pPeb == NULL)
|
if (pPeb == NULL)
|
||||||
@@ -44,10 +42,10 @@ PLDR_DATA_TABLE_ENTRY2 FindLdrTableEntry(
|
|||||||
pCurEntry = CONTAINING_RECORD(pListEntry, LDR_DATA_TABLE_ENTRY2, InLoadOrderLinks);
|
pCurEntry = CONTAINING_RECORD(pListEntry, LDR_DATA_TABLE_ENTRY2, InLoadOrderLinks);
|
||||||
pListEntry = pListEntry->Flink;
|
pListEntry = pListEntry->Flink;
|
||||||
|
|
||||||
INT BaseName1 = p_wcsnicmp(BaseName, pCurEntry->BaseDllName.Buffer, (pCurEntry->BaseDllName.Length / sizeof(wchar_t)) - 4);
|
//BOOL BaseName1 = WideStringCompare(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));
|
BOOL BaseName2 = WideStringCompare(BaseName, pCurEntry->BaseDllName.Buffer, WideStringLength(BaseName));
|
||||||
|
|
||||||
if (!BaseName1 || !BaseName2)
|
if (BaseName2 == TRUE)
|
||||||
{
|
{
|
||||||
return pCurEntry;
|
return pCurEntry;
|
||||||
}
|
}
|
||||||
@@ -64,6 +62,11 @@ PRTL_RB_TREE FindModuleBaseAddressIndex()
|
|||||||
PRTL_BALANCED_NODE pNode = NULL;
|
PRTL_BALANCED_NODE pNode = NULL;
|
||||||
PRTL_RB_TREE pModBaseAddrIndex = NULL;
|
PRTL_RB_TREE pModBaseAddrIndex = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODO:
|
||||||
|
Implement these manually cause these could totally be hooked
|
||||||
|
and various other reasons
|
||||||
|
*/
|
||||||
RTLCOMPAREMEMORY pRtlCompareMemory = (RTLCOMPAREMEMORY)GetFunctionAddress(IsModulePresent(L"ntdll.dll"), "RtlCompareMemory");
|
RTLCOMPAREMEMORY pRtlCompareMemory = (RTLCOMPAREMEMORY)GetFunctionAddress(IsModulePresent(L"ntdll.dll"), "RtlCompareMemory");
|
||||||
STRCMP pstrcmp = (STRCMP)GetFunctionAddress(IsModulePresent(L"ntdll.dll"), "strcmp");
|
STRCMP pstrcmp = (STRCMP)GetFunctionAddress(IsModulePresent(L"ntdll.dll"), "strcmp");
|
||||||
|
|
||||||
@@ -307,11 +310,27 @@ HMODULE IsModulePresentA(
|
|||||||
char* Name
|
char* Name
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
MBSTOWCS pmbstowcs = (MBSTOWCS)GetFunctionAddress(IsModulePresent(L"ucrtbased.dll"), "mbstowcs");
|
MULTIBYTETOWIDECHAR pMultiByteToWideChar = (MULTIBYTETOWIDECHAR)GetFunctionAddress(IsModulePresent(L"kernel32.dll"), "MultiByteToWideChar");
|
||||||
|
|
||||||
wchar_t wtext[500];
|
WCHAR* wideName = NULL;
|
||||||
pmbstowcs(wtext, Name, strlen(Name) + 1);
|
DWORD wideNameSize = 0;
|
||||||
return IsModulePresent(wtext);
|
|
||||||
|
// MultiByteToWideChar returns size in characters, not bytes
|
||||||
|
wideNameSize = pMultiByteToWideChar(CP_UTF8, 0, Name, -1, NULL, 0) * 2;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Attempt to allocate this on the stack, seeing as it's faster and we can attempt
|
||||||
|
to avoid funny shit like heap fragmentation on a simple temp var
|
||||||
|
*/
|
||||||
|
wideName = (WCHAR*)_malloca(wideNameSize);
|
||||||
|
|
||||||
|
pMultiByteToWideChar(CP_UTF8, 0, Name, -1, wideName, wideNameSize);
|
||||||
|
|
||||||
|
HMODULE hModule = IsModulePresent(wideName);
|
||||||
|
|
||||||
|
_freea(wideName);
|
||||||
|
|
||||||
|
return hModule;
|
||||||
}
|
}
|
||||||
|
|
||||||
HMODULE IsModulePresent(
|
HMODULE IsModulePresent(
|
||||||
@@ -336,6 +355,10 @@ HMODULE IsModulePresent(
|
|||||||
|
|
||||||
pLdrTbl = (PLDR_DATA_TABLE_ENTRY2)ucModPtrOff;
|
pLdrTbl = (PLDR_DATA_TABLE_ENTRY2)ucModPtrOff;
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODO:
|
||||||
|
Make this its own ANSI case-insensitive string compare function
|
||||||
|
*/
|
||||||
BOOL match = TRUE;
|
BOOL match = TRUE;
|
||||||
for (int i = 0; i < pLdrTbl->BaseDllName.Length/2; i++)
|
for (int i = 0; i < pLdrTbl->BaseDllName.Length/2; i++)
|
||||||
{
|
{
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user