在学习第一篇时,就直接折腾代码,这是我学习的方法,基础的只是简单过一遍就好了,因为根本记得不够深刻,还是用了之后,才知道真正的含义。
然后在第一篇的基础上,把卸载加进来了,同时重整理了注入的代码,更重要的是这次的消息接收,抛弃了MFC,直接用的C++写的,感觉真好
另外,在这个注入和进程的通讯上,还遇到两个问题:
第一点,对于OpenProcess 时使用的权限最好还是PROCESS_ALL_ACCESS,反正我换了台电脑,就会造成CreateRemoteThread失败
第二点,在进程的通讯上,也存在权限问题,也就是说接收方如果不做处理 ,可能收不到,在WM_INITDIALOG中使用了ChangeWindowMessageFilter(WM_COPYDATA, 1)来处理一下
还是直接贴代码,也懒得上工程,有些变量啥的可能看不全,刚入门的同学们对不住了,你们还是慢慢看
#include "stdafx.h" #include "Inject.h" //#include <iostream>; //using namespace std; //#include <windows.h>; //#include <tlhelp32.h>; //#include <tchar.h>; // 提升进程访问权限 bool enableDebugPriv() { HANDLE hToken; LUID sedebugnameValue; TOKEN_PRIVILEGES tkp; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken) ) { return false; } if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue)) { CloseHandle(hToken); return false; } tkp.PrivilegeCount = 1; tkp.Privileges[0].Luid = sedebugnameValue; tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL)) { CloseHandle(hToken); return false; } return true; } // 根据进程名称得到进程ID,如果有多个运行实例的话,返回第一个枚举到的进程的ID DWORD processNameToId(LPCTSTR lpszProcessName) { HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); PROCESSENTRY32 pe; pe.dwSize = sizeof(PROCESSENTRY32); if (!Process32First(hSnapshot, &pe)) { MessageBox(NULL, L"The frist entry of the process list has not been copyied to the buffer", L"Notice", MB_ICONINFORMATION | MB_OK ); return 0; } while (Process32Next(hSnapshot, &pe)) { if (!wcscmp(lpszProcessName, pe.szExeFile)) { return pe.th32ProcessID; } } return 0; } bool InjectDll() { enableDebugPriv(); DWORD dwProcessId = processNameToId(INJECT_PROCESS_NAME); if (dwProcessId == 0) { MessageBox(NULL, L"The target process have not been found !", L"Notice", MB_ICONINFORMATION | MB_OK ); return FALSE; } return InjectDll(INJECT_DLL_NAME, dwProcessId); } bool InjectDll(const TCHAR* ptszDllFile, DWORD dwProcessId) { // 参数无效 if (NULL == ptszDllFile || 0 == ::_tcslen(ptszDllFile)) { return false; } // 指定 Dll 文件不存在 if (-1 == _taccess(ptszDllFile, 0)) { return false; } HANDLE hProcess = NULL; HANDLE hThread = NULL; DWORD dwSize = 0; TCHAR* ptszRemoteBuf = NULL; LPTHREAD_START_ROUTINE lpThreadFun = NULL; // 获取目标进程句柄 hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId); if (NULL == hProcess) { return false; } // 在目标进程中分配内存空间 dwSize = (DWORD)::_tcslen(ptszDllFile) + 1; ptszRemoteBuf = (TCHAR*)::VirtualAllocEx(hProcess, NULL, dwSize * sizeof(TCHAR), MEM_COMMIT, PAGE_READWRITE); if (NULL == ptszRemoteBuf) { ::CloseHandle(hProcess); return false; } // 在目标进程的内存空间中写入所需参数(模块名) if (FALSE == ::WriteProcessMemory(hProcess, ptszRemoteBuf, (LPVOID)ptszDllFile, dwSize * sizeof(TCHAR), NULL)) { ::VirtualFreeEx(hProcess, ptszRemoteBuf, dwSize, MEM_DECOMMIT); ::CloseHandle(hProcess); return false; } // 从 Kernel32.dll 中获取 LoadLibrary 函数地址 #ifdef _UNICODE lpThreadFun = (PTHREAD_START_ROUTINE)::GetProcAddress(::GetModuleHandle(_T("Kernel32")), "LoadLibraryW"); #else lpThreadFun = (PTHREAD_START_ROUTINE)::GetProcAddress(::GetModuleHandle(_T("Kernel32")), "LoadLibraryA"); #endif //LPVOID pFunc = LoadLibraryA; if (NULL == lpThreadFun) { ::VirtualFreeEx(hProcess, ptszRemoteBuf, dwSize, MEM_DECOMMIT); ::CloseHandle(hProcess); return false; } // 创建远程线程调用 LoadLibrary hThread = ::CreateRemoteThread(hProcess, NULL, 0, lpThreadFun, ptszRemoteBuf, 0, NULL); if (NULL == hThread) { DWORD error = GetLastError(); ::VirtualFreeEx(hProcess, ptszRemoteBuf, dwSize, MEM_DECOMMIT); ::CloseHandle(hProcess); return false; } // 等待远程线程结束 ::WaitForSingleObject(hThread, INFINITE); // 清理 ::VirtualFreeEx(hProcess, ptszRemoteBuf, dwSize, MEM_DECOMMIT); ::CloseHandle(hThread); ::CloseHandle(hProcess); return true; } bool UnInjectDll() { enableDebugPriv(); DWORD dwProcessId = processNameToId(INJECT_PROCESS_NAME); if (dwProcessId == 0) { MessageBox(NULL, L"The target process have not been found !", L"Notice", MB_ICONINFORMATION | MB_OK ); return FALSE; } return UnInjectDll(INJECT_DLL_NAME, dwProcessId); } //----------------------------------------------------------------------------------------------------------- // 函数: UnInjectDll // 功能: 从目标进程中卸载一个指定 Dll 模块文件. // 参数: [in] const TCHAR* ptszDllFile - Dll 文件名及路径 // [in] DWORD dwProcessId - 目标进程 ID // 返回: bool - 卸载成功返回 true, 卸载失败则返回 false. // 说明: 采用远程线程注入技术实现 //----------------------------------------------------------------------------------------------------------- bool UnInjectDll(const TCHAR* ptszDllFile, DWORD dwProcessId) { // 参数无效 if (NULL == ptszDllFile || 0 == ::_tcslen(ptszDllFile)) { return false; } HANDLE hModuleSnap = INVALID_HANDLE_VALUE; HANDLE hProcess = NULL; HANDLE hThread = NULL; // 获取模块快照 hModuleSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId); if (INVALID_HANDLE_VALUE == hModuleSnap) { return false; } MODULEENTRY32 me32; memset(&me32, 0, sizeof(MODULEENTRY32)); me32.dwSize = sizeof(MODULEENTRY32); // 开始遍历 if (FALSE == ::Module32First(hModuleSnap, &me32)) { ::CloseHandle(hModuleSnap); return false; } // 遍历查找指定模块 bool isFound = false; do { isFound = (0 == ::_tcsicmp(me32.szModule, ptszDllFile) || 0 == ::_tcsicmp(me32.szExePath, ptszDllFile)); if (isFound) // 找到指定模块 { break; } } while (TRUE == ::Module32Next(hModuleSnap, &me32)); ::CloseHandle(hModuleSnap); if (false == isFound) { return false; } // 获取目标进程句柄 hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId); if (NULL == hProcess) { return false; } // 从 Kernel32.dll 中获取 FreeLibrary 函数地址 LPTHREAD_START_ROUTINE lpThreadFun = (PTHREAD_START_ROUTINE)::GetProcAddress(::GetModuleHandle(_T("Kernel32")), "FreeLibrary"); if (NULL == lpThreadFun) { ::CloseHandle(hProcess); return false; } // 创建远程线程调用 FreeLibrary hThread = ::CreateRemoteThread(hProcess, NULL, 0, lpThreadFun, me32.modBaseAddr /* 模块地址 */, 0, NULL); if (NULL == hThread) { ::CloseHandle(hProcess); return false; } // 等待远程线程结束 ::WaitForSingleObject(hThread, INFINITE); // 清理 ::CloseHandle(hThread); ::CloseHandle(hProcess); return true; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
2011-06-01 股票信息
2009-06-01 利用移动提供的网站用C#做一个免费发短信的程序(不含源码)