关于远程线程的调用
Posted 13572980562
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于远程线程的调用相关的知识,希望对你有一定的参考价值。
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框弹了好多次,不知道怎么解决,还希望大神指点。
以上是关于关于远程线程的调用的主要内容,如果未能解决你的问题,请参考以下文章