mirror of
https://github.com/monoxgas/sRDI
synced 2026-06-06 16:14:36 +00:00
Huge re-factor of the base RDI code
This commit is contained in:
+250
-406
@@ -5,6 +5,7 @@
|
||||
#include "GetProcAddressWithHash.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <winternl.h>
|
||||
#include <intrin.h>
|
||||
|
||||
// we declare some common stuff in here...
|
||||
@@ -17,22 +18,6 @@
|
||||
#define DEREF_16( name )*(WORD *)(name)
|
||||
#define DEREF_8( name )*(BYTE *)(name)
|
||||
|
||||
typedef ULONG_PTR(WINAPI * REFLECTIVELOADER)(LPVOID lpParameter, LPVOID lpLibraryAddress, DWORD dwFunctionHash, LPVOID lpUserData, DWORD nUserdataLen, BOOL exitThread);
|
||||
typedef BOOL(WINAPI * DLLMAIN)(HINSTANCE, DWORD, LPVOID);
|
||||
|
||||
typedef HMODULE(WINAPI * LOADLIBRARYA)(LPCSTR);
|
||||
typedef FARPROC(WINAPI * GETPROCADDRESS)(HMODULE, LPCSTR);
|
||||
typedef LPVOID(WINAPI * VIRTUALALLOC)(LPVOID, SIZE_T, DWORD, DWORD);
|
||||
typedef VOID(WINAPI * EXITTHREAD)(DWORD);
|
||||
typedef DWORD(NTAPI * NTFLUSHINSTRUCTIONCACHE)(HANDLE, PVOID, ULONG);
|
||||
typedef VOID(WINAPI * GETNATIVESYSTEMINFO)(LPSYSTEM_INFO);
|
||||
typedef BOOL(WINAPI * VIRTUALPROTECT)(LPVOID, SIZE_T, DWORD, PDWORD);
|
||||
typedef int (WINAPI * MESSAGEBOXA)(HWND, LPSTR, LPSTR, UINT);
|
||||
typedef BOOL(WINAPI * VIRTUALFREE)(LPVOID, SIZE_T, DWORD);
|
||||
typedef BOOL(WINAPI * LOCALFREE)(LPVOID);
|
||||
|
||||
typedef BOOL(* EXPORTFUNC)(LPVOID, DWORD);
|
||||
|
||||
/** NOTE: module hashes are computed using all-caps unicode strings */
|
||||
#define KERNEL32DLL_HASH 0x6A4ABC5B
|
||||
#define NTDLLDLL_HASH 0x3CFA685D
|
||||
@@ -53,6 +38,7 @@ typedef BOOL(* EXPORTFUNC)(LPVOID, DWORD);
|
||||
|
||||
#define SRDI_CLEARHEADER 0x1
|
||||
#define SRDI_CLEARMEMORY 0x2
|
||||
#define SRDI_OBFUSCATEIMPORTS 0x4
|
||||
|
||||
#ifdef _WIN64
|
||||
#define HOST_MACHINE IMAGE_FILE_MACHINE_AMD64
|
||||
@@ -60,87 +46,22 @@ typedef BOOL(* EXPORTFUNC)(LPVOID, DWORD);
|
||||
#define HOST_MACHINE IMAGE_FILE_MACHINE_I386
|
||||
#endif
|
||||
|
||||
typedef struct _UNICODE_STR
|
||||
{
|
||||
USHORT Length;
|
||||
USHORT MaximumLength;
|
||||
PWSTR pBuffer;
|
||||
} UNICODE_STR, *PUNICODE_STR;
|
||||
|
||||
typedef struct _PEB_FREE_BLOCK
|
||||
{
|
||||
struct _PEB_FREE_BLOCK * pNext;
|
||||
DWORD dwSize;
|
||||
} PEB_FREE_BLOCK, *PPEB_FREE_BLOCK;
|
||||
typedef BOOL(WINAPI * DLLMAIN)(HINSTANCE, DWORD, LPVOID);
|
||||
typedef BOOL(*EXPORTFUNC)(LPVOID, DWORD);
|
||||
|
||||
typedef struct __PEB
|
||||
{
|
||||
BYTE bInheritedAddressSpace;
|
||||
BYTE bReadImageFileExecOptions;
|
||||
BYTE bBeingDebugged;
|
||||
BYTE bSpareBool;
|
||||
LPVOID lpMutant;
|
||||
LPVOID lpImageBaseAddress;
|
||||
PPEB_LDR_DATA pLdr;
|
||||
LPVOID lpProcessParameters;
|
||||
LPVOID lpSubSystemData;
|
||||
LPVOID lpProcessHeap;
|
||||
PRTL_CRITICAL_SECTION pFastPebLock;
|
||||
LPVOID lpFastPebLockRoutine;
|
||||
LPVOID lpFastPebUnlockRoutine;
|
||||
DWORD dwEnvironmentUpdateCount;
|
||||
LPVOID lpKernelCallbackTable;
|
||||
DWORD dwSystemReserved;
|
||||
DWORD dwAtlThunkSListPtr32;
|
||||
PPEB_FREE_BLOCK pFreeList;
|
||||
DWORD dwTlsExpansionCounter;
|
||||
LPVOID lpTlsBitmap;
|
||||
DWORD dwTlsBitmapBits[2];
|
||||
LPVOID lpReadOnlySharedMemoryBase;
|
||||
LPVOID lpReadOnlySharedMemoryHeap;
|
||||
LPVOID lpReadOnlyStaticServerData;
|
||||
LPVOID lpAnsiCodePageData;
|
||||
LPVOID lpOemCodePageData;
|
||||
LPVOID lpUnicodeCaseTableData;
|
||||
DWORD dwNumberOfProcessors;
|
||||
DWORD dwNtGlobalFlag;
|
||||
LARGE_INTEGER liCriticalSectionTimeout;
|
||||
DWORD dwHeapSegmentReserve;
|
||||
DWORD dwHeapSegmentCommit;
|
||||
DWORD dwHeapDeCommitTotalFreeThreshold;
|
||||
DWORD dwHeapDeCommitFreeBlockThreshold;
|
||||
DWORD dwNumberOfHeaps;
|
||||
DWORD dwMaximumNumberOfHeaps;
|
||||
LPVOID lpProcessHeaps;
|
||||
LPVOID lpGdiSharedHandleTable;
|
||||
LPVOID lpProcessStarterHelper;
|
||||
DWORD dwGdiDCAttributeList;
|
||||
LPVOID lpLoaderLock;
|
||||
DWORD dwOSMajorVersion;
|
||||
DWORD dwOSMinorVersion;
|
||||
WORD wOSBuildNumber;
|
||||
WORD wOSCSDVersion;
|
||||
DWORD dwOSPlatformId;
|
||||
DWORD dwImageSubsystem;
|
||||
DWORD dwImageSubsystemMajorVersion;
|
||||
DWORD dwImageSubsystemMinorVersion;
|
||||
DWORD dwImageProcessAffinityMask;
|
||||
DWORD dwGdiHandleBuffer[34];
|
||||
LPVOID lpPostProcessInitRoutine;
|
||||
LPVOID lpTlsExpansionBitmap;
|
||||
DWORD dwTlsExpansionBitmapBits[32];
|
||||
DWORD dwSessionId;
|
||||
ULARGE_INTEGER liAppCompatFlags;
|
||||
ULARGE_INTEGER liAppCompatFlagsUser;
|
||||
LPVOID lppShimData;
|
||||
LPVOID lpAppCompatInfo;
|
||||
UNICODE_STR usCSDVersion;
|
||||
LPVOID lpActivationContextData;
|
||||
LPVOID lpProcessAssemblyStorageMap;
|
||||
LPVOID lpSystemDefaultActivationContextData;
|
||||
LPVOID lpSystemAssemblyStorageMap;
|
||||
DWORD dwMinimumStackCommit;
|
||||
} _PEB, *_PPEB;
|
||||
typedef HMODULE(WINAPI * LOADLIBRARYA)(LPCSTR);
|
||||
typedef ULONG_PTR(WINAPI * GETPROCADDRESS)(HMODULE, LPCSTR);
|
||||
typedef LPVOID(WINAPI * VIRTUALALLOC)(LPVOID, SIZE_T, DWORD, DWORD);
|
||||
typedef VOID(WINAPI * EXITTHREAD)(DWORD);
|
||||
typedef DWORD(NTAPI * NTFLUSHINSTRUCTIONCACHE)(HANDLE, PVOID, ULONG);
|
||||
typedef VOID(WINAPI * GETNATIVESYSTEMINFO)(LPSYSTEM_INFO);
|
||||
typedef BOOL(WINAPI * VIRTUALPROTECT)(LPVOID, SIZE_T, DWORD, PDWORD);
|
||||
typedef int (WINAPI * MESSAGEBOXA)(HWND, LPSTR, LPSTR, UINT);
|
||||
typedef BOOL(WINAPI * VIRTUALFREE)(LPVOID, SIZE_T, DWORD);
|
||||
typedef BOOL(WINAPI * LOCALFREE)(LPVOID);
|
||||
|
||||
#define RVA(type, base, rva) (type)((ULONG_PTR) base + rva)
|
||||
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 4214 ) // nonstandard extension
|
||||
@@ -156,117 +77,112 @@ AlignValueUp(size_t value, size_t alignment) {
|
||||
return (value + alignment - 1) & ~(alignment - 1);
|
||||
}
|
||||
|
||||
// Write the logic for the primary payload here
|
||||
// Normally, I would call this 'main' but if you call a function 'main', link.exe requires that you link against the CRT
|
||||
// Rather, I will pass a linker option of "/ENTRY:ExecutePayload" in order to get around this issue.
|
||||
ULONG_PTR ExecutePayload(ULONG_PTR uiLibraryAddress, DWORD dwFunctionHash, LPVOID lpUserData, DWORD nUserdataLen, DWORD flags)
|
||||
ULONG_PTR LoadDLL(PBYTE dllData, DWORD dwFunctionHash, LPVOID lpUserData, DWORD nUserdataLen, DWORD flags)
|
||||
{
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 4055 ) // Ignore cast warnings
|
||||
|
||||
// the functions we need
|
||||
// Function pointers
|
||||
LOADLIBRARYA pLoadLibraryA = NULL;
|
||||
GETPROCADDRESS pGetProcAddress = NULL;
|
||||
VIRTUALALLOC pVirtualAlloc = NULL;
|
||||
EXITTHREAD pExitThread = NULL;
|
||||
NTFLUSHINSTRUCTIONCACHE pNtFlushInstructionCache = NULL;
|
||||
GETNATIVESYSTEMINFO pGetNativeSystemInfo = NULL;
|
||||
VIRTUALPROTECT pVirtualProtect = NULL;
|
||||
VIRTUALFREE pVirtualFree = NULL;
|
||||
LOCALFREE pLocalFree = NULL;
|
||||
//MESSAGEBOXA pMessageBoxA = NULL;
|
||||
/// MESSAGEBOXA pMessageBoxA = NULL;
|
||||
|
||||
PIMAGE_DATA_DIRECTORY directory = NULL;
|
||||
PIMAGE_EXPORT_DIRECTORY exports = NULL;
|
||||
int idx;
|
||||
DWORD nameSearchIndex;
|
||||
DWORD *nameRef = NULL;
|
||||
WORD *ordinal = NULL;
|
||||
PCSTR pTempChar;
|
||||
DWORD dwCalculatedFunctionHash;
|
||||
// PE data
|
||||
PIMAGE_NT_HEADERS ntHeaders;
|
||||
PIMAGE_SECTION_HEADER sectionHeader;
|
||||
PIMAGE_DATA_DIRECTORY dataDir;
|
||||
PIMAGE_IMPORT_DESCRIPTOR importDesc;
|
||||
PIMAGE_DELAYLOAD_DESCRIPTOR delayDesc;
|
||||
PIMAGE_THUNK_DATA firstThunk, origFirstThunk;
|
||||
PIMAGE_IMPORT_BY_NAME importByName;
|
||||
PIMAGE_TLS_DIRECTORY tlsDir;
|
||||
PIMAGE_TLS_CALLBACK * callback;
|
||||
PIMAGE_BASE_RELOCATION relocation;
|
||||
PIMAGE_RELOC relocList;
|
||||
PIMAGE_EXPORT_DIRECTORY exportDir;
|
||||
PDWORD expName;
|
||||
PWORD expOrdinal;
|
||||
LPCSTR expNameStr;
|
||||
|
||||
// Functions
|
||||
DLLMAIN dllMain;
|
||||
EXPORTFUNC exportFunc;
|
||||
|
||||
// Memory protections
|
||||
DWORD executable, readable, writeable, protect;
|
||||
|
||||
// Counters
|
||||
DWORD i = 0;
|
||||
DWORD c = 0;
|
||||
|
||||
// Alignment
|
||||
DWORD lastSectionEnd;
|
||||
DWORD endOfSection;
|
||||
DWORD alignedImageSize;
|
||||
|
||||
ULONGLONG baseOffset;
|
||||
SYSTEM_INFO sysInfo;
|
||||
|
||||
DWORD executable;
|
||||
DWORD readable;
|
||||
DWORD writeable;
|
||||
DWORD protect;
|
||||
DWORD oldProtect = 0;
|
||||
// General
|
||||
PBYTE libraryAddress;
|
||||
DWORD funcHash;
|
||||
|
||||
// Relocated base
|
||||
ULONG_PTR baseAddress;
|
||||
|
||||
PIMAGE_SECTION_HEADER section;
|
||||
size_t optionalSectionSize;
|
||||
size_t lastSectionEnd = 0;
|
||||
|
||||
EXPORTFUNC f = NULL;
|
||||
|
||||
// the initial location of this image in memory
|
||||
//ULONG_PTR uiLibraryAddress;
|
||||
// the kernels base address and later this images newly loaded base address
|
||||
ULONG_PTR uiBaseAddress;
|
||||
|
||||
// variables for processing the kernels export table
|
||||
ULONG_PTR uiAddressArray;
|
||||
ULONG_PTR uiNameArray;
|
||||
ULONG_PTR uiExportDir;
|
||||
|
||||
// variables for loading this image
|
||||
ULONG_PTR uiHeaderValue;
|
||||
ULONG_PTR uiValueA;
|
||||
ULONG_PTR uiValueB;
|
||||
ULONG_PTR uiValueC;
|
||||
ULONG_PTR uiValueD;
|
||||
ULONG_PTR uiValueE;
|
||||
|
||||
// exit code for current thread
|
||||
DWORD dwExitCode = 1;
|
||||
// -------
|
||||
|
||||
///
|
||||
// STEP 1: Locate all the required functions
|
||||
// STEP 1: locate all the required functions
|
||||
///
|
||||
|
||||
//pMessageBoxA = (MESSAGEBOXA)GetProcAddressWithHash(MESSAGEBOXA_HASH);
|
||||
|
||||
pLoadLibraryA = (LOADLIBRARYA)GetProcAddressWithHash(LOADLIBRARYA_HASH);
|
||||
pGetProcAddress = (GETPROCADDRESS)GetProcAddressWithHash(GETPROCADDRESS_HASH);
|
||||
pVirtualAlloc = (VIRTUALALLOC)GetProcAddressWithHash(VIRTUALALLOC_HASH);
|
||||
pVirtualProtect = (VIRTUALPROTECT)GetProcAddressWithHash(VIRTUALPROTECT_HASH);
|
||||
pExitThread = (EXITTHREAD)GetProcAddressWithHash(EXITTHREAD_HASH);
|
||||
pNtFlushInstructionCache = (NTFLUSHINSTRUCTIONCACHE)GetProcAddressWithHash(NTFLUSHINSTRUCTIONCACHE_HASH);
|
||||
pGetNativeSystemInfo = (GETNATIVESYSTEMINFO)GetProcAddressWithHash(GETNATIVESYSTEMINFO_HASH);
|
||||
/// pMessageBoxA = (MESSAGEBOXA)GetProcAddressWithHash(MESSAGEBOXA_HASH);
|
||||
|
||||
if (!pLoadLibraryA || !pGetProcAddress || !pVirtualAlloc || !pVirtualProtect ||
|
||||
!pNtFlushInstructionCache || !pGetNativeSystemInfo) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
// STEP 2: load our image into a new permanent location in memory
|
||||
///
|
||||
|
||||
// get the VA of the NT Header for the PE to be loaded
|
||||
uiHeaderValue = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;
|
||||
|
||||
ntHeaders = RVA(PIMAGE_NT_HEADERS, dllData, ((PIMAGE_DOS_HEADER)dllData)->e_lfanew);
|
||||
|
||||
// Perform sanity checks on the image (Stolen from https://github.com/fancycode/MemoryModule/blob/master/MemoryModule.c)
|
||||
|
||||
if (((PIMAGE_NT_HEADERS)uiHeaderValue)->Signature != IMAGE_NT_SIGNATURE)
|
||||
if (ntHeaders->Signature != IMAGE_NT_SIGNATURE)
|
||||
return 0;
|
||||
|
||||
if (((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.Machine != HOST_MACHINE)
|
||||
if (ntHeaders->FileHeader.Machine != HOST_MACHINE)
|
||||
return 0;
|
||||
|
||||
if (((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SectionAlignment & 1)
|
||||
if (ntHeaders->OptionalHeader.SectionAlignment & 1)
|
||||
return 0;
|
||||
|
||||
|
||||
// Align the image to the page size (Stolen from https://github.com/fancycode/MemoryModule/blob/master/MemoryModule.c)
|
||||
|
||||
section = IMAGE_FIRST_SECTION(((PIMAGE_NT_HEADERS)uiHeaderValue));
|
||||
optionalSectionSize = ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SectionAlignment;
|
||||
for (idx = 0; idx < ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.NumberOfSections; idx++, section++) {
|
||||
size_t endOfSection;
|
||||
if (section->SizeOfRawData == 0) {
|
||||
// Section without data in the DLL
|
||||
endOfSection = section->VirtualAddress + optionalSectionSize;
|
||||
sectionHeader = IMAGE_FIRST_SECTION(ntHeaders);
|
||||
lastSectionEnd = 0;
|
||||
|
||||
for (i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++, sectionHeader++) {
|
||||
if (sectionHeader->SizeOfRawData == 0) {
|
||||
endOfSection = sectionHeader->VirtualAddress + ntHeaders->OptionalHeader.SectionAlignment;
|
||||
}
|
||||
else {
|
||||
endOfSection = section->VirtualAddress + section->SizeOfRawData;
|
||||
endOfSection = sectionHeader->VirtualAddress + sectionHeader->SizeOfRawData;
|
||||
}
|
||||
|
||||
if (endOfSection > lastSectionEnd) {
|
||||
@@ -275,213 +191,161 @@ ULONG_PTR ExecutePayload(ULONG_PTR uiLibraryAddress, DWORD dwFunctionHash, LPVOI
|
||||
}
|
||||
|
||||
pGetNativeSystemInfo(&sysInfo);
|
||||
alignedImageSize = (DWORD)AlignValueUp(((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfImage, sysInfo.dwPageSize);
|
||||
if (alignedImageSize != AlignValueUp(lastSectionEnd, sysInfo.dwPageSize))
|
||||
alignedImageSize = (DWORD)AlignValueUp(ntHeaders->OptionalHeader.SizeOfImage, sysInfo.dwPageSize);
|
||||
if (alignedImageSize != AlignValueUp(lastSectionEnd, sysInfo.dwPageSize)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// allocate all the memory for the DLL to be loaded into. Attempt to use the preffered base address
|
||||
// Also zeros all memory and marks it as READ and WRITE.
|
||||
uiBaseAddress = (ULONG_PTR)pVirtualAlloc(
|
||||
(LPVOID)(((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.ImageBase),
|
||||
((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfImage,
|
||||
// Allocate all the memory for the DLL to be loaded into. Attempt to use the preferred base address.
|
||||
|
||||
baseAddress = (ULONG_PTR)pVirtualAlloc(
|
||||
(LPVOID)(ntHeaders->OptionalHeader.ImageBase),
|
||||
alignedImageSize,
|
||||
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE
|
||||
);
|
||||
|
||||
if (uiBaseAddress == 0)
|
||||
uiBaseAddress = (ULONG_PTR)pVirtualAlloc(
|
||||
NULL,
|
||||
((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfImage,
|
||||
if (baseAddress == 0) {
|
||||
baseAddress = (ULONG_PTR)pVirtualAlloc(
|
||||
NULL,
|
||||
alignedImageSize,
|
||||
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE
|
||||
);
|
||||
}
|
||||
|
||||
// we must now copy over the headers
|
||||
uiValueA = ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfHeaders;
|
||||
uiValueB = uiLibraryAddress;
|
||||
uiValueC = uiBaseAddress;
|
||||
uiValueD = 0;
|
||||
uiValueE = FIELD_OFFSET(IMAGE_DOS_HEADER, e_lfanew);
|
||||
// Copy over the headers
|
||||
|
||||
while (uiValueA--) {
|
||||
if ((flags & SRDI_CLEARHEADER) && uiValueD < (uiHeaderValue - uiLibraryAddress) && (uiValueD < uiValueE || uiValueD > (uiValueE + sizeof(WORD)))) {
|
||||
// Blow away everything before the NT_HEADERS. Leave e_lfanew;
|
||||
*(BYTE *)uiValueC++ = '\0';
|
||||
uiValueB++;
|
||||
if (flags & SRDI_CLEARHEADER) {
|
||||
((PIMAGE_DOS_HEADER)baseAddress)->e_lfanew = ((PIMAGE_DOS_HEADER)dllData)->e_lfanew;
|
||||
|
||||
for (i = ((PIMAGE_DOS_HEADER)dllData)->e_lfanew; i < ntHeaders->OptionalHeader.SizeOfHeaders; i++) {
|
||||
((PBYTE)baseAddress)[i] = ((PBYTE)dllData)[i];
|
||||
}
|
||||
else
|
||||
*(BYTE *)uiValueC++ = *(BYTE *)uiValueB++;
|
||||
|
||||
uiValueD++;
|
||||
}else{
|
||||
for (i = 0; i < ntHeaders->OptionalHeader.SizeOfHeaders; i++) {
|
||||
((PBYTE)baseAddress)[i] = ((PBYTE)dllData)[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
ntHeaders = RVA(PIMAGE_NT_HEADERS, baseAddress, ((PIMAGE_DOS_HEADER)baseAddress)->e_lfanew);
|
||||
|
||||
///
|
||||
// STEP 3: Load in the sections
|
||||
///
|
||||
|
||||
sectionHeader = IMAGE_FIRST_SECTION(ntHeaders);
|
||||
|
||||
for (i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++, sectionHeader++) {
|
||||
for (c = 0; c < sectionHeader->SizeOfRawData; c++) {
|
||||
((PBYTE)(baseAddress + sectionHeader->VirtualAddress))[c] = ((PBYTE)(dllData + sectionHeader->PointerToRawData))[c];
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
// STEP 3: load in all of our sections
|
||||
// STEP 4: process our import table
|
||||
///
|
||||
|
||||
// uiValueA = the VA of the first section
|
||||
uiValueA = ((ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader + ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.SizeOfOptionalHeader);
|
||||
dataDir = &ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
|
||||
|
||||
// iterate through all sections, loading them into memory.
|
||||
uiValueE = ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.NumberOfSections;
|
||||
while (uiValueE--)
|
||||
{
|
||||
// uiValueB is the VA for this section
|
||||
uiValueB = (uiBaseAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->VirtualAddress);
|
||||
if (dataDir->Size) {
|
||||
importDesc = RVA(PIMAGE_IMPORT_DESCRIPTOR, baseAddress, dataDir->VirtualAddress);
|
||||
|
||||
// uiValueC if the VA for this sections data
|
||||
uiValueC = (uiLibraryAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->PointerToRawData);
|
||||
for (; importDesc->Name; importDesc++) {
|
||||
|
||||
// copy the section over
|
||||
uiValueD = ((PIMAGE_SECTION_HEADER)uiValueA)->SizeOfRawData;
|
||||
libraryAddress = (PBYTE)pLoadLibraryA((LPCSTR)(baseAddress + importDesc->Name));
|
||||
firstThunk = RVA(PIMAGE_THUNK_DATA, baseAddress, importDesc->FirstThunk);
|
||||
origFirstThunk = RVA(PIMAGE_THUNK_DATA, baseAddress, importDesc->OriginalFirstThunk);
|
||||
|
||||
if (uiValueD != 0) {
|
||||
while (uiValueD--)
|
||||
*(BYTE *)uiValueB++ = *(BYTE *)uiValueC++;
|
||||
}
|
||||
|
||||
// get the VA of the next section
|
||||
uiValueA += sizeof(IMAGE_SECTION_HEADER);
|
||||
}
|
||||
|
||||
///
|
||||
// STEP 4: process our images import table
|
||||
///
|
||||
// iterate through all imported functions, importing by ordinal if no name present
|
||||
for (; origFirstThunk->u1.Function; firstThunk++, origFirstThunk++) {
|
||||
|
||||
// uiValueB = the address of the import directory
|
||||
uiValueB = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
|
||||
|
||||
// we assume their is an import table to process
|
||||
// uiValueC is the first entry in the import table
|
||||
uiValueC = (uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress);
|
||||
|
||||
// itterate through all imports
|
||||
while (((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name)
|
||||
{
|
||||
// use LoadLibraryA to load the imported module into memory
|
||||
uiLibraryAddress = (ULONG_PTR)pLoadLibraryA((LPCSTR)(uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name));
|
||||
|
||||
// uiValueD = VA of the OriginalFirstThunk
|
||||
uiValueD = (uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->OriginalFirstThunk);
|
||||
|
||||
// uiValueA = VA of the IAT (via first thunk not origionalfirstthunk)
|
||||
uiValueA = (uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->FirstThunk);
|
||||
|
||||
// itterate through all imported functions, importing by ordinal if no name present
|
||||
while (DEREF(uiValueA))
|
||||
{
|
||||
|
||||
// sanity check uiValueD as some compilers only import by FirstThunk
|
||||
if (((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal && uiValueD && ((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal & IMAGE_ORDINAL_FLAG)
|
||||
{
|
||||
|
||||
// get the VA of the modules NT Header
|
||||
uiExportDir = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;
|
||||
|
||||
// uiNameArray = the address of the modules export directory entry
|
||||
uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
|
||||
|
||||
// get the VA of the export directory
|
||||
uiExportDir = (uiLibraryAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress);
|
||||
|
||||
// get the VA for the array of addresses
|
||||
uiAddressArray = (uiLibraryAddress + ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfFunctions);
|
||||
|
||||
// use the import ordinal (- export ordinal base) as an index into the array of addresses
|
||||
uiAddressArray += ((IMAGE_ORDINAL(((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal) - ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->Base) * sizeof(DWORD));
|
||||
|
||||
// patch in the address for this imported function
|
||||
DEREF(uiValueA) = (uiLibraryAddress + DEREF_32(uiAddressArray));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// get the VA of this functions import by name struct
|
||||
uiValueB = (uiBaseAddress + DEREF(uiValueA));
|
||||
|
||||
// use GetProcAddress and patch in the address for this imported function
|
||||
DEREF(uiValueA) = (ULONG_PTR)pGetProcAddress((HMODULE)uiLibraryAddress, (LPCSTR)((PIMAGE_IMPORT_BY_NAME)uiValueB)->Name);
|
||||
}
|
||||
|
||||
// get the next imported function
|
||||
uiValueA += sizeof(ULONG_PTR);
|
||||
if (uiValueD)
|
||||
uiValueD += sizeof(ULONG_PTR);
|
||||
}
|
||||
|
||||
// get the next import
|
||||
uiValueC += sizeof(IMAGE_IMPORT_DESCRIPTOR);
|
||||
}
|
||||
|
||||
///
|
||||
// STEP 5: process all of our images relocations
|
||||
///
|
||||
|
||||
// calculate the base address delta and perform relocations (assuming we missed the preferred address)
|
||||
uiLibraryAddress = uiBaseAddress - ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.ImageBase;
|
||||
|
||||
if (uiLibraryAddress != 0) {
|
||||
// uiValueB = the address of the relocation directory
|
||||
uiValueB = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
|
||||
|
||||
// check if their are any relocations present
|
||||
if (((PIMAGE_DATA_DIRECTORY)uiValueB)->Size)
|
||||
{
|
||||
// uiValueC is now the first entry (IMAGE_BASE_RELOCATION)
|
||||
uiValueC = (uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress);
|
||||
|
||||
// and we itterate through all entries...
|
||||
while (((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock)
|
||||
{
|
||||
// uiValueA = the VA for this relocation block
|
||||
uiValueA = (uiBaseAddress + ((PIMAGE_BASE_RELOCATION)uiValueC)->VirtualAddress);
|
||||
|
||||
// uiValueB = number of entries in this relocation block
|
||||
uiValueB = (((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(IMAGE_RELOC);
|
||||
|
||||
// uiValueD is now the first entry in the current relocation block
|
||||
uiValueD = uiValueC + sizeof(IMAGE_BASE_RELOCATION);
|
||||
|
||||
// we itterate through all the entries in the current block...
|
||||
while (uiValueB--)
|
||||
{
|
||||
// perform the relocation, skipping IMAGE_REL_BASED_ABSOLUTE as required.
|
||||
// we dont use a switch statement to avoid the compiler building a jump table
|
||||
// which would not be very position independent!
|
||||
if (((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_DIR64)
|
||||
*(ULONG_PTR *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += uiLibraryAddress;
|
||||
else if (((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGHLOW)
|
||||
*(DWORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += (DWORD)uiLibraryAddress;
|
||||
else if (((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGH)
|
||||
*(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += HIWORD(uiLibraryAddress);
|
||||
else if (((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_LOW)
|
||||
*(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += LOWORD(uiLibraryAddress);
|
||||
|
||||
// get the next entry in the current relocation block
|
||||
uiValueD += sizeof(IMAGE_RELOC);
|
||||
if (IMAGE_SNAP_BY_ORDINAL(origFirstThunk->u1.Ordinal)) {
|
||||
firstThunk->u1.Function = (ULONGLONG)pGetProcAddress((HMODULE)libraryAddress, (LPCSTR)IMAGE_ORDINAL(origFirstThunk->u1.Ordinal));
|
||||
}
|
||||
else {
|
||||
importByName = RVA(PIMAGE_IMPORT_BY_NAME, baseAddress, origFirstThunk->u1.AddressOfData);
|
||||
firstThunk->u1.Function = (ULONGLONG)pGetProcAddress((HMODULE)libraryAddress, importByName->Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get the next entry in the relocation directory
|
||||
uiValueC = uiValueC + ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock;
|
||||
///
|
||||
// STEP 5: process our delayed import table
|
||||
///
|
||||
|
||||
dataDir = &ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT];
|
||||
|
||||
if (dataDir->Size) {
|
||||
delayDesc = RVA(PIMAGE_DELAYLOAD_DESCRIPTOR, baseAddress, dataDir->VirtualAddress);
|
||||
|
||||
for (; delayDesc->DllNameRVA; delayDesc++) {
|
||||
|
||||
libraryAddress = (PBYTE)pLoadLibraryA((LPCSTR)(baseAddress + delayDesc->DllNameRVA));
|
||||
firstThunk = RVA(PIMAGE_THUNK_DATA, baseAddress, delayDesc->ImportAddressTableRVA);
|
||||
origFirstThunk = RVA(PIMAGE_THUNK_DATA, baseAddress, delayDesc->ImportNameTableRVA);
|
||||
|
||||
// iterate through all imported functions, importing by ordinal if no name present
|
||||
for (; firstThunk->u1.Function; firstThunk++, origFirstThunk++) {
|
||||
if (IMAGE_SNAP_BY_ORDINAL(origFirstThunk->u1.Ordinal)) {
|
||||
firstThunk->u1.Function = (ULONGLONG)pGetProcAddress((HMODULE)libraryAddress, (LPCSTR)IMAGE_ORDINAL(origFirstThunk->u1.Ordinal));
|
||||
}
|
||||
else {
|
||||
importByName = RVA(PIMAGE_IMPORT_BY_NAME, baseAddress, origFirstThunk->u1.AddressOfData);
|
||||
firstThunk->u1.Function = (ULONGLONG)pGetProcAddress((HMODULE)libraryAddress, importByName->Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
// STEP 6: Finalize our sections. Set memory protections.
|
||||
// STEP 6: process all of our images relocations (assuming we missed the preferred address)
|
||||
///
|
||||
|
||||
uiValueA = ((ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader + ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.SizeOfOptionalHeader);
|
||||
baseOffset = baseAddress - ntHeaders->OptionalHeader.ImageBase;
|
||||
dataDir = &ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
|
||||
|
||||
// itterate through all sections, loading them into memory.
|
||||
uiValueE = ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.NumberOfSections;
|
||||
while (uiValueE--)
|
||||
{
|
||||
if (((PIMAGE_SECTION_HEADER)uiValueA)->SizeOfRawData > 0) {
|
||||
if (baseOffset && dataDir->Size) {
|
||||
|
||||
relocation = RVA(PIMAGE_BASE_RELOCATION, baseAddress, dataDir->VirtualAddress);
|
||||
|
||||
while (relocation->VirtualAddress) {
|
||||
relocList = (PIMAGE_RELOC)(relocation + 1);
|
||||
|
||||
while ((PBYTE)relocList != (PBYTE)relocation + relocation->SizeOfBlock) {
|
||||
|
||||
if (relocList->type == IMAGE_REL_BASED_DIR64)
|
||||
* (PULONG_PTR)((PBYTE)baseAddress + relocation->VirtualAddress + relocList->offset) += baseOffset;
|
||||
else if (relocList->type == IMAGE_REL_BASED_HIGHLOW)
|
||||
* (PULONG_PTR)((PBYTE)baseAddress + relocation->VirtualAddress + relocList->offset) += (DWORD)baseOffset;
|
||||
else if (relocList->type == IMAGE_REL_BASED_HIGH)
|
||||
* (PULONG_PTR)((PBYTE)baseAddress + relocation->VirtualAddress + relocList->offset) += HIWORD(baseOffset);
|
||||
else if (relocList->type == IMAGE_REL_BASED_LOW)
|
||||
* (PULONG_PTR)((PBYTE)baseAddress + relocation->VirtualAddress + relocList->offset) += LOWORD(baseOffset);
|
||||
|
||||
relocList++;
|
||||
}
|
||||
relocation = (PIMAGE_BASE_RELOCATION)relocList;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
// STEP 7: Finalize our sections. Set memory protections.
|
||||
///
|
||||
|
||||
sectionHeader = IMAGE_FIRST_SECTION(ntHeaders);
|
||||
|
||||
for (i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++, sectionHeader++) {
|
||||
|
||||
if (sectionHeader->SizeOfRawData) {
|
||||
|
||||
// determine protection flags based on characteristics
|
||||
executable = (((PIMAGE_SECTION_HEADER)uiValueA)->Characteristics & IMAGE_SCN_MEM_EXECUTE) != 0;
|
||||
readable = (((PIMAGE_SECTION_HEADER)uiValueA)->Characteristics & IMAGE_SCN_MEM_READ) != 0;
|
||||
writeable = (((PIMAGE_SECTION_HEADER)uiValueA)->Characteristics & IMAGE_SCN_MEM_WRITE) != 0;
|
||||
executable = (sectionHeader->Characteristics & IMAGE_SCN_MEM_EXECUTE) != 0;
|
||||
readable = (sectionHeader->Characteristics & IMAGE_SCN_MEM_READ) != 0;
|
||||
writeable = (sectionHeader->Characteristics & IMAGE_SCN_MEM_WRITE) != 0;
|
||||
|
||||
if (!executable && !readable && !writeable)
|
||||
protect = PAGE_NOACCESS;
|
||||
@@ -500,117 +364,97 @@ ULONG_PTR ExecutePayload(ULONG_PTR uiLibraryAddress, DWORD dwFunctionHash, LPVOI
|
||||
else if (executable && readable && writeable)
|
||||
protect = PAGE_EXECUTE_READWRITE;
|
||||
|
||||
if (((PIMAGE_SECTION_HEADER)uiValueA)->Characteristics & IMAGE_SCN_MEM_NOT_CACHED) {
|
||||
if (sectionHeader->Characteristics & IMAGE_SCN_MEM_NOT_CACHED) {
|
||||
protect |= PAGE_NOCACHE;
|
||||
}
|
||||
|
||||
// change memory access flags
|
||||
if (!pVirtualProtect((LPVOID)(uiBaseAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->VirtualAddress),
|
||||
((PIMAGE_SECTION_HEADER)uiValueA)->SizeOfRawData,
|
||||
protect, &oldProtect))
|
||||
return 0;
|
||||
pVirtualProtect(
|
||||
(LPVOID)(baseAddress + sectionHeader->VirtualAddress),
|
||||
sectionHeader->SizeOfRawData,
|
||||
protect, &protect
|
||||
);
|
||||
}
|
||||
|
||||
// get the VA of the next section
|
||||
uiValueA += sizeof(IMAGE_SECTION_HEADER);
|
||||
}
|
||||
|
||||
// We must flush the instruction cache to avoid stale code being used which was updated by our relocation processing.
|
||||
|
||||
// We must flush the instruction cache to avoid stale code being used
|
||||
pNtFlushInstructionCache((HANDLE)-1, NULL, 0);
|
||||
|
||||
///
|
||||
// STEP 7: execute TLS callbacks
|
||||
// STEP 8: execute TLS callbacks
|
||||
///
|
||||
|
||||
// uiValueB = the address of the TLS directory
|
||||
uiValueB = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS];
|
||||
|
||||
// check if their are any TLS callbacks required
|
||||
if (((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress)
|
||||
baseOffset = (ULONGLONG)(baseAddress - ntHeaders->OptionalHeader.ImageBase);
|
||||
dataDir = &ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS];
|
||||
|
||||
if (dataDir->Size)
|
||||
{
|
||||
// uiValueC is the TLS directory
|
||||
uiValueC = (uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress);
|
||||
PIMAGE_TLS_DIRECTORY test = (PIMAGE_TLS_DIRECTORY)uiValueC;
|
||||
|
||||
// uiValueD is the first callback entry
|
||||
uiValueD = (PIMAGE_TLS_CALLBACK *)((PIMAGE_TLS_DIRECTORY)uiValueC)->AddressOfCallBacks;
|
||||
PIMAGE_TLS_CALLBACK * test2 = (PIMAGE_TLS_CALLBACK *)uiValueD;
|
||||
|
||||
if (uiValueD) {
|
||||
while (*(PIMAGE_TLS_CALLBACK *)uiValueD) {
|
||||
(*(PIMAGE_TLS_CALLBACK *)uiValueD)((LPVOID)uiBaseAddress, DLL_PROCESS_ATTACH, NULL);
|
||||
(PIMAGE_TLS_CALLBACK *)uiValueD++;
|
||||
}
|
||||
tlsDir = RVA(PIMAGE_TLS_DIRECTORY, baseAddress, dataDir->VirtualAddress);
|
||||
callback = RVA(PIMAGE_TLS_CALLBACK *, baseAddress, tlsDir->AddressOfCallBacks);
|
||||
|
||||
for (; callback; callback++) {
|
||||
(*callback)((LPVOID)baseAddress, DLL_PROCESS_ATTACH, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
// STEP 8: call our images entry point
|
||||
// STEP 9: call our images entry point
|
||||
///
|
||||
|
||||
// uiValueA = the VA of our newly loaded DLL/EXE's entry point
|
||||
uiValueA = (uiBaseAddress + ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.AddressOfEntryPoint);
|
||||
|
||||
// call our respective entry point, fudging our hInstance value
|
||||
// if we are injecting a DLL via LoadRemoteLibraryR we call DllMain and pass in our parameter (via the DllMain lpReserved parameter)
|
||||
|
||||
((DLLMAIN)uiValueA)((HINSTANCE)uiBaseAddress, DLL_PROCESS_ATTACH, (LPVOID)1);
|
||||
dllMain = RVA(DLLMAIN, baseAddress, ntHeaders->OptionalHeader.AddressOfEntryPoint);
|
||||
dllMain((HINSTANCE)baseAddress, DLL_PROCESS_ATTACH, (LPVOID)1);
|
||||
|
||||
///
|
||||
// STEP 9: call our exported function
|
||||
// STEP 10: call our exported function
|
||||
///
|
||||
|
||||
if (dwFunctionHash) {
|
||||
|
||||
do
|
||||
{
|
||||
directory = &((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
|
||||
if (directory->Size == 0)
|
||||
dataDir = &ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
|
||||
if (!dataDir->Size)
|
||||
break;
|
||||
|
||||
exports = (PIMAGE_EXPORT_DIRECTORY)(uiBaseAddress + directory->VirtualAddress);
|
||||
if (exports->NumberOfNames == 0 || exports->NumberOfFunctions == 0)
|
||||
exportDir = (PIMAGE_EXPORT_DIRECTORY)(baseAddress + dataDir->VirtualAddress);
|
||||
if (!exportDir->NumberOfNames || !exportDir->NumberOfFunctions)
|
||||
break;
|
||||
|
||||
// search function name in list of exported names
|
||||
idx = -1;
|
||||
nameRef = (DWORD *)(uiBaseAddress + exports->AddressOfNames);
|
||||
ordinal = (WORD *)(uiBaseAddress + exports->AddressOfNameOrdinals);
|
||||
for (nameSearchIndex = 0; nameSearchIndex < exports->NumberOfNames; nameSearchIndex++, nameRef++, ordinal++) {
|
||||
expName = RVA(PDWORD, baseAddress, exportDir->AddressOfNames);
|
||||
expOrdinal = RVA(PWORD, baseAddress, exportDir->AddressOfNameOrdinals);
|
||||
|
||||
pTempChar = (char *)(uiBaseAddress + (*nameRef));
|
||||
dwCalculatedFunctionHash = 0;
|
||||
for (i = 0; i < exportDir->NumberOfNames; i++, expName++, expOrdinal++) {
|
||||
|
||||
do
|
||||
expNameStr = RVA(LPCSTR, baseAddress, *expName);
|
||||
funcHash = 0;
|
||||
|
||||
if (!expNameStr)
|
||||
break;
|
||||
|
||||
for (; *expNameStr; expNameStr++) {
|
||||
funcHash += *expNameStr;
|
||||
funcHash = ROTR32(funcHash, 13);
|
||||
|
||||
}
|
||||
|
||||
if (dwFunctionHash == funcHash && expOrdinal)
|
||||
{
|
||||
dwCalculatedFunctionHash = ROTR32(dwCalculatedFunctionHash, 13);
|
||||
dwCalculatedFunctionHash += *pTempChar;
|
||||
pTempChar++;
|
||||
} while (*(pTempChar - 1) != 0);
|
||||
|
||||
if (dwFunctionHash == dwCalculatedFunctionHash)
|
||||
{
|
||||
idx = *ordinal;
|
||||
exportFunc = RVA(EXPORTFUNC, baseAddress, *(PDWORD)(baseAddress + exportDir->AddressOfFunctions + (*expOrdinal * 4)));
|
||||
exportFunc(lpUserData, nUserdataLen);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (idx == -1)
|
||||
break;
|
||||
|
||||
// AddressOfFunctions contains the RVAs to the "real" functions
|
||||
f = (EXPORTFUNC)(uiBaseAddress + (*(DWORD *)(uiBaseAddress + exports->AddressOfFunctions + (idx * 4))));
|
||||
if (!f(lpUserData, nUserdataLen))
|
||||
break;
|
||||
|
||||
dwExitCode = 0;
|
||||
} while (0);
|
||||
}
|
||||
|
||||
if (flags & SRDI_CLEARMEMORY) {
|
||||
uiValueA = pVirtualFree((LPVOID)uiLibraryAddress, 0, 0x8000);
|
||||
|
||||
if (!uiValueA)
|
||||
pLocalFree((LPVOID)uiLibraryAddress);
|
||||
if (flags & SRDI_CLEARMEMORY && pVirtualFree && pLocalFree) {
|
||||
if (!pVirtualFree((LPVOID)dllData, 0, 0x8000))
|
||||
pLocalFree((LPVOID)dllData);
|
||||
}
|
||||
|
||||
return uiBaseAddress; //Atempt to return a handle to the module
|
||||
|
||||
// Atempt to return a handle to the module
|
||||
return baseAddress;
|
||||
}
|
||||
Reference in New Issue
Block a user