最近的项目涉及了软件破解方面的知识,记录一下。
将dll注入另一个进程。
// Inject.cpp : Defines the exported functions for the DLL application. // #include "stdafx.h" #include <TlHelp32.h> #include <Psapi.h> #include <tchar.h> // LoadLibrary的不同版本 #if defined _UNICODE #define _LoadLibrary "LoadLibraryW" //_UNICODE #else #define _LoadLibrary "LoadLibraryA" //_MBCS #endif // 根据进程名获取PID DWORD GetPID(LPTSTR lpProcess) { HANDLE hProcSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); // 获取进程快照句柄 PROCESSENTRY32 pe32; pe32.dwSize = sizeof(PROCESSENTRY32); BOOL flag = Process32First(hProcSnap, &pe32); // 获取列表的第一个进程 while(flag) { if(!_tcsicmp(pe32.szExeFile, lpProcess)) { CloseHandle(hProcSnap); return pe32.th32ProcessID; //pid } flag=Process32Next(hProcSnap, &pe32); //获取下一个进程 } CloseHandle(hProcSnap); return 0; } // 获取适当的Privilege // hProcess 当前进程的handle // Privilege 需要的Privilege // 成功返回TRUE,失败返回FALSE BOOL AdjustProcessPrivilege(HANDLE hProcess, TCHAR *Privilege) { HANDLE hToken=NULL; OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken); //打开进程令牌环 if(NULL==hToken) return FALSE; LUID luid; if(!LookupPrivilegeValue(NULL, Privilege, &luid)) // 获得进程本地唯一ID { CloseHandle(hToken); return FALSE; } TOKEN_PRIVILEGES token_privileges; token_privileges.PrivilegeCount =1; token_privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; token_privileges.Privileges[0].Luid = luid; //调整进程权限 if(!AdjustTokenPrivileges(hToken, FALSE, &token_privileges, NULL, NULL, NULL)) { CloseHandle(hToken); return FALSE; } CloseHandle(hToken); return TRUE; } // 在进程中查找dll HMODULE CheckProcessModule(LPTSTR lpRemoteProcess, LPTSTR lpInjectDll) { DWORD nRemotePID = GetPID(lpRemoteProcess); HANDLE hRemoteProcess = OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, FALSE, nRemotePID); HMODULE hMods[1024]; DWORD cbNeeded = 0; // Get a handle to the process. if( EnumProcessModules(hRemoteProcess, hMods, sizeof(hMods), &cbNeeded)) { for (UINT i=0; i<(cbNeeded/sizeof(HMODULE)); i++) { TCHAR szModName[MAX_PATH]; // Get the full path to the module's file. if (GetModuleFileNameEx(hRemoteProcess, hMods[i], szModName, sizeof(szModName)/sizeof(TCHAR))) { if (!_tcsicmp(lpInjectDll, szModName)) { CloseHandle(hRemoteProcess); return hMods[i]; } } } } CloseHandle(hRemoteProcess); return NULL; } BOOL InjectDll(LPTSTR lpRemoteProcess, LPTSTR lpInjectDll, BOOL bInject) { // 获取SeDebugPrivilege权限 if(FALSE == AdjustProcessPrivilege(GetCurrentProcess(), _T("SeDebugPrivilege"))) return FALSE; // 函数准备 LPTHREAD_START_ROUTINE pfnThread = NULL; HINSTANCE hMod = GetModuleHandle(_T("kernel32.dll")); if (bInject) pfnThread = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod,_LoadLibrary); // LoadLibrary注入 else pfnThread = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod,"FreeLibrary"); // FreeLibrary卸载 if(NULL == pfnThread) return FALSE; __try { // 获取目标进程ID DWORD nRemotePID = GetPID(lpRemoteProcess); // 打开目标进程 HANDLE hRemoteProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, nRemotePID); if(hRemoteProcess == NULL) { return FALSE; } if (bInject) //注入 { // 在远端进程中分配内存 LPVOID ModName = VirtualAllocEx(hRemoteProcess, NULL, (_tcslen(lpInjectDll)+1)*sizeof(TCHAR), MEM_COMMIT, PAGE_READWRITE); if(!ModName) __leave; // 在远端进程中写入dll的文件名 if(0 == WriteProcessMemory(hRemoteProcess, ModName, lpInjectDll, (_tcslen(lpInjectDll)+1)*sizeof(TCHAR), NULL)) __leave; // 创建远程线程 HANDLE hRemoteThread = CreateRemoteThread(hRemoteProcess, NULL, 0, pfnThread, ModName, 0, NULL); if(NULL == hRemoteThread) __leave; WaitForSingleObject(hRemoteThread,INFINITE); VirtualFreeEx(hRemoteProcess, ModName, 0, MEM_RELEASE); CloseHandle(hRemoteThread); } else //卸载 { // 在进程中查找需要卸载的dll HMODULE hTarget = CheckProcessModule(lpRemoteProcess, lpInjectDll); // 创建远程线程 HANDLE hRemoteThread = CreateRemoteThread(hRemoteProcess, NULL, 0, pfnThread, hTarget, 0, NULL); if(NULL == hRemoteThread) __leave; WaitForSingleObject(hRemoteThread,INFINITE); CloseHandle(hRemoteThread); } CloseHandle(hRemoteProcess); return TRUE; } __finally { } return FALSE; }
以上已经将dll成功注入到目标进程,但是怎样让注入的dll执行?可以在dll加载时,执行一段代码。
BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: Fun(); // 需要执行的代码 break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; }