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:
+2
-2
File diff suppressed because one or more lines are too long
@@ -38,7 +38,7 @@ DWORD HashFunctionName(LPSTR name) {
|
||||
return hash;
|
||||
}
|
||||
|
||||
extern "C" ULONG_PTR ExecutePayload(ULONG_PTR uiLibraryAddress, DWORD dwFunctionHash, LPVOID lpUserData, DWORD nUserdataLen, DWORD flags);
|
||||
extern "C" ULONG_PTR LoadDLL(ULONG_PTR uiLibraryAddress, DWORD dwFunctionHash, LPVOID lpUserData, DWORD nUserdataLen, DWORD flags);
|
||||
|
||||
int main()
|
||||
{
|
||||
@@ -60,7 +60,7 @@ int main()
|
||||
return 1;
|
||||
}
|
||||
|
||||
ExecutePayload((ULONG_PTR)buffer, HashFunctionName("SayHello"), NULL, 0, 0x0);
|
||||
LoadDLL((ULONG_PTR)buffer, HashFunctionName("SayHello"), NULL, 0, 0x1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+3
-3
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+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;
|
||||
}
|
||||
@@ -191,7 +191,7 @@
|
||||
<FunctionOrder>function_link_order.txt</FunctionOrder>
|
||||
<IgnoreEmbeddedIDL />
|
||||
<DataExecutionPrevention />
|
||||
<EntryPointSymbol>ExecutePayload</EntryPointSymbol>
|
||||
<EntryPointSymbol>LoadDLL</EntryPointSymbol>
|
||||
<LinkErrorReporting />
|
||||
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||
@@ -711,7 +711,7 @@
|
||||
</IgnoreEmbeddedIDL>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<EntryPointSymbol>ExecutePayload</EntryPointSymbol>
|
||||
<EntryPointSymbol>LoadDLL</EntryPointSymbol>
|
||||
<LinkErrorReporting>
|
||||
</LinkErrorReporting>
|
||||
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
ExecutePayload
|
||||
LoadDLL
|
||||
GetProcAddressWithHash
|
||||
Reference in New Issue
Block a user