Huge re-factor of the base RDI code

This commit is contained in:
Nick Landers
2019-09-25 22:08:23 -04:00
parent 7e73a4285b
commit d939bae226
8 changed files with 264 additions and 420 deletions
+2 -2
View File
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -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
View File
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
View File
@@ -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;
}
+2 -2
View File
@@ -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 -1
View File
@@ -1,2 +1,2 @@
ExecutePayload
LoadDLL
GetProcAddressWithHash