[C] 纯文本查看 复制代码
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stddef.h>
#if !defined(NTSTATUS)
typedef LONG NTSTATUS;
typedef NTSTATUS *PNTSTATUS;
#endif
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
#if defined(_M_IX86)
#define GET_PEB() (uintptr_t)__readfsdword(0x30)
#elif defined(_M_AMD64)
#define GET_PEB() (uintptr_t)__readgsqword(0x60)
#endif
struct UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
};
static struct MY_LIST_ENTRY
{
struct MY_LIST_ENTRY *Flink;
struct MY_LIST_ENTRY *Blink;
};
struct PEB_LDR_DATA
{
ULONG Length;
UCHAR Initialized;
VOID* SsHandle;
struct MY_LIST_ENTRY InLoadOrderModuleList;
struct MY_LIST_ENTRY InMemoryOrderModuleList;
struct MY_LIST_ENTRY InInitializationOrderModuleList;
VOID* EntryInProgress;
UCHAR ShutdownInProgress;
VOID* ShutdownThreadId;
};
struct PEB
{
UCHAR InheritedAddressSpace;
UCHAR ReadImageFileExecOptions;
UCHAR BeingDebugged;
UCHAR BitField;
VOID* Mutant;
VOID* ImageBaseAddress;
struct PEB_LDR_DATA* Ldr;
// 省略...
};
struct LDR_DATA_TABLE_ENTRY
{
struct MY_LIST_ENTRY InLoadOrderLinks;
struct MY_LIST_ENTRY InMemoryOrderLinks;
struct MY_LIST_ENTRY InInitializationOrderLinks;
VOID* DllBase;
VOID* EntryPoint;
ULONG SizeOfImage;
struct UNICODE_STRING FullDllName;
struct UNICODE_STRING BaseDllName;
ULONG Flags;
USHORT LoadCount;
USHORT TlsIndex;
// 省略...
};
static __forceinline int my_wcsnicmp(wchar_t *s1, wchar_t *s2, size_t n)
{
wchar_t c1 = 0, c2 = 0;
size_t i;
for(i = 0; i < n; i++)
{
c1 = s1;
c2 = s2;
if (c1 == 0) break;
if (c1 >= 'A' && c1 <= 'Z') c1 += 32;
if (c2 >= 'A' && c2 <= 'Z') c2 += 32;
if (c1 != c2) break;
}
return (c1 - c2);
}
static __forceinline int my_strcmp(const char *s1, const char *s2)
{
while (*s1 && *s1 == *s2) {
s1++; s2++;
}
return *s1 - *s2;
}
static __forceinline void* my_memcpy(void* d, const void* s, size_t n)
{
size_t i;
for (i = 0; i < n; i++) {
((char*)d) = ((char*)s);
}
return d;
}
static __forceinline int my_wcsnicmpA(wchar_t *s1, char *s2, size_t n)
{
wchar_t c1 = 0, c2 = 0;
size_t i;
for(i = 0; i < n; i++)
{
c1 = s1;
c2 = s2;
if (c1 == 0) break;
if (c1 >= 'A' && c1 <= 'Z') c1 += 32;
if (c2 >= 'A' && c2 <= 'Z') c2 += 32;
if (c1 != c2) break;
}
return (c1 - c2);
}
static void* myGetModuleHandleW(wchar_t* name)
{
struct PEB* peb = (struct PEB*)GET_PEB();
struct MY_LIST_ENTRY* head = &peb->Ldr->InLoadOrderModuleList;
struct LDR_DATA_TABLE_ENTRY* entry = (struct LDR_DATA_TABLE_ENTRY*)head->Flink;
while((struct MY_LIST_ENTRY*)entry != head)
{
if (my_wcsnicmp(entry->BaseDllName.Buffer, name, entry->BaseDllName.Length) == 0)
{
return entry->DllBase;
}
entry = (struct LDR_DATA_TABLE_ENTRY*)entry->InLoadOrderLinks.Flink;
}
return NULL;
}
static __forceinline void* myGetModuleHandleA(char* name) // 不支持扩展字符
{
struct PEB* peb = (struct PEB*)GET_PEB();
struct MY_LIST_ENTRY* head = &peb->Ldr->InLoadOrderModuleList;
struct LDR_DATA_TABLE_ENTRY* entry = (struct LDR_DATA_TABLE_ENTRY*)head->Flink;
while((struct MY_LIST_ENTRY*)entry != head)
{
if (my_wcsnicmpA(entry->BaseDllName.Buffer, name, entry->BaseDllName.Length) == 0)
{
return entry->DllBase;
}
entry = (struct LDR_DATA_TABLE_ENTRY*)entry->InLoadOrderLinks.Flink;
}
return NULL;
}
static __forceinline void* myGetProcAddress(void* base, char* name)
{
IMAGE_DOS_HEADER* dos = (PIMAGE_DOS_HEADER)base;
IMAGE_NT_HEADERS* nt = (PIMAGE_NT_HEADERS)((UINT_PTR)base + dos->e_lfanew);
IMAGE_DATA_DIRECTORY* dir = &nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
if (dir->Size > 0)
{
IMAGE_EXPORT_DIRECTORY* exportDir = (IMAGE_EXPORT_DIRECTORY*)((UINT_PTR)base + dir->VirtualAddress);
DWORD* names = (DWORD*)((UINT_PTR)base + exportDir->AddressOfNames);
DWORD* functions = (DWORD*)((UINT_PTR)base + exportDir->AddressOfFunctions);
WORD* ordinals = (WORD*)((UINT_PTR)base + exportDir->AddressOfNameOrdinals);
DWORD i;
for (i = 0; i < exportDir->NumberOfNames; i++)
{
if (my_strcmp((char*)base + names, name) == 0)
{
return (void*)((UINT_PTR)base + functions[ordinals]);
}
}
}
return NULL;
}
// 相对虚拟地址转文件偏移
static __forceinline UINT_PTR RVA2FO(UINT16 SectionNumber, IMAGE_SECTION_HEADER* SectionPtr, UINT_PTR RVA)
{
UINT16 i;
for (i = 0; i < SectionNumber; i++)
{
if (RVA >= SectionPtr.VirtualAddress && RVA <= SectionPtr.VirtualAddress + SectionPtr.SizeOfRawData)
{
return RVA - SectionPtr.VirtualAddress + SectionPtr.PointerToRawData;
}
}
return 0;
}
BOOL __stdcall RunEXE(char* pFileData, BOOL wait, char** CommandLine, char** ApplicationName) // Process Hollowing
{
const size_t OffsetOf_PEB_ImageBaseAddress = offsetof(struct PEB, ImageBaseAddress);
char str1[] = {'k', 'e', 'r', 'n', 'e', 'l', '3', '2', '.', 'd', 'l', 'l', 0};
char str2[] = {'G', 'e', 't', 'P', 'r', 'o', 'c', 'A', 'd', 'd', 'r', 'e', 's', 's', 0};
char str3[] = {'G', 'e', 't', 'S', 'y', 's', 't', 'e', 'm', 'D', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', 'A', 0};
char str4[] = {'C', 'r', 'e', 'a', 't', 'e', 'P', 'r', 'o', 'c', 'e', 's', 's', 'A', 0};
char str5[] = {'V', 'i', 'r', 't', 'u', 'a', 'l', 'A', 'l', 'l', 'o', 'c', 'E', 'x', 0};
char str6[] = {'C', 'l', 'o', 's', 'e', 'H', 'a', 'n', 'd', 'l', 'e', 0};
char str7[] = {'W', 'a', 'i', 't', 'F', 'o', 'r', 'S', 'i', 'n', 'g', 'l', 'e', 'O', 'b', 'j', 'e', 'c', 't', 0};
//char str8[] = {'G', 'e', 't', 'E', 'x', 'i', 't', 'C', 'o', 'd', 'e', 'P', 'r', 'o', 'c', 'e', 's', 's', 0};
void *kernel32 = myGetModuleHandleA(str1);
void * (WINAPI *api_GetProcAddress) (HMODULE hModule, LPCSTR lpProcName) = myGetProcAddress(kernel32, str2);
UINT (WINAPI *api_GetSystemDirectoryA) (LPSTR lpBuffer, UINT uSize) = api_GetProcAddress(kernel32, str3);
BOOL (WINAPI *api_CreateProcessA) (LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation) = api_GetProcAddress(kernel32, str4);
LPVOID (WINAPI *api_VirtualAllocEx) (HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect) = api_GetProcAddress(kernel32, str5);
BOOL (WINAPI *api_CloseHandle) (HANDLE hObject) = api_GetProcAddress(kernel32, str6);
DWORD (WINAPI *api_WaitForSingleObject) (HANDLE hHandle, DWORD dwMilliseconds) = api_GetProcAddress(kernel32, str7);
//BOOL (WINAPI *api_GetExitCodeProcess) (HANDLE hProcess, LPDWORD lpExitCode) = api_GetProcAddress(kernel32, str8);
char str9[] = {'n', 't', 'd', 'l', 'l', '.', 'd', 'l', 'l', 0};
char str10[] = {'N', 't', 'G', 'e', 't', 'C', 'o', 'n', 't', 'e', 'x', 't', 'T', 'h', 'r', 'e', 'a', 'd', 0};
char str11[] = {'N', 't', 'S', 'e', 't', 'C', 'o', 'n', 't', 'e', 'x', 't', 'T', 'h', 'r', 'e', 'a', 'd', 0};
char str12[] = {'N', 't', 'R', 'e', 's', 'u', 'm', 'e', 'T', 'h', 'r', 'e', 'a', 'd', 0};
char str13[] = {'N', 't', 'T', 'e', 'r', 'm', 'i', 'n', 'a', 't', 'e', 'P', 'r', 'o', 'c', 'e', 's', 's', 0};
char str14[] = {'N', 't', 'R', 'e', 'a', 'd', 'V', 'i', 'r', 't', 'u', 'a', 'l', 'M', 'e', 'm', 'o', 'r', 'y', 0};
char str15[] = {'N', 't', 'W', 'r', 'i', 't', 'e', 'V', 'i', 'r', 't', 'u', 'a', 'l', 'M', 'e', 'm', 'o', 'r', 'y', 0};
char str16[] = {'N', 't', 'U', 'n', 'm', 'a', 'p', 'V', 'i', 'e', 'w', 'O', 'f', 'S', 'e', 'c', 't', 'i', 'o', 'n', 0};
void *ntdll = myGetModuleHandleA(str9);
NTSTATUS (NTAPI *api_NtGetContextThread) (HANDLE, PCONTEXT) = api_GetProcAddress(ntdll, str10);
NTSTATUS (NTAPI *api_NtSetContextThread) (HANDLE, PCONTEXT) = api_GetProcAddress(ntdll, str11);
NTSTATUS (NTAPI *api_NtResumeThread) (HANDLE, PULONG) = api_GetProcAddress(ntdll, str12);
NTSTATUS (NTAPI *api_NtTerminateProcess) (HANDLE, NTSTATUS) = api_GetProcAddress(ntdll, str13);
NTSTATUS (NTAPI *api_NtReadVirtualMemory) (HANDLE, PVOID, PVOID, ULONG, PULONG) = api_GetProcAddress(ntdll, str14);
NTSTATUS (NTAPI *api_NtWriteVirtualMemory)(HANDLE, PVOID, PVOID, ULONG, PULONG) = api_GetProcAddress(ntdll, str15);
NTSTATUS (NTAPI *api_NtUnmapViewOfSection)(HANDLE, PVOID) = api_GetProcAddress(ntdll, str16);
IMAGE_DOS_HEADER* idh;
IMAGE_NT_HEADERS* inh;
STARTUPINFOA si;
PROCESS_INFORMATION pi;
char path[MAX_PATH];
char *pAppName = *ApplicationName;
idh = (IMAGE_DOS_HEADER*)pFileData;
if (idh->e_magic != IMAGE_DOS_SIGNATURE) return FALSE;
inh = (IMAGE_NT_HEADERS*)(pFileData + idh->e_lfanew);
if (inh->Signature != IMAGE_NT_SIGNATURE) return FALSE;
if (pAppName == 0 || *pAppName == 0)
{
size_t len = api_GetSystemDirectoryA(path, MAX_PATH);
{ // strcat
char str[] = {'\\', 'c', 'm', 'd', '.', 'e', 'x', 'e', 0};
char* destination = path + len;
char* source = str;
//while (*destination) ++destination; //strlen
while ((*destination++ = *source++)); //strcpy
}
pAppName = path;
}
si.cb = sizeof(si);
si.lpReserved = NULL;
si.lpDesktop = NULL;
si.lpTitle = NULL;
si.dwX = 0;
si.dwY = 0;
si.dwXSize = 0;
si.dwYSize = 0;
si.dwXCountChars = 0;
si.dwYCountChars = 0;
si.dwFillAttribute = 0;
si.dwFlags = 0;
si.wShowWindow = 0;
si.cbReserved2 = 0;
si.lpReserved2 = NULL;
si.hStdInput = NULL;
si.hStdOutput = NULL;
si.hStdError = NULL;
if (!api_CreateProcessA(pAppName, *CommandLine, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi))
{
// 创建进程 失败
return FALSE;
}
do
{
IMAGE_SECTION_HEADER* ish;
CONTEXT context;
UINT_PTR FakeImageBase;
UINT_PTR OldImageBase;
UINT_PTR NewImageBase;
UINT_PTR NewImageSize;
UINT_PTR peb;
UINT16 sectionsNumber;
UINT16 sectionsIndex;
ULONG PreviousSuspendCount;
context.ContextFlags = CONTEXT_FULL;
if (api_NtGetContextThread(pi.hThread, &context) != STATUS_SUCCESS)
{
// 获取线程上下文 失败
break;
}
#ifndef _WIN64
peb = context.Ebx;
#else
peb = context.Rdx;
#endif
if (api_NtReadVirtualMemory(pi.hProcess, (PVOID)(peb + OffsetOf_PEB_ImageBaseAddress), &FakeImageBase, sizeof(FakeImageBase), NULL) != STATUS_SUCCESS) //PEB.ImageBase
{
// 读进程内存 失败
break;
}
OldImageBase = inh->OptionalHeader.ImageBase;
NewImageSize = inh->OptionalHeader.SizeOfImage;
if (OldImageBase == FakeImageBase) // 冲突
{
if ((inh->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) != 0)
{
if (api_NtUnmapViewOfSection(pi.hProcess, (PVOID)FakeImageBase) != STATUS_SUCCESS)
{
// 此文件没有重定位信息,不支持动态基址,并且固定基址不可用!
break;
}
}
}
NewImageBase = (UINT_PTR)api_VirtualAllocEx(pi.hProcess, (PVOID)OldImageBase, NewImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (!NewImageBase) // 不能使用固定基址
{
// 尝试使用动态基址
NewImageBase = (UINT_PTR)api_VirtualAllocEx(pi.hProcess, NULL, NewImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (!NewImageBase)
{
// 调用 VirtualAllocEx 函数失败!
break;
}
// 动态基址在 Windows 10 不需要自己重定位,但以防万一和为了兼容还是自己重定位。
{ // 修改PE文件的重定位地址
IMAGE_DATA_DIRECTORY* pDir = &inh->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
UINT_PTR size = pDir->Size;
ish = (IMAGE_SECTION_HEADER*)((UINT_PTR)inh + offsetof(IMAGE_NT_HEADERS, OptionalHeader) + inh->FileHeader.SizeOfOptionalHeader);
sectionsNumber = inh->FileHeader.NumberOfSections;
if (size > 0)
{
IMAGE_BASE_RELOCATION* pBaseRelocation = (IMAGE_BASE_RELOCATION*)((UINT_PTR)idh + RVA2FO(sectionsNumber, ish, pDir->VirtualAddress));
INT_PTR deltaBase = NewImageBase - OldImageBase;
UINT_PTR end_ptr = (UINT_PTR)pBaseRelocation + size;
while (end_ptr > (UINT_PTR)pBaseRelocation)
{
UINT_PTR address = pBaseRelocation->VirtualAddress;
size_t size = pBaseRelocation->SizeOfBlock;
WORD* blockPtr = (WORD*)((UINT_PTR)pBaseRelocation + sizeof(IMAGE_BASE_RELOCATION));
UINT_PTR blockEndPtr = (UINT_PTR)pBaseRelocation + pBaseRelocation->SizeOfBlock;
for (; blockEndPtr > (UINT_PTR)blockPtr; blockPtr++)
{
WORD type = *blockPtr >> 0x0C;
WORD offset = *blockPtr & 0x0FFF;
#ifndef _WIN64
if (type == IMAGE_REL_BASED_HIGHLOW)
{
UINT_PTR p = (UINT_PTR)idh + RVA2FO(sectionsNumber, ish, address + offset);
*(UINT32*)(p) += deltaBase;
}
#else
if (type == IMAGE_REL_BASED_DIR64)
{
UINT_PTR p = (UINT_PTR)idh + RVA2FO(sectionsNumber, ish, address + offset);
*(UINT64*)(p) += deltaBase;
}
#endif
}
pBaseRelocation = (IMAGE_BASE_RELOCATION*)blockEndPtr;
}
}
inh->OptionalHeader.ImageBase = NewImageBase;
}
}
if (api_NtWriteVirtualMemory(pi.hProcess, (PVOID)(peb + OffsetOf_PEB_ImageBaseAddress), &NewImageBase, sizeof(NewImageBase), NULL) != STATUS_SUCCESS)
{
// 写进程内存 失败
break;
}
#ifndef _WIN64
context.Eax = NewImageBase + inh->OptionalHeader.AddressOfEntryPoint; //入口点
#else
context.Rcx = NewImageBase + inh->OptionalHeader.AddressOfEntryPoint; //入口点
#endif
if (api_NtSetContextThread(pi.hThread, &context) != STATUS_SUCCESS)
{
break;
}
if (api_NtWriteVirtualMemory(pi.hProcess, (PVOID)NewImageBase, idh, inh->OptionalHeader.SizeOfHeaders, NULL) != STATUS_SUCCESS)
{
break;
}
ish = IMAGE_FIRST_SECTION(inh);
sectionsNumber = inh->FileHeader.NumberOfSections;
for (sectionsIndex = 0; sectionsIndex < sectionsNumber; sectionsIndex++)
{
DWORD VirtualAddress = ish[sectionsIndex].VirtualAddress;
DWORD VirtualSize = ish[sectionsIndex].Misc.VirtualSize;
DWORD PointerToRawData = ish[sectionsIndex].PointerToRawData;
DWORD SizeOfRawData = ish[sectionsIndex].SizeOfRawData;
api_NtWriteVirtualMemory(pi.hProcess, (PVOID)(NewImageBase + VirtualAddress), (PVOID)((UINT_PTR)idh + PointerToRawData), SizeOfRawData, NULL);
}
if (api_NtResumeThread(pi.hThread, &PreviousSuspendCount) != STATUS_SUCCESS)
{
break;
}
api_CloseHandle(pi.hThread);
if (wait)
{
api_WaitForSingleObject(pi.hProcess, -1);
}
api_CloseHandle(pi.hProcess);
return TRUE;
} while (FALSE);
api_NtTerminateProcess(pi.hProcess, 0);
api_CloseHandle(pi.hThread);
api_CloseHandle(pi.hProcess);
return FALSE;
}
void* __stdcall LoadDLL(char* pFileData) // Manual Mapping
{
char str1[] = {'k', 'e', 'r', 'n', 'e', 'l', '3', '2', '.', 'd', 'l', 'l', 0};
char str2[] = {'G', 'e', 't', 'P', 'r', 'o', 'c', 'A', 'd', 'd', 'r', 'e', 's', 's', 0};
char str3[] = {'L', 'o', 'a', 'd', 'L', 'i', 'b', 'r', 'a', 'r', 'y', 'A', 0};
char str4[] = {'V', 'i', 'r', 't', 'u', 'a', 'l', 'A', 'l', 'l', 'o', 'c', 0};
char str5[] = {'V', 'i', 'r', 't', 'u', 'a', 'l', 'F', 'r', 'e', 'e', 0};
void *kernel32 = myGetModuleHandleA(str1);
FARPROC (WINAPI *api_GetProcAddress)(HMODULE hModule, LPCSTR lpProcName) = myGetProcAddress(kernel32, str2);
HMODULE (WINAPI *api_LoadLibraryA) (LPCSTR lpLibFileName) = (void*)api_GetProcAddress(kernel32, str3);
LPVOID (WINAPI *api_VirtualAlloc) (LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect) = (void*)api_GetProcAddress(kernel32, str4);
BOOL (WINAPI *api_VirtualFree) (LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType) = (void*)api_GetProcAddress(kernel32, str5);
PIMAGE_DOS_HEADER dos;
PIMAGE_NT_HEADERS nt;
DWORD imageSize;
char* imageBuffer;
PIMAGE_SECTION_HEADER sections;
WORD sectionNumber;
WORD sectionIndex;
BOOL (WINAPI *ep)(HMODULE, DWORD, LPVOID);
dos = (PIMAGE_DOS_HEADER)pFileData;
if (IMAGE_DOS_SIGNATURE != dos->e_magic) return NULL;
nt = (PIMAGE_NT_HEADERS)((UINT_PTR)pFileData + dos->e_lfanew);
if (IMAGE_NT_SIGNATURE != nt->Signature) return NULL;
#ifdef _WIN64
if (IMAGE_FILE_MACHINE_AMD64 != nt->FileHeader.Machine) return NULL;
#else
if (IMAGE_FILE_MACHINE_I386 != nt->FileHeader.Machine) return NULL;
#endif
imageSize = nt->OptionalHeader.SizeOfImage;
imageBuffer = (char*)api_VirtualAlloc(NULL, imageSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (!imageBuffer) return NULL;
// Header
my_memcpy(imageBuffer, pFileData, nt->OptionalHeader.SizeOfHeaders);
// Section
sections = (PIMAGE_SECTION_HEADER)((UINT_PTR)nt + FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) + nt->FileHeader.SizeOfOptionalHeader);
sectionNumber = nt->FileHeader.NumberOfSections;
for (sectionIndex = 0; sectionIndex < sectionNumber; sectionIndex++)
{
my_memcpy(imageBuffer + sections[sectionIndex].VirtualAddress, pFileData + sections[sectionIndex].PointerToRawData, sections[sectionIndex].SizeOfRawData);
}
// BaseReloc
{
PIMAGE_DATA_DIRECTORY pDir = &nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
if (pDir->Size > 0)
{
UINT_PTR oldBase = (UINT_PTR)nt->OptionalHeader.ImageBase;
UINT_PTR newBase = (UINT_PTR)imageBuffer;
UINT_PTR deltaBase = newBase - oldBase;
PIMAGE_BASE_RELOCATION pBaseRelocation = (PIMAGE_BASE_RELOCATION)(imageBuffer + pDir->VirtualAddress);
UINT_PTR relocationEndPtr = (UINT_PTR)pBaseRelocation + pDir->Size;
while (relocationEndPtr > (UINT_PTR)pBaseRelocation)
{
UINT_PTR address = (UINT_PTR)imageBuffer + pBaseRelocation->VirtualAddress;
WORD* blockPtr = (WORD*)((UINT_PTR)pBaseRelocation + sizeof(IMAGE_BASE_RELOCATION));
UINT_PTR blockEndPtr = (UINT_PTR)pBaseRelocation + pBaseRelocation->SizeOfBlock;
while (blockEndPtr > (UINT_PTR)blockPtr)
{
WORD type = *blockPtr >> 0x0C;
WORD offset = *blockPtr & 0x0FFF;
#ifndef _WIN64
if (type == IMAGE_REL_BASED_HIGHLOW)
{
*(UINT32*)(address + offset) += deltaBase;
}
#else
if (type == IMAGE_REL_BASED_DIR64)
{
*(UINT64*)(address + offset) += deltaBase;
}
#endif
blockPtr++;
}
pBaseRelocation = (IMAGE_BASE_RELOCATION*)blockEndPtr;
}
}
}
// Import
{
PIMAGE_DATA_DIRECTORY pDir = &nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
if (pDir->Size > 0)
{
PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(imageBuffer + pDir->VirtualAddress);
for (; pImportDescriptor->Characteristics; pImportDescriptor++)
{
char* name = imageBuffer + pImportDescriptor->Name;
HMODULE hModule = api_LoadLibraryA(name);
IMAGE_THUNK_DATA* pOriginalFirstThunk;
IMAGE_THUNK_DATA* pThunkData;
if (hModule == NULL)
{
api_VirtualFree(imageBuffer, 0, MEM_RELEASE); return NULL;
}
pOriginalFirstThunk = (IMAGE_THUNK_DATA*)(imageBuffer + pImportDescriptor->OriginalFirstThunk);
pThunkData = (IMAGE_THUNK_DATA*)(imageBuffer + pImportDescriptor->FirstThunk);
while (pOriginalFirstThunk->u1.Function)
{
FARPROC address;
if (pOriginalFirstThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG)
{
UINT_PTR ordinal = IMAGE_ORDINAL(pOriginalFirstThunk->u1.Ordinal);
address = api_GetProcAddress(hModule, (LPCSTR)ordinal);
}
else
{
IMAGE_IMPORT_BY_NAME* pName = (IMAGE_IMPORT_BY_NAME*)(imageBuffer + pOriginalFirstThunk->u1.AddressOfData);
address = api_GetProcAddress(hModule, (LPCSTR)pName->Name);
}
if (address == NULL)
{
api_VirtualFree(imageBuffer, 0, MEM_RELEASE); return NULL;
}
pThunkData->u1.Function = (UINT_PTR)address;
pOriginalFirstThunk++; pThunkData++;
}
}
}
}
// ImageBase
dos = (PIMAGE_DOS_HEADER)imageBuffer;
nt = (PIMAGE_NT_HEADERS)((UINT_PTR)imageBuffer + dos->e_lfanew);
nt->OptionalHeader.ImageBase = (UINT_PTR)imageBuffer;
/*
// TLS
{
PIMAGE_DATA_DIRECTORY pDir = &nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS];
if (pDir->Size > 0)
{
PIMAGE_TLS_DIRECTORY TLS = (PIMAGE_TLS_DIRECTORY)(imageBuffer + pDir->VirtualAddress);
PIMAGE_TLS_CALLBACK* CallBacks = (PIMAGE_TLS_CALLBACK*)TLS->AddressOfCallBacks;
for (; *CallBacks; CallBacks++)
{
ep = (void*)*CallBacks;
ep((HMODULE)imageBuffer, DLL_PROCESS_ATTACH, NULL);
}
}
}
*/
// DllMain
ep = (void*)(imageBuffer + nt->OptionalHeader.AddressOfEntryPoint);
ep((HMODULE)imageBuffer, DLL_PROCESS_ATTACH, NULL);
return imageBuffer;
}
BOOL __stdcall FreeDll(void* h)
{
char str1[] = {'k', 'e', 'r', 'n', 'e', 'l', '3', '2', '.', 'd', 'l', 'l', 0};
char str2[] = {'V', 'i', 'r', 't', 'u', 'a', 'l', 'F', 'r', 'e', 'e', 0};
void *kernel32 = myGetModuleHandleA(str1);
BOOL (WINAPI *api_VirtualFree)(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType) = (void*)myGetProcAddress(kernel32, str2);
PIMAGE_DOS_HEADER dos;
PIMAGE_NT_HEADERS nt;
BOOL (WINAPI *ep)(HMODULE, DWORD, LPVOID);
dos = (PIMAGE_DOS_HEADER)h;
nt = (PIMAGE_NT_HEADERS)((UINT_PTR)h + dos->e_lfanew);
ep = (void*)((UINT_PTR)h + nt->OptionalHeader.AddressOfEntryPoint);
ep((HMODULE)h, DLL_PROCESS_DETACH, NULL);
return api_VirtualFree(h, 0, MEM_RELEASE);
}
#pragma comment(linker, "/ENTRY:EntryPoint")
int EntryPoint(void* peb)
{
void *kernel32 = myGetModuleHandleW(L"kernel32.dll");
HMODULE (WINAPI *LoadLibraryW)(LPCWSTR lpLibFileName) = myGetProcAddress(kernel32, "LoadLibraryW");
void *msvcrt = LoadLibraryW(L"msvcrt.dll");
void (*printf)(const char*, ...) = myGetProcAddress(msvcrt, "printf");
// 为了提取汇编给易语言调用,注意调用约定是 stdcall、文本型是 char**
printf("LoadDLL: %p\n", LoadDLL);
printf("FreeDll: %p\n", FreeDll);
printf("RunEXE: %p\n", RunEXE);
return 0;
}