天天看點

挂起線程注入

     首先,通過獲得目标程序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;
	}
}
           

繼續閱讀