1. 程式人生 > >關於遠程線程的調用

關於遠程線程的調用

obj mod ini ren std dll文件 計算器 first ram

CreateRemoteThread 這個函數可以用於遠程註入,無DLL的註入,是一個功能非常強大的函數,下面是它的原型:

HANDLE WINAPI CreateRemoteThread(
	_In_  HANDLE                 hProcess,
	_In_  LPSECURITY_ATTRIBUTES  lpThreadAttributes,
	_In_  SIZE_T                 dwStackSize,
	_In_  LPTHREAD_START_ROUTINE lpStartAddress,
	_In_  LPVOID                 lpParameter,
	_In_  DWORD                  dwCreationFlags,
	_Out_ LPDWORD                lpThreadId
	);

  

參數都比較好理解,但是用法卻有一些難度,下面通過一個代碼分析:

做一個簡單動態庫:

#include "stdafx.h"

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
	{
		MessageBox(0, L"123", L"456", 0);
		break;
	}
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
	{
		MessageBox(0, L"xiezai", L"卸載", 0);
		break;
	}
		
	}
	return TRUE;
}

  

裏面在進程加載和卸載的時候分別彈框。

然後寫調用程序:

#include "stdafx.h"
#include <windows.h>
#include <TlHelp32.h>

BOOL WINAPI LoadDll(DWORD ProcessId, char* DllFullPathName);
BOOL WINAPI FreeDll(DWORD ProcessId, char* DllFullPathName);

int main()
{
	// DLL文件全路徑名.
	char DllFullPathName[MAX_PATH] = { 0 };

	char CurrentPath[MAX_PATH] = { 0 };
	GetCurrentDirectoryA(MAX_PATH, CurrentPath);

	strcat(DllFullPathName, CurrentPath);
	strcat(DllFullPathName, "\\Hide.dll");
	


	DWORD ProcessId = 0;
	HWND hWnd = FindWindow(L"notepad",NULL);
	if (!hWnd) 
	{
		printf("Can‘t find the file!\n");
		return 0;
	}

	// 獲得目標進程的進程號pid.
	GetWindowThreadProcessId(hWnd, &ProcessId);
	
	LoadDll(ProcessId, DllFullPathName);
	FreeDll(ProcessId, DllFullPathName);
}

BOOL WINAPI LoadDll(DWORD ProcessId, char* DllFullPathName)
{
	

	HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessId);
	if (hProcess == NULL)
	{
		return 0;
	}

	int DllLength = strlen(DllFullPathName) + sizeof(char);

	PVOID DllAddress = VirtualAllocEx(hProcess,
		NULL,
		DllLength,
		MEM_COMMIT,
		PAGE_READWRITE);
	if (DllLength == NULL)
	{
		CloseHandle(hProcess);
		return 0;
	}

	SIZE_T WriteNum = 0;
	BOOL v1 = WriteProcessMemory(hProcess, DllAddress, DllFullPathName, DllLength, &WriteNum);


	//好多人先寫這樣,到下面強制類型轉換,結果錯誤
	//FARPROC FunAddr = GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryA");

	PTHREAD_START_ROUTINE FunAddress = (PTHREAD_START_ROUTINE)
		GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryA");

	HANDLE hThread = CreateRemoteThread(hProcess,
		NULL,
		0,
		FunAddress,
		DllAddress,
		0,
		NULL);
	int a = GetLastError();
	WaitForSingleObject(hThread, INFINITE);

	CloseHandle(hThread);
	CloseHandle(hProcess);
}

BOOL WINAPI FreeDll(DWORD ProcessId, char* DllFullPathName)
{
	BOOL   Result = FALSE;
	HANDLE hProcess = NULL;
	HANDLE hThread = NULL;
	HANDLE Snapshot = NULL;
	MODULEENTRY32 hMod = { sizeof(hMod) };

	__try
	{
		// 打開進程. 
		hProcess = OpenProcess(
			PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION,
			FALSE,
			ProcessId
			);

		if (hProcess == NULL)
			__leave;


		// 取得FreeLibrary函數在Kernel32.dll中的地址. 
		PTHREAD_START_ROUTINE pfnThread =
			(PTHREAD_START_ROUTINE)GetProcAddress(
				GetModuleHandle(L"Kernel32.dll"), "FreeLibrary");

		if (pfnThread == NULL)
			__leave;

		// 取得指定進程的所有模塊映象. 
		Snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, ProcessId);
		if (Snapshot == NULL)
			__leave;

		// 取得所有模塊列表中的指定的模塊. 
		BOOL bMoreMods = Module32First(Snapshot, &hMod);
		if (bMoreMods == FALSE)
			__leave;

		// 循環取得想要的模塊. 
		for (; bMoreMods; bMoreMods = Module32Next(Snapshot, &hMod))
		{
			if ((wcscmp(hMod.szExePath, (WCHAR*)DllFullPathName) == 0) ||
				(wcscmp(hMod.szModule, (WCHAR*)DllFullPathName) == 0)) {
				break;
			}
		}

		hThread = CreateRemoteThread(hProcess,
			NULL,
			0,
			pfnThread,
			hMod.modBaseAddr,
			0,
			NULL);
		if (hThread == NULL)
			__leave;

		// 等待遠程線程終止.
		WaitForSingleObject(hThread, INFINITE);

		Result = TRUE;

	}
	__finally
	{
		// 關閉句柄. 
		if (hThread != NULL)
			CloseHandle(hThread);

		if (Snapshot != NULL)
			CloseHandle(Snapshot);

		if (hProcess != NULL)
			CloseHandle(hProcess);
	}

	return Result;
}

  在主函數中分別調用了一下。win10下測試成功。

有三個需要註意的問題:

一是如果打開的是記事本,一定要分清楚32位和64位兩個是不同的,64位在System32目錄下,32位在SystemWow64目錄下,而我們平時打開的是64位的,編譯的程序卻是x86,不匹配導致無法顯示。補充說一下,win10下的計算器也是兩個目錄下各一個,但是用任務管理器查看的時候,發現都是64位,沒有32位的,不知道怎麽回事,我第一次註入計算器,結果失敗了好長時間。

二是CreateRemoteThread的第四參數本來直接定義函數指針,最後強制類型轉換,結果一直失敗,調用,錯誤顯示是拒絕訪問,後來改為直接定義PTHREAD_START_ROUTINE,就OK了。

三是卸載的MessageBox框彈了好多次,不知道怎麽解決,還希望大神指點。

關於遠程線程的調用