原创 : 星绽紫辉 转载请注明出处 http://www.cppblog.com/rawdata
我写的一个用到的WinXP下的隐藏SysListView32界面窗口子项目的C++类,它可以实现界面级的隐藏。用它可以隐藏任务管理器的进程,隐藏MMC外壳程序(如Windows服务窗口)的子项。隐藏后目标界面无明显刷新,调用方法如下: CHideProc hide;
hide.HideReset(); hide.HideScan();
hide.HideReset(); hide.HideScan();
hide.HideQuit();
http://www.cppblog.com/rawdata 那么让我来看看它是怎么样工作的:首先,声明声明一个CHideProc 类,然后调用HideReset();之后就可以传入一个进程参数,让它调用 HideScan();实现隐藏了。当要隐藏其他子项时(如:对于任务管理器,当前隐藏的是system子项,我想换成word.exe子项),只需重复调用HideReset()再调用HideScan()即可(详见后面的代码清单)。最后调用HideQuit();退出。
实现目的: 1.学习API 2.让某些重要数据安全的进程不被轻易结束(界面级) 3.了解一些内核原理
现在我大致说一下实现的过程及原理
第一步: 找目标主程序(如taskmgr.exe/mmc.exe)的PID(进程句柄 HANDLE)和窗口句柄(HWND)。通过 ToolHelp32系列函数可以很方便地找出,如果你对这些函数不了解,参见《Windows核心编程》一书。
第二步:调用AllocateMemoryEx在目标进程分配空间,然后用WriteProcessMemory写入一些数据,至于写入什么数据,先保留。然后调用CreateRemoteThread创建远程线程到目标进程,创建成功的话,我们的程序就可以调用进程隐藏类的函数了。
那么我们到底要写了一些什么东西到目标进程的地址空间呢? 首先是CreateRemoteThread的参数,因为该线程在目标的地址空间运行,所以不能直接使用本进程的任何变量和函数,否则会造成内存访问错误。既然如此,我们就在目标进程分配空间来存贮我们的变量和函数,然后就在CreateRemoteThread的回调函数中使用这些变量和函数。就像我们把自己的代码插入了目标进程让它和在我们自己的进程里运行一样。呵呵,不要用它来做坏事哦~
然后看看CreateRemoteThread的回调函数,我们要隐藏SysListView32窗口类的子项,显然只要对它发送WM_DELETEITEMW消息就可以了(当然有一些细节问题还要注意,详见后面的代码)。然而,回调函数只被设计成调用一次,那么我们怎么样才能让它持续隐藏呢?显然,不断的调用CreateRemoteThread是不切实际的。 这里,我们直接拦截目标进程的窗口消息,很简单,只需要调用SetWindowLongA(W)改变它的原来的窗口过程地址,并且要保存原来的窗口过程地址,这样才能保证调用了我们自己的函数之后能调用它本身的窗口过程。
其中,非常关键的是,有些变量在“窗口过程代码区”(我们写到目标进程代码区)中是无法使用的。虽然我们能将变量写到目标进程,但是我们却无法在NewWindowProc中对它进行定位和使用(函数就不同了,所有的系统函数都是被映射到所有的进程的相同的地址上,而我们自己的函数直接拷贝到目标进程并引用其地址即可)。要解决定位问题,我所采用的方法是直接将变量写到NewWindowProc函数入口地址的开头,当我要在NewWindowProc中引用这些变量的时候,只需要根据当前的EIP计算出NewWindowProc函数入口地址,然后根据需要读取变量,这样就能实现在目标代码区使用我们自己变量和函数的目的。
计算函数入口地址的汇编代码如下(不同的编译器/系统计算可能不同,但是都可以通过反汇编计算出来):
LRESULT __stdcall CHideProc::NewWindowProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) {
DWORD dwTest = NULL; _asm { call dummy dummy: pop ecx sub ecx,0x00000013 //得到EIP mov dwTest, ecx //得到NewWindowProc的入口地址 }
RemoteParam* pRP = (RemoteParam*)(dwTest-sizeof(RemoteParam));
}
好了,整个过程大概就是这样,下面贴出完整代码: http://www.cppblog.com/rawdata
后记:代码只能在Release版本运行,因为debug版本会有堆栈cookie检查(_chkesp),这是VC++堆栈保护机制,但这是不必要的,因为我们的代码在另外的进程中运行。(2009-4-6) 头文件:
1#pragma once 2 3 4/**//* 忽略指针强制转换的警告 */ 5#pragma warning(disable:4312) 6#pragma warning(disable:4311) 7 8 9/**//* STL 链表 */ 10#include <list> //STL容器 11#include <algorithm> //STL算法 12using namespace std; 13 14 15 16/**//* 必须包含的头文件 */ 17#include <windows.h> 18#include <windowsx.h> 19#include <TlHelp32.h> 20#include <commctrl.h> 21 22#include <Winternl.h> 23 24 25#define LMAXSIZE 512 //一个字符串的最大长度 26#define LMAXSTR 64 //最多可以支持多少个字符串 27#define LMAXBUF 256 //临时缓冲区的最大长度 28#define TDSIZE 4096 //定义线程体或远程函数体的代码尺寸 29#define LCTRLMAX 8 30 31typedef struct _RemoteParam { 32 DWORD dwSendMessage; //SendMessage的入口函数地址 33 DWORD dwSetWindowLong; //SetWindowLong函数 34 DWORD dwNewSubClass; //新的SubClass的入口地址 35 DWORD dwCharLowerBuff; //CharLowerBuff函数的入口地址 36 DWORD dwlstrlen; //lstrlen函数的入口地址 37 DWORD dwMsgBox; //MessageBox函数的入口地址 38 DWORD dwlstrcmp; //lstrcmp函数的入口地址 39 DWORD dwOldSubClass[LCTRLMAX]; //原来的SubClass入口地址 40 HWND hWndArray[LCTRLMAX]; //SysListView32控件的窗口句柄数组 41 UINT nWndCount; //SysListView32控件窗口句柄的数量 42 int iCount; //存贮实际要隐藏名字串的数量 43 UINT iOffset[LMAXSTR]; //存贮名字串在szProcessName中的首地址索引 44 char szItemName[LMAXBUF]; //用做远程过程的临时缓冲区 45 char szProcessName[LMAXSIZE * LMAXSTR]; //存储要隐藏服务项目的字符串 46} RemoteParam; 47 48 49 50/**//* SendMessageA 和 WindowProc */ 51typedef LRESULT (__stdcall* PFN_SENDMSG)(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam); 52/**//* SetWindowLongW */ 53typedef LONG (__stdcall* PFN_SETWINDOWLONG)(HWND hWnd,int nIndex,LONG dwNewLong); 54/**//* MessageBoxA */ 55typedef int (__stdcall* PFN_MSGBOX)(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT uType); 56/**//* lstrcmp */ 57typedef int (__stdcall* PFN_LSTRCMP)(LPCTSTR lpString1,LPCTSTR lpString2); 58/**//* lstrlen */ 59typedef int (__stdcall* PFN_LSTRLEN)(LPCTSTR lpString); 60/**//* CharLowerBuf */ 61typedef DWORD (__stdcall* PFN_CHARLOWERBUFF)(LPTSTR lpsz,DWORD cchLength); 62 63 64 65 66class CHideProc 67{ 68public: 69 CHideProc(void); 70 ~CHideProc(void); 71 72 /**//* 接口函数 */ 73 74 /**//* 初始化 */ 75 BOOL HideReset(HWND hWnd,char* pszStrArray[],int iStrCount); 76 BOOL HideReset(HANDLE hProcess,char* pszStrArray[],int iStrCount); 77 BOOL HideReset(const char* pszExeName,char* pszStrArray[],int iStrCount); 78 BOOL HideReset(DWORD dwPID,char* pszStrArray[],int iStrCount); 79 80 /**//* 扫描 */ 81 BOOL HideScan(); 82 83 /**//* 结束 */ 84 void HideQuit(); 85 86 87private: 88 89 /**//* 找到目标控件窗口,并存入链表 */ 90 void FindChildWindow(HWND hWndTopLever,const char* pszWndText, 91 const char* pszWndClass); 92 93 /**//* 转化字符串 */ 94 BOOL ConvertFitString(); 95 96 /**//* 复位 */ 97 BOOL Reset(); 98 99 /**//* 根据程序名得到PID并存入链表 */ 100 void GetPIDByNameToList(); 101 102 /**//* DeleteUselessPID的子程序 */ 103 void FindAndDelete(DWORD dwPID,const char * pszKeyName); 104 105 /**//* 删除失效的PID */ 106 BOOL DeleteUselessPID(); 107 108 /**//* 检查PID是否已经注入过线程 */ 109 BOOL CheckPID(DWORD pid); 110 111 /**//* 提升进程权限 */ 112 BOOL EnableDebugPriv(); 113 114 /**//* 注入线程 */ 115 BOOL InsertRemoteThread(DWORD dwProcessId); 116 117 /**//* 新的窗口过程 */ 118 static LRESULT __stdcall NewWindowProc(HWND hWnd,UINT uMsg,WPARAM wParam, 119 LPARAM lParam); 120 121 /**//* 远程线程 */ 122 static DWORD __stdcall ThreadProc(LPVOID lParam); 123 124 /**//* 分配空间存贮字符串列表 */ 125 BOOL InitStringSet(char* pszStrArray[],int iStrCount); 126 127private: 128 list<DWORD> m_ListPIDDone; //存贮所有已经注入的PID 129 list<HWND> m_ListHWND; //某个PID对应的所有SysListView32窗口列表 130 list<DWORD> m_ListPIDAdd; //待注入线程的PID列表 131 HANDLE m_hProcess; //专用于进程句柄 132 HWND m_hWndCur; //专用于传入参数为窗口句柄 133 DWORD m_dwPID; //专用于PID 134 BYTE* m_pByte; //用于存贮转化后的字符串 135 char* m_pszExeName; //专用于进程名字 136 char** m_ppszItemList; //存贮要隐藏的字符串 137 UINT m_iCount; //偏移索引数组元素的个数 138 UINT* m_pUint; //偏移索引数组 139}; 140
/********************************************************************************************************* * * 实现文件: * *********************************************************************************************************/
1#include "hideproc.h" 2 3CHideProc::CHideProc(void) 4{ 5 m_dwPID = -1; 6 m_hProcess = NULL; 7 m_hWndCur = NULL; 8 m_iCount = -1; 9 10 m_ListHWND.clear(); 11 m_ListPIDAdd.clear(); 12 m_ListPIDDone.clear(); 13 14 15 m_pByte = NULL; 16 m_ppszItemList = NULL; 17 18 19 m_pszExeName = NULL; 20 m_pUint = NULL; 21 22 EnableDebugPriv(); 23} 24 25CHideProc::~CHideProc(void) 26{ 27} 28 29 30/**//* 转换大小写,并建立常量字符串数据字典 */ 31BOOL CHideProc::ConvertFitString() 32{ 33 m_pByte = new BYTE[LMAXSIZE * LMAXSTR]; 34 char* pStrBuf = (char*)m_pByte; 35 m_pUint = new UINT[LMAXSTR]; 36 37 ZeroMemory(pStrBuf,LMAXSIZE * LMAXSTR); 38 ZeroMemory(m_pUint,LMAXSTR*sizeof(UINT)); 39 40 for(UINT i=0;i<m_iCount;i++) 41 { 42 __try 43 { 44 lstrcat(pStrBuf,m_ppszItemList[i]); 45 lstrcat(pStrBuf,"#"); 46 } 47 __except(EXCEPTION_EXECUTE_HANDLER) 48 { 49 ::MessageBoxA(NULL,"错误:输入的字符串长度不匹配或转换错误,程序将结束!" 50 ,"信息提示:",MB_ICONINFORMATION | MB_OK); 51 return FALSE; 52 } 53 m_pUint[i+1] = (UINT)lstrlen(pStrBuf)-1; 54 } 55 56 ::CharLowerBuff(pStrBuf,(DWORD)lstrlen(pStrBuf)); 57 58 for(i=0;i<m_iCount;i++) 59 m_pByte[m_pUint[i+1]] = 0; 60 61 for(i=0;i<m_iCount;i++) 62 m_pUint[i+1] = m_pUint[i+1] + 1; 63 64 m_pUint[i] = 0; 65 66 return 0; 67} 68 69/**//* 新的窗口过程 */ 70LRESULT __stdcall CHideProc::NewWindowProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) 71{ 72 73 DWORD dwTest = NULL; 74 _asm 75 { 76 call dummy 77 dummy: 78 pop ecx 79 sub ecx,0x00000013 //得到EIP 80 mov dwTest, ecx //得到NewWindowProc的入口地址 81 } 82 83 RemoteParam* pRP = (RemoteParam*)(dwTest-sizeof(RemoteParam)); 84 for(UINT i=0;i<(pRP->nWndCount);i++) 85 { 86 if(pRP->hWndArray[i] == hWnd) 87 break; 88 } 89 90 PFN_SENDMSG pfnOldWindowProc = (PFN_SENDMSG)(DWORD)pRP->dwOldSubClass[i]; 91 PFN_SENDMSG pfnSendMessage = (PFN_SENDMSG)pRP->dwSendMessage; 92// PFN_MSGBOX pfnMSGBOX = (PFN_MSGBOX)pRP->dwMsgBox; 93 PFN_LSTRCMP pfnlstrcmp = (PFN_LSTRCMP)pRP->dwlstrcmp; 94 PFN_CHARLOWERBUFF pfnCharLowerBuf = (PFN_CHARLOWERBUFF)pRP->dwCharLowerBuff; 95 PFN_LSTRLEN pfnlstrlen = (PFN_LSTRLEN)pRP->dwlstrlen; 96 97 LV_ITEM Item; 98 Item.iSubItem = 0; 99 Item.mask = LVIF_TEXT; 100 Item.pszText = pRP->szItemName; 101 Item.cchTextMax = LMAXBUF; 102 char * pszName = NULL; 103 switch(uMsg) 104 { 105 case WM_PAINT: 106 { 107 108 int nCount = pfnSendMessage(hWnd,LVM_GETITEMCOUNT,0,0); 109 for(int i=0;i<nCount;i++) 110 { 111F: 112 for(int k=0;k<LMAXBUF;k++) 113 (pRP->szItemName)[k] = 0; 114 115 pfnSendMessage(hWnd,LVM_GETITEMTEXT,(WPARAM)i,(LPARAM)&Item); 116 pfnCharLowerBuf(Item.pszText,pfnlstrlen(Item.pszText)); 117 118 for(int j=0;j<(pRP->iCount);j++) 119 { 120 pszName = (char*)((pRP->szProcessName)+(pRP->iOffset[j])); 121 122 if(pfnlstrcmp(pszName,pRP->szItemName) == 0) 123 { 124 pfnSendMessage(hWnd,WM_SETREDRAW,(WPARAM)FALSE,0); 125 pfnSendMessage(hWnd,LVM_DELETEITEM,(WPARAM)i,0); 126 pfnSendMessage(hWnd,WM_SETREDRAW,(WPARAM)TRUE,0); 127 goto F; 128 } 129 } 130 } 131 } 132 } 133 return pfnOldWindowProc(hWnd,uMsg,wParam,lParam); 134} 135 136 137/**//* 远程线程调用 */ 138DWORD __stdcall CHideProc::ThreadProc(LPVOID lParam) 139{ 140 RemoteParam* pRP = (RemoteParam*)lParam; 141 142 PFN_SENDMSG pfnSendMessage = (PFN_SENDMSG)pRP->dwSendMessage; 143 HWND hWnd; 144 for(UINT i=0;i<(pRP->nWndCount);i++) 145 { 146 hWnd = (pRP->hWndArray)[i]; 147 PFN_SETWINDOWLONG pfnSetWindowLong = (PFN_SETWINDOWLONG)pRP->dwSetWindowLong; 148 pRP->dwOldSubClass[i] = (DWORD)pfnSetWindowLong(hWnd,GWL_WNDPROC,(LONG)(pRP->dwNewSubClass)); 149 pfnSendMessage(hWnd,WM_PAINT,0,0); 150 } 151 return 0; 152} 153 154 155/**//* 提升自己的进程访问权限 */ 156BOOL CHideProc::EnableDebugPriv() 157{ 158 HANDLE hToken; 159 LUID sedebugnameValue; 160 TOKEN_PRIVILEGES tkp; 161 162 if (!OpenProcessToken(GetCurrentProcess(), 163 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) 164 return FALSE; 165 166 167 if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue)) { 168 CloseHandle(hToken); 169 return FALSE; 170 } 171 172 tkp.PrivilegeCount = 1; 173 tkp.Privileges[0].Luid = sedebugnameValue; 174 tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 175 176 //更改权限 177 if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL)) { 178 CloseHandle(hToken); 179 return FALSE; 180 } 181 return TRUE; 182} 183 184 185/**//* 线程注入的详细实现 */ 186BOOL CHideProc::InsertRemoteThread(DWORD dwProcessId) 187{ 188 //控件窗口链 189 if( m_ListHWND.empty()) 190 return FALSE; 191 192 HANDLE hTargetProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId); 193 if (!hTargetProcess) 194 { 195 MessageBox(NULL, "打开句柄失败,不能对目标进程进行访问!", 196 "信息提示:", MB_ICONINFORMATION | MB_OK); 197 return FALSE; 198 } 199 200 RemoteParam remoteData; 201 ZeroMemory(&remoteData, sizeof(RemoteParam)); 202 203 HINSTANCE hUser32 = ::LoadLibrary("User32.dll"); 204 remoteData.dwSendMessage = (DWORD)GetProcAddress(hUser32, "SendMessageA"); 205 remoteData.dwSetWindowLong = (DWORD)GetProcAddress(hUser32, "SetWindowLongW"); 206 remoteData.dwMsgBox = (DWORD)GetProcAddress(hUser32, "MessageBoxA"); 207 remoteData.dwCharLowerBuff = (DWORD)GetProcAddress(hUser32, "CharLowerBuffA"); 208 ::FreeLibrary(hUser32); 209 210 HINSTANCE hKernel32 = ::LoadLibraryA("kernel32.dll"); 211 remoteData.dwlstrcmp = (DWORD)GetProcAddress(hKernel32, "lstrcmp"); 212 remoteData.dwlstrlen = (DWORD)::GetProcAddress(hKernel32,"lstrlenA"); 213 214 //主窗口下的所有SysListView32子窗口 215 remoteData.nWndCount = (UINT)m_ListHWND.size(); 216 list<HWND>::iterator pos; 217 int i=0; 218 for(pos = m_ListHWND.begin();pos != m_ListHWND.end(); ++pos,++i) 219 remoteData.hWndArray[i] = *pos; 220 221 /**////////////////////////// 222 ZeroMemory(remoteData.szProcessName,sizeof(remoteData.szProcessName)); 223 memcpy(remoteData.szProcessName,m_pByte,LMAXSIZE * LMAXSTR); 224 225 /**////////////////////////// 226 ZeroMemory(remoteData.iOffset,sizeof(remoteData.iOffset)); 227 memcpy(remoteData.iOffset,m_pUint,sizeof(int)*m_iCount); 228 remoteData.iCount = m_iCount; 229 230 /**////////////////////////// 231 ZeroMemory(remoteData.szItemName,sizeof(remoteData.szItemName)); 232 233 DWORD dwThreadSize = TDSIZE; 234 void* pRemoteThread = NULL; 235 void* pNewWindowProc = NULL; 236 __try 237 { 238 pNewWindowProc = VirtualAllocEx(hTargetProcess, 0, 239 dwThreadSize+sizeof(remoteData), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 240 241 if(pNewWindowProc == NULL) 242 { 243 MessageBox(NULL, "在目标进程分配内存页面失败!", 244 "信息提示:", MB_ICONINFORMATION | MB_OK); 245 246 CloseHandle(hTargetProcess); 247 return FALSE; 248 } 249 250 remoteData.dwNewSubClass = (DWORD)(void*)((char*)pNewWindowProc+sizeof(remoteData)); 251 252 /**//////////////////// 253 WriteProcessMemory(hTargetProcess,pNewWindowProc, 254 &remoteData, sizeof(remoteData), 0); 255 256 WriteProcessMemory(hTargetProcess,(void*)((char*)pNewWindowProc + sizeof(remoteData)), 257 &NewWindowProc, dwThreadSize, 0); 258 259 pRemoteThread = VirtualAllocEx(hTargetProcess, 0, 260 dwThreadSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 261 if(pRemoteThread == NULL) 262 { 263 MessageBox(NULL, "在目标进程分配内存页面失败!", 264 "信息提示:", MB_ICONINFORMATION | MB_OK); 265 266 CloseHandle(hTargetProcess); 267 return FALSE; 268 } 269 /**//////////////////// 270 WriteProcessMemory(hTargetProcess, 271 pRemoteThread, &ThreadProc, dwThreadSize, 0); 272 273 } 274 __except(EXCEPTION_EXECUTE_HANDLER) 275 { 276 MessageBox(NULL, "出现错误,无法在远程进程中分配或读写页面!。", 277 "信息提示:", MB_ICONINFORMATION | MB_OK); 278 279 CloseHandle(hTargetProcess); 280 return FALSE; 281 } 282 283 284 HANDLE hRemoteThread = NULL; 285 __try 286 { 287 /**/////////// 288 hRemoteThread = CreateRemoteThread(hTargetProcess, NULL, 0, 289 (DWORD (__stdcall *)(void *))pRemoteThread, pNewWindowProc, 0, 0); 290 } 291 __except(EXCEPTION_EXECUTE_HANDLER) 292 { 293 MessageBox(NULL, "出现错误,创建远程线程失败,程序将结束!。", 294 "信息提示:", MB_ICONINFORMATION | MB_OK); 295 296 297 ::VirtualFreeEx(hTargetProcess,pNewWindowProc,dwThreadSize+sizeof(remoteData), 298 MEM_RELEASE); 299 ::VirtualFreeEx(hTargetProcess,pRemoteThread,dwThreadSize,MEM_RELEASE); 300 301 CloseHandle(hTargetProcess); 302 return FALSE; 303 } 304 305 CloseHandle(hRemoteThread); 306 CloseHandle(hTargetProcess); 307 308 return TRUE; 309} 310 311 /**//* 用递归的方法实现查找某个窗口的子控件窗口 */ 312void CHideProc::FindChildWindow(HWND hWndTopLever,const char* pszWndText,const char* pszWndClass) 313{ 314 if(pszWndClass == NULL || !IsWindow(hWndTopLever))return; 315 316 317 HWND hWndChild = GetWindow(hWndTopLever,GW_CHILD); 318 if(hWndChild == NULL)return; 319 320 char szClass[256]; 321 char szText[256]; 322 323 while(hWndChild) 324 { 325 ZeroMemory(szClass,sizeof(szClass)); 326 ZeroMemory(szText,sizeof(szText)); 327 GetClassName(hWndChild,szClass,sizeof(szClass)); 328 if(lstrcmp(szClass,pszWndClass) == 0) 329 { 330 GetWindowText(hWndChild,szText,sizeof(szText)); 331 if(pszWndText != NULL) 332 { 333 if(lstrcmp(szText,pszWndText) == 0) 334 m_ListHWND.push_back(hWndChild); 335 } 336 else 337 m_ListHWND.push_back(hWndChild);; 338 } 339 FindChildWindow(hWndChild,pszWndText,pszWndClass); 340 hWndChild = GetWindow(hWndChild,GW_HWNDNEXT); 341 } 342 return; 343} 344 345 346/**//* DeleteUselessPID的子程序 */ 347void CHideProc::FindAndDelete(DWORD dwPID,const char * pszKeyName) 348{ 349 list<DWORD>::iterator pos; 350 pos = find(m_ListPIDDone.begin(),m_ListPIDDone.end(),dwPID); 351 if(pos != m_ListPIDDone.end()) 352 { 353 if(lstrcmp(pszKeyName,m_pszExeName) != 0) 354 m_ListPIDDone.remove(dwPID); 355 } 356} 357 358 359/**//* 删除无效的PID */ 360BOOL CHideProc::DeleteUselessPID() 361{ 362 if(m_ListPIDDone.empty()) 363 return TRUE; 364 365 HANDLE hSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,NULL); 366 PROCESSENTRY32 pe; 367 pe.dwSize = sizeof(pe); 368 if(!::Process32First(hSnap,&pe)) 369 return FALSE; 370 FindAndDelete(pe.th32ProcessID,pe.szExeFile); 371 372 while(::Process32Next(hSnap,&pe)) 373 FindAndDelete(pe.th32ProcessID,pe.szExeFile); 374 375 return TRUE; 376} 377 378/**//* 检查重复的PID */ 379BOOL CHideProc::CheckPID(DWORD pid) 380{ 381 if(m_ListPIDDone.empty()) 382 return FALSE; 383 list<DWORD>::iterator pos; 384 pos = find(m_ListPIDDone.begin(),m_ListPIDDone.end(),pid); 385 if(pos != m_ListPIDDone.end()) 386 return TRUE; 387 388 return FALSE; 389} 390 391 392 393 394/**//* 进程名 */ 395BOOL CHideProc::HideReset(const char* pszExeName,char* pszStrArray[],int iStrCount) 396{ 397 if(pszExeName == NULL) 398 return FALSE; 399 400 Reset(); 401 402 UINT uLen = lstrlen(pszExeName) + 1; 403 m_pszExeName = new char[uLen]; 404 ZeroMemory(m_pszExeName,uLen); 405 lstrcpy(m_pszExeName,pszExeName); 406 407 m_iCount = iStrCount; 408 409 InitStringSet(pszStrArray,iStrCount); 410 411 ConvertFitString(); 412 413 return TRUE; 414} 415 416/**//* 进程句柄 */ 417BOOL CHideProc::HideReset(HANDLE hProcess,char* pszStrArray[],int iStrCount) 418{ 419 if(hProcess == NULL) 420 return FALSE; 421 422 Reset(); 423 424 m_hProcess = hProcess; 425 426 InitStringSet(pszStrArray,iStrCount); 427 428 ConvertFitString(); 429 430 return TRUE; 431} 432 433/**//* 进程主窗口 */ 434BOOL CHideProc::HideReset(HWND hWnd,char* pszStrArray[],int iStrCount) 435{ 436 if(hWnd == NULL) 437 return FALSE; 438 439 Reset(); 440 441 m_hWndCur = hWnd; 442 443 InitStringSet(pszStrArray,iStrCount); 444 445 ConvertFitString(); 446 447 return TRUE; 448} 449 450/**//* 给定PID */ 451BOOL CHideProc::HideReset(DWORD dwPID,char* pszStrArray[],int iStrCount) 452{ 453 454 if(dwPID == -1) 455 return FALSE; 456 457 Reset(); 458 459 m_dwPID = dwPID; 460 461 InitStringSet(pszStrArray,iStrCount); 462 463 ConvertFitString(); 464 465 return 0; 466} 467 468/**//* 复位状态,释放内存 */ 469BOOL CHideProc::Reset() 470{ 471 if(m_pszExeName != NULL) 472 delete []m_pszExeName; 473 474 475 if(m_ppszItemList != NULL){ 476 for(UINT i=0;i<m_iCount;i++) 477 delete []m_ppszItemList[i]; 478 delete m_ppszItemList; 479 } 480 481 if(m_pByte != NULL) 482 delete []m_pByte; 483 484 if(m_pUint != NULL) 485 delete []m_pUint; 486 487 488 489 m_dwPID = -1; 490 m_hProcess = NULL; 491 m_hWndCur = NULL; 492 m_iCount = -1; 493 494 m_ListHWND.clear(); 495 m_ListPIDAdd.clear(); 496 497 m_pByte = NULL; 498 m_ppszItemList = NULL; 499 500 501 m_pszExeName = NULL; 502 m_pUint = NULL; 503 504 return 0; 505} 506 507/**//* 退出时释放动态内存 */ 508void CHideProc::HideQuit() 509{ 510 Reset(); 511 m_ListPIDDone.clear(); 512} 513 514/**//* 根据进程名字得到PID并存入链表 */ 515void CHideProc::GetPIDByNameToList() 516{ 517 if(m_pszExeName == NULL) 518 return ; 519 520 HANDLE hSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 521 NULL); 522 523 PROCESSENTRY32 pe; 524 pe.dwSize = sizeof(pe); 525 if(!::Process32First(hSnap,&pe)) 526 return; 527 528 if(lstrcmp(pe.szExeFile,m_pszExeName) == 0) 529 m_ListPIDAdd.push_back(pe.th32ProcessID); 530 531 while(::Process32Next(hSnap,&pe)) 532 if(lstrcmp(pe.szExeFile,m_pszExeName) == 0) 533 m_ListPIDAdd.push_back(pe.th32ProcessID); 534} 535 536/**//* 一次扫描注入进程 */ 537BOOL CHideProc::HideScan() 538{ 539 DeleteUselessPID(); 540 m_ListPIDAdd.clear(); 541 //给出进程名 542 GetPIDByNameToList(); 543 //给出进程 544 if(m_hProcess != NULL) 545 m_ListPIDAdd.push_back(GetProcessId(m_hProcess)); 546 //给出PID 547 if(m_dwPID != -1) 548 m_ListPIDAdd.push_back(m_dwPID); 549 //给出窗口句柄 550 DWORD dwProcessID = 0; 551 if(m_hWndCur != NULL) 552 if(!IsWindow(m_hWndCur)) 553 return FALSE; 554 else 555 { 556 GetWindowThreadProcessId(m_hWndCur,&dwProcessID); 557 if(CheckPID(dwProcessID)) 558 return FALSE; 559 560 m_ListHWND.clear(); 561 FindChildWindow(m_hWndCur,NULL,"SysListView32"); 562 if(m_ListHWND.empty()) 563 return FALSE; 564 565 if(InsertRemoteThread(dwProcessID)) 566 m_ListPIDDone.push_back(dwProcessID); 567 m_ListHWND.clear(); 568 return TRUE; 569 } 570 571 if(m_ListPIDAdd.empty()) 572 return FALSE; 573 574 575 HWND hWndTop= ::GetDesktopWindow(); 576 HWND hWndChild = hWndTop; 577 list<DWORD>::iterator pos; 578 579 BOOL bFirst = TRUE; 580 while(hWndChild) 581 { 582 dwProcessID = 0; 583 if(bFirst){ 584 hWndChild = ::GetWindow(hWndChild,GW_CHILD); 585 bFirst = FALSE; 586 }else{//枚举窗口 587 hWndChild = ::GetWindow(hWndChild,GW_HWNDNEXT); 588 } 589 590 GetWindowThreadProcessId(hWndChild,&dwProcessID); 591 if(CheckPID(dwProcessID)) 592 continue; 593 594 pos = find(m_ListPIDAdd.begin(),m_ListPIDAdd.end(),dwProcessID); 595 if(pos == m_ListPIDAdd.end()) 596 continue; 597 598 if(CheckPID(dwProcessID)) 599 continue; 600 601 602 m_ListHWND.clear(); 603 FindChildWindow(hWndChild,NULL,"SysListView32"); 604 if(m_ListHWND.empty()) 605 continue; 606 607 //注入线程 608 if(InsertRemoteThread(dwProcessID)) 609 m_ListPIDDone.push_back(dwProcessID); 610 m_ListHWND.clear(); 611 } 612 613 Sleep(5); 614 return TRUE; 615} 616 617BOOL CHideProc::InitStringSet(char* pszStrArray[],int iStrCount) 618{ 619 UINT uLen; 620 m_ppszItemList = (char**)new char[iStrCount*(sizeof(char*))]; 621 m_iCount = iStrCount; 622 for(int i=0; i<iStrCount; i++) 623 { 624 uLen = lstrlen(pszStrArray[i]) + 1; 625 m_ppszItemList[i] = new char[uLen]; 626 ZeroMemory(m_ppszItemList[i],uLen); 627 lstrcpy(m_ppszItemList[i],pszStrArray[i]); 628 } 629 return 0; 630}
希望以上的代码和介绍能对你学习Windows编程有所帮助,代码如果有谬误或者你有更好的解决方法,请留言或者EmailToMe:xiaolu69soft@yahoo.com.cn。 星绽紫辉2008-12-30完稿 http://www.cppblog.com/rawdat
|