赞
踩
网上确实有关于DLL注入的过程,但是很多写的都不全,或者内容有点老旧。
// dllmain.cpp : 定义 DLL 应用程序的入口点。 #include "pch.h" #include "windows.h" #include <iostream> #include <fstream> using namespace std; BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: { // 当DLL被进程 <<第一次>> 调用时,导致DllMain函数被调用, // 同时ul_reason_for_call的值为DLL_PROCESS_ATTACH, // 如果同一个进程后来再次调用此DLL时,操作系统只会增加DLL的使用次数, // 不会再用DLL_PROCESS_ATTACH调用DLL的DllMain函数。 // 获取窗口对象 HWND hwnd = GetActiveWindow(); MessageBox(hwnd, L"DLL已进入目标进程。", L"信息", MB_ICONINFORMATION); } } return TRUE; }
这里就很好办了
创建MFC 应用,注意,如果没有的话,点击【工具】-【获取工具和功能】
MFC 应用程序的使用方法这里不详细说明了。
建立好MFC应用程序后,打开资源文件
在注入之前,你需要获得被注入程序的相关信息。通过SPY++获取(VS的内置工具)
拖拽【查找程序窗口工具】到记事本窗口窗顶
自动显示相关的内容
这里面的信息我们接下来要用到
以下是注入程序的内容(写在与Button绑定的事件函数中)
// m_StrDLLPath 为DLL文件的绝对路径,例如CString m_StrDLLPath(L"D:\\桌面\\testDLL.DLL") if (m_StrDLLPath.IsEmpty()) { MessageBox(_T("请选择DLL模块")); return; } // :: 代表全局查找,后面的内容可以通过SPY++获取 // 【参数1】类 // 【参数2】标题 HWND hwnd = ::FindWindow(L"Notepad++", L"D:\\桌面\\新建文本文档 (2).txt - Notepad++"); if (hwnd == NULL) { MessageBox(L"没有找到"); return; } // 获取窗口所在的PID DWORD dwPID = 0; GetWindowThreadProcessId(hwnd, &dwPID); if (dwPID == 0) { MessageBox(L"获取PID失败"); return; } // 通过PID获取进程的句柄 // 获取句柄后,可以完全控制进程 HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID); if (hProcess == NULL) { MessageBox(L"进程的句柄获取失败"); return; } // TerminateProcess(hProcess, 0);//关闭句柄对象 // 实现注入 // 1.首先要提升权限,打开进程的访问令牌 // 【参数1】当前程序 // 【参数2】权限,可添加的权限|可查询的权限 HANDLE hToken; if (FALSE == OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { // 权限修改失败 MessageBox(L"权限修改失败"); return; } //2.查看与进程相关的特权信息 LUID luid; if (FALSE == LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) { // 特权信息查询失败 MessageBox(L"特权信息查询失败"); return; }; //3.调节进程的访问令牌的特权属性 // 这几行代码固定不变 TOKEN_PRIVILEGES tkp; tkp.PrivilegeCount = 1; tkp.Privileges[0].Luid = luid; tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; // 打开特权 // 【参数1】访问令牌 // 【参数2】是否禁用特权 // 【参数3】新特权所占的字节数 // 【参数4】原来的特权是否需要保存 // 【参数5】原特权的长度 if (FALSE == AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL)) { // 提升特权失败 MessageBox(L"提升特权失败"); return; }; //在远程进程中申请内存空间 // 【参数1】程序的句柄对象 // 【参数2】申请的内存地址,由系统分配,所以为NULL // 【参数3】申请的内存长度 // 【参数4】调用物理存储器 // 【参数5】这块内存可读可写,可执行 // 【返回】申请到的地址 LPVOID lpAddr = VirtualAllocEx(hProcess, NULL, m_StrDLLPath.GetLength() * 2+2,MEM_COMMIT,PAGE_EXECUTE_READWRITE); if (lpAddr == NULL) { // 在远程进程中申请内存失败 MessageBox(L"在远程进程中申请内存失败"); return; } // 把DLL路径写入到远程进程中 // 强行修改程序的内存 // 【参数1】程序的句柄 // 【参数2】申请到的内存首地址 // 【参数3】写入的内容 // 【参数4】要写入的字节数 // 【参数5】 if (FALSE == WriteProcessMemory(hProcess, lpAddr, m_StrDLLPath, m_StrDLLPath.GetLength() * 2, NULL)) { // 在远程进程中写入数据失败 MessageBox(L"在远程进程中写入数据失败"); return; }; // 调用Kernel32.dll中的LoadLibraryW方法用以加载DLL文件 PTHREAD_START_ROUTINE pfnStartAssr = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(L"Kernel32.dll"), "LoadLibraryW"); // 在远程进程中开辟线程 // 【参数1】远程线程的句柄 // 【参数2】线程属性。NULL表示使用默认属性 // 【参数3】堆栈大小。0代表默认 // 【参数4】加载DLL文件的对象 // 【参数5】加载文件的路径 // 【参数6】延迟时间。0代表立即启动 // 【参数7】线程ID。为NULL就行了 HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, pfnStartAssr, lpAddr, 0, NULL); if (hThread == NULL) { // 创建远程线程失败 MessageBox(L"创建远程线程失败"); return; } MessageBox(L"注入成功");
#include <windows.h> #include <iostream> #include <Tlhelp32.h> #include <stdio.h> using namespace std; /// <summary> /// 根据进程名称获取进程信息 /// </summary> /// <param name="info"></param> /// <param name="processName"></param> /// <returns></returns> BOOL getProcess32Info(PROCESSENTRY32* info, const TCHAR processName[]) { HANDLE handle; //定义CreateToolhelp32Snapshot系统快照句柄 handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);//获得系统快照句柄 //PROCESSENTRY32 结构的 dwSize 成员设置成 sizeof(PROCESSENTRY32) info->dwSize = sizeof(PROCESSENTRY32); //调用一次 Process32First 函数,从快照中获取进程列表 Process32First(handle, info); //重复调用 Process32Next,直到函数返回 FALSE 为止 while (Process32Next(handle, info) != FALSE) { if (wcscmp(processName, info->szExeFile) == 0) { return TRUE; } } return FALSE; } /// <summary> /// 注入DLL文件 /// </summary> /// <param name="DllFullPath">DLL文件的全路径</param> /// <param name="dwRemoteProcessId">要注入的程序的PID</param> /// <returns></returns> BOOL InjectDLL(const wchar_t* DllFullPath, const DWORD dwRemoteProcessId) { // 计算路径的字节数 int pathSize = (wcslen(DllFullPath) + 1) * sizeof(wchar_t); // 获取句柄后,可以完全控制进程 HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwRemoteProcessId); if (hProcess == NULL) { cout << "获取句柄失败" << endl; return FALSE; } // TerminateProcess(hProcess, 0);//关闭句柄对象 // 实现注入 // 1.首先要提升权限,打开进程的访问令牌 // 【参数1】当前程序 // 【参数2】权限,可添加的权限|可查询的权限 HANDLE hToken; if (FALSE == OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { // 权限修改失败 cout << "权限修改失败" << endl; return FALSE; } //2.查看与进程相关的特权信息 LUID luid; if (FALSE == LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) { // 特权信息查询失败 cout << "特权信息查询失败" << endl; return FALSE; }; //3.调节进程的访问令牌的特权属性 // 这几行代码固定不变 TOKEN_PRIVILEGES tkp; tkp.PrivilegeCount = 1; tkp.Privileges[0].Luid = luid; tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; // 打开特权 // 【参数1】访问令牌 // 【参数2】是否禁用特权 // 【参数3】新特权所占的字节数 // 【参数4】原来的特权是否需要保存 // 【参数5】原特权的长度 if (FALSE == AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL)) { // 提升特权失败 cout << "提升特权失败" << endl; return FALSE; }; //在远程进程中申请内存空间 // 【参数1】程序的句柄对象 // 【参数2】申请的内存地址,由系统分配,所以为NULL // 【参数3】申请的内存长度 // 【参数4】调用物理存储器 // 【参数5】这块内存可读可写,可执行 // 【返回】申请到的地址 LPVOID lpAddr = VirtualAllocEx(hProcess, NULL, pathSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (lpAddr == NULL) { // 在远程进程中申请内存失败 cout << "在远程进程中申请内存失败" << endl; return FALSE; } // 把DLL路径写入到远程进程中 // 强行修改程序的内存 // 【参数1】程序的句柄 // 【参数2】申请到的内存首地址 // 【参数3】写入的内容 // 【参数4】要写入的字节数 // 【参数5】 if (FALSE == WriteProcessMemory(hProcess, lpAddr, DllFullPath, pathSize, NULL)) { // 在远程进程中写入数据失败 cout << "在远程进程中写入数据失败" << endl; return FALSE; }; // 调用Kernel32.dll中的LoadLibraryW方法用以加载DLL文件 PTHREAD_START_ROUTINE pfnStartAssr = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(L"Kernel32.dll"), "LoadLibraryW"); // 在远程进程中开辟线程 // 【参数1】远程线程的句柄 // 【参数2】线程属性。NULL表示使用默认属性 // 【参数3】堆栈大小。0代表默认 // 【参数4】加载DLL文件的对象 // 【参数5】加载文件的路径 // 【参数6】延迟时间。0代表立即启动 // 【参数7】线程ID。为NULL就行了 HANDLE hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, pfnStartAssr, lpAddr, 0, NULL); if (hRemoteThread == NULL) { // 创建远程线程失败 cout << "创建远程线程失败" << endl; // 释放内存 VirtualFreeEx(hProcess, lpAddr, 0, MEM_FREE); return FALSE; } cout << "注入成功" << endl; // 等待线程结束 WaitForSingleObject(hRemoteThread, -1); // 关闭线程 CloseHandle(hRemoteThread); // 释放内存 VirtualFreeEx(hProcess, lpAddr, 0, MEM_FREE); } int main() { PROCESSENTRY32 info; if (getProcess32Info(&info, L"EditPlus.exe")) { // 24 InjectDLL(L"F:\\Dll1.dll", info.th32ProcessID);//这个dll你所要注入的dll文件,这个"数字"是你想注入的进程的PID号 } else { cout << "查找失败" << endl; } return 0; }
#include <iostream> #include <windows.h> #include <Tlhelp32.h> #include <stdio.h> using namespace std; /// <summary> /// 根据进程名称获取进程信息 /// </summary> /// <param name="info"></param> /// <param name="processName"></param> /// <returns></returns> BOOL getProcess32Info(PROCESSENTRY32* info, const TCHAR processName[]) { HANDLE handle; //定义CreateToolhelp32Snapshot系统快照句柄 handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);//获得系统快照句柄 //PROCESSENTRY32 结构的 dwSize 成员设置成 sizeof(PROCESSENTRY32) info->dwSize = sizeof(PROCESSENTRY32); //调用一次 Process32First 函数,从快照中获取进程列表 Process32First(handle, info); //重复调用 Process32Next,直到函数返回 FALSE 为止 while (Process32Next(handle, info) != FALSE) { if (wcscmp(processName, info->szExeFile) == 0) { return TRUE; } } return FALSE; } BOOL ZwCreateThreadExInjectDll(DWORD dwProcessId, const wchar_t* pszDllFileName) { int pathSize = (wcslen(pszDllFileName) + 1) * sizeof(wchar_t); // 1.打开目标进程 HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, // 打开权限 FALSE, // 是否继承 dwProcessId); // 进程PID if (NULL == hProcess) { cout << L"打开目标进程失败!" << endl; return FALSE; } // 2.在目标进程中申请空间 LPVOID lpPathAddr = VirtualAllocEx( hProcess, // 目标进程句柄 0, // 指定申请地址 pathSize, // 申请空间大小 MEM_RESERVE | MEM_COMMIT, // 内存的状态 PAGE_READWRITE); // 内存属性 if (NULL == lpPathAddr) { cout << L"在目标进程中申请空间失败!" << endl; CloseHandle(hProcess); return FALSE; } // 3.在目标进程中写入Dll路径 if (FALSE == WriteProcessMemory( hProcess, // 目标进程句柄 lpPathAddr, // 目标进程地址 pszDllFileName, // 写入的缓冲区 pathSize, // 缓冲区大小 NULL)) // 实际写入大小 { cout << L"目标进程中写入Dll路径失败!" << endl; CloseHandle(hProcess); return FALSE; } //4.加载ntdll.dll HMODULE hNtdll = LoadLibraryW(L"ntdll.dll"); if (NULL == hNtdll) { cout << L"加载ntdll.dll失败!" << endl; CloseHandle(hProcess); return FALSE; } //5.获取LoadLibraryA的函数地址 //FARPROC可以自适应32位与64位 FARPROC pFuncProcAddr = GetProcAddress(GetModuleHandle(L"Kernel32.dll"), "LoadLibraryW"); if (NULL == pFuncProcAddr) { cout << L"获取LoadLibrary函数地址失败!" << endl; CloseHandle(hProcess); return FALSE; } //6.获取ZwCreateThreadEx函数地址,该函数在32位与64位下原型不同 //_WIN64用来判断编译环境 ,_WIN32用来判断是否是Windows系统 #ifdef _WIN64 typedef DWORD(WINAPI* typedef_ZwCreateThreadEx)( PHANDLE ThreadHandle, ACCESS_MASK DesiredAccess, LPVOID ObjectAttributes, HANDLE ProcessHandle, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, ULONG CreateThreadFlags, SIZE_T ZeroBits, SIZE_T StackSize, SIZE_T MaximumStackSize, LPVOID pUnkown ); #else typedef DWORD(WINAPI* typedef_ZwCreateThreadEx)( PHANDLE ThreadHandle, ACCESS_MASK DesiredAccess, LPVOID ObjectAttributes, HANDLE ProcessHandle, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, BOOL CreateSuspended, DWORD dwStackSize, DWORD dw1, DWORD dw2, LPVOID pUnkown ); #endif typedef_ZwCreateThreadEx ZwCreateThreadEx = (typedef_ZwCreateThreadEx)GetProcAddress(hNtdll, "ZwCreateThreadEx"); if (NULL == ZwCreateThreadEx) { cout << L"获取ZwCreateThreadEx函数地址失败!" << endl; CloseHandle(hProcess); return FALSE; } //7.在目标进程中创建远线程 HANDLE hRemoteThread = NULL; DWORD dwStatus = ZwCreateThreadEx(&hRemoteThread, PROCESS_ALL_ACCESS, NULL, hProcess, (LPTHREAD_START_ROUTINE)pFuncProcAddr, lpPathAddr, 0, 0, 0, 0, NULL); if (NULL == hRemoteThread) { cout << L"目标进程中创建线程失败!" << endl; CloseHandle(hProcess); return FALSE; } // 8.等待线程结束 WaitForSingleObject(hRemoteThread, -1); // 9.清理环境 VirtualFreeEx(hProcess, lpPathAddr, 0, MEM_RELEASE); CloseHandle(hRemoteThread); CloseHandle(hProcess); FreeLibrary(hNtdll); return TRUE; } const wchar_t dllPath[] = L"F:\\Dll1.dll"; int main() { PROCESSENTRY32 info; // 查找指定进程名的PID if (getProcess32Info(&info, L"EditPlus.exe")) { // 进程标识符PID。 ZwCreateThreadExInjectDll(info.th32ProcessID, dllPath); cout << "注入成功" << endl; } else { cout << "注入失败" << endl; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。