zoukankan      html  css  js  c++  java
  • 关于远程线程的调用

    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!
    ");
    		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框弹了好多次,不知道怎么解决,还希望大神指点。

  • 相关阅读:
    HTML5 跨文档消息传输
    Cordova 本地项目创建方法
    远程登录协议
    Linux mii-tool命令
    Linux ethtool命令
    Linux内核阅读相关
    C语言介绍
    Proc-fs 编程
    Linux syslog介绍
    Mpich编程
  • 原文地址:https://www.cnblogs.com/kekoukele987/p/7508036.html
Copyright © 2011-2022 走看看