找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 3742|回复: 1

研究spy++如何获取窗口的WndProc回调地址

[复制链接]

307

主题

228

回帖

7349

积分

用户组: 真·技术宅

UID
2
精华
76
威望
291 点
宅币
5599 个
贡献
253 次
宅之契约
0 份
在线时间
949 小时
注册时间
2014-1-25
发表于 2015-1-16 17:04:05 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
    该题目源于网上一段提问,提问者问:每个窗口都有其回调函数WndProc用于处理消息,然而如果获取其他进程的窗口信息,通过GetWindowLong仅能获取到除了WndProc以外的参数,唯独WndProc获取不了,然而为何Spy++可以?是通过HWND对应的内核结构获取到的吗?(内核驱动我不懂,懂得大哥说说)
    经过实验我发现确实不能用GetWindowLong获取到该参数GWL_WNDPROC,于是我决定研究一下Spy++,弄了一天终于研究出来了。分析表明Spy++采取了Windows自带Hook功能获取一些特殊窗口参数,关键代码在spyxxhk.dll的SpyxxGetMsgProc函数中。试验方法是:随便用spy++查找一个窗口,右键查看窗口属性,看常规选项卡中“窗口进程”的结果,例如00417912,之后用Winhex打开Spyxx.exe进程的SPYXXHK.DLL模块,搜索该数据,发现在6D325C44处,使用IDA附加该进程,查看该处地址为一变量,查看引用可知SpyxxGetMsgProc中对其进行了修改。接下来看Spyxx.exe对该函数的调用,可以分析出如下代码:

  1. HMODULE spyhkmod;
  2. HHOOK getmsghook;
  3. HHOOK callwndprochook;
  4. HHOOK callwndprocrethook;
  5. extern HHOOK _ghhkMsgHook;//dll导出变量,对应getmsghook
  6. extern HHOOK _ghhkCallHook;//dll导出变量,对应callwndprochook
  7. extern HHOOK _ghhkRetHook;//dll导出变量,对应callwndprocrethook

  8. void SetMsgHook(BOOL Enable)
  9. {
  10.         if(Enable)//hook
  11.         {
  12.                 if(!spyhkmod)
  13.                 {
  14.                         spyhkmod=GetModuleHandle(_T("SpyxxHk"));
  15.                         if(!spyhkmod)
  16.                                 return;
  17.                 }
  18.                 if(!getmsghook)
  19.                 {
  20.                         getmsghook=SetWindowsHookEx(WH_GETMESSAGE,SpyxxGetMsgProc,spyhkmod,0);
  21.                         if(!getmsghook)
  22.                         {
  23.                                 CString text,caption;
  24.                                 text.LoadString(113);//Cannot set the WH_GETMESSAGE hook.  Message logging is inoperable.
  25.                                 caption.LoadString(1);//Microsoft Spy++
  26.                                 MessageBox(NULL,text,caption,MB_OK|MB_ICONEXCLAMATION|MB_SYSTEMMODAL);
  27.                                 return;
  28.                         }
  29.                         _ghhkMsgHook=getmsghook;
  30.                 }
  31.                 if(!callwndprochook)
  32.                 {
  33.                         callwndprochook=SetWindowsHookEx(WH_CALLWNDPROC,SpyxxCallWndProc,spyhkmod,0);
  34.                         if(!callwndprochook)
  35.                         {
  36.                                 CString text,caption;
  37.                                 text.LoadString(114);//Cannot set the WH_CALLWNDPROC hook.  Message logging is inoperable.
  38.                                 caption.LoadString(1);//Microsoft Spy++
  39.                                 MessageBox(NULL,text,caption,MB_OK|MB_ICONEXCLAMATION|MB_SYSTEMMODAL);
  40.                                 UnhookWindowsHookEx(getmsghook);
  41.                                 return;
  42.                         }
  43.                         _ghhkCallHook=callwndprochook;
  44.                 }
  45.                 if(!callwndprocrethook)
  46.                 {
  47.                         callwndprocrethook=SetWindowsHookEx(WH_CALLWNDPROCRET,SpyxxCallWndRetProc,spyhkmod,0);
  48.                         if(!callwndprocrethook)
  49.                         {
  50.                                 CString text,caption;
  51.                                 text.LoadString(115);//,Cannot set the WH_CALLWNDPROCRET hook.  Message logging is inoperable.
  52.                                 caption.LoadString(1);//Microsoft Spy++
  53.                                 MessageBox(NULL,text,caption,MB_OK|MB_ICONEXCLAMATION|MB_SYSTEMMODAL);
  54.                                 UnhookWindowsHookEx(getmsghook);
  55.                                 UnhookWindowsHookEx(callwndprochook);
  56.                                 return;
  57.                         }
  58.                         _ghhkRetHook=callwndprocrethook;
  59.                 }
  60.         }
  61.         else//unhook
  62.         {
  63.                 if(getmsghook)
  64.                 {
  65.                         UnhookWindowsHookEx(getmsghook);
  66.                         getmsghook=NULL;
  67.                 }
  68.                 if(callwndprochook)
  69.                 {
  70.                         UnhookWindowsHookEx(callwndprochook);
  71.                         callwndprochook=NULL;
  72.                 }
  73.                 //还有一个没有unhook呢?bug?
  74.         }
  75. }

  76. HWND hWnd;
  77. HANDLE hWriterMutex,hAccessMutex,hReadEvent,hWrittenEvent,hOtherAccessMutex,hOtherDataEvent;
  78. void HookMain(void* param)
  79. {
  80.         hWriterMutex = CreateMutexW(0, 0, L"Local\\Spy++ Writer Mutex");
  81.         hAccessMutex = CreateMutexW(0, 0, L"Local\\Spy++ Access Mutex");
  82.         hReadEvent = CreateEventW(0, 0, 1, L"Local\\Spy++ Read Event");
  83.         hWrittenEvent = CreateEventW(0, 0, 0, L"Local\\Spy++ Written Event");
  84.         hOtherAccessMutex = CreateMutexW(0, 0, L"Local\\Spy++ Other Process Access Mutex");
  85.         hOtherDataEvent = CreateEventW(0, 0, 0, L"Local\\Spy++ Other Process Data Event");
  86.         PSECURITY_DESCRIPTOR sd=NULL;
  87.         if(ConvertStringSecurityDescriptorToSecurityDescriptor(
  88.                 _T("D:(A;;GA;;;WD)(A;;GA;;;SY)(A;;GA;;;BA)(A;;GA;;;AN)(A;;GA;;;RC)(A;;GA;;;S-1-15-2-1)"),
  89.                 SDDL_REVISION_1,&sd,NULL))
  90.         {
  91.                 PACL pDacl;
  92.                 BOOL bDaclPresent;
  93.                 BOOL bDaclDefaulted;
  94.                 if(GetSecurityDescriptorDacl(sd,&bDaclPresent,&pDacl,&bDaclDefaulted))
  95.                 {
  96.                         SetSecurityInfo(hWriterMutex,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION,NULL,NULL,pDacl,NULL);
  97.                         SetSecurityInfo(hAccessMutex,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION,NULL,NULL,pDacl,NULL);
  98.                         SetSecurityInfo(hReadEvent,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION,NULL,NULL,pDacl,NULL);
  99.                         SetSecurityInfo(hWrittenEvent,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION,NULL,NULL,pDacl,NULL);
  100.                         SetSecurityInfo(hOtherAccessMutex,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION,NULL,NULL,pDacl,NULL);
  101.                         SetSecurityInfo(hOtherDataEvent,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION,NULL,NULL,pDacl,NULL);
  102.                 }
  103.                 LocalFree(sd);
  104.         }
  105.         if(ConvertStringSecurityDescriptorToSecurityDescriptor(_T("S:(ML;;NW;;;LW)"),SDDL_REVISION_1,&sd,NULL))
  106.         {
  107.                 PACL pSacl;
  108.                 BOOL bDaclPresent;
  109.                 BOOL bDaclDefaulted;
  110.                 if(GetSecurityDescriptorDacl(sd,&bDaclPresent,&pSacl,&bDaclDefaulted))
  111.                 {
  112.                         SetSecurityInfo(hWriterMutex,SE_KERNEL_OBJECT,LABEL_SECURITY_INFORMATION,NULL,NULL,pSacl,NULL);
  113.                         SetSecurityInfo(hAccessMutex,SE_KERNEL_OBJECT,LABEL_SECURITY_INFORMATION,NULL,NULL,pSacl,NULL);
  114.                         SetSecurityInfo(hReadEvent,SE_KERNEL_OBJECT,LABEL_SECURITY_INFORMATION,NULL,NULL,pSacl,NULL);
  115.                         SetSecurityInfo(hWrittenEvent,SE_KERNEL_OBJECT,LABEL_SECURITY_INFORMATION,NULL,NULL,pSacl,NULL);
  116.                         SetSecurityInfo(hOtherAccessMutex,SE_KERNEL_OBJECT,LABEL_SECURITY_INFORMATION,NULL,NULL,pSacl,NULL);
  117.                         SetSecurityInfo(hOtherDataEvent,SE_KERNEL_OBJECT,LABEL_SECURITY_INFORMATION,NULL,NULL,pSacl,NULL);
  118.                 }
  119.                 LocalFree(sd);
  120.         }
  121.         //.........
  122.         SetMsgHook(TRUE);
  123.         //........
  124. }
  125. void WINAPI CreateHookThread()
  126. {
  127.         //.........
  128.         _beginthread(HookMain,0x10000,hWnd);
  129.         //.........
  130. }
  131. int CSpyApp::InitInstance()
  132. {
  133.         //.........
  134.         CreateHookThread();
  135.         //.........
  136. }
  137. BOOL gfHookEnabled,gfHookDisabled;
  138. DWORD _gpidSpyxx;
  139. LRESULT WINAPI SpyxxCallWndProc(int nCode, WPARAM wParam, LPARAM lParam)
  140. {
  141.         LRESULT ret=CallNextHookEx(_ghhkCallHook,nCode,wParam,lParam);
  142.         CWPSTRUCT* cwp=(CWPSTRUCT*)lParam;
  143.         if(gfHookEnabled && !gfHookDisabled && nCode == HC_ACTION && cwp && cwp->hwnd)
  144.         {         
  145.                  DWORD procid;
  146.                 DWORD id=GetWindowThreadProcessId(cwp->hwnd,&procid);
  147.                 if(procid != _gpidSpyxx && id != _gpidSpyxx && GetCurrentThreadId() != _gpidSpyxx)
  148.                         func(1,0,cwp->hwnd,cwp->message,cwp->wParam,cwp->lParam,0,0,0);
  149.         }
  150.         return ret;
  151. }
  152. LRESULT WINAPI SpyxxCallWndRetProc(int nCode, WPARAM wParam, LPARAM lParam)
  153. {
  154.         LRESULT ret=CallNextHookEx(_ghhkRetHook,nCode,wParam,lParam);
  155.         CWPRETSTRUCT* cwp=(CWPRETSTRUCT*)lParam;
  156.         if(gfHookEnabled && !gfHookDisabled && nCode == HC_ACTION && cwp && cwp->hwnd)
  157.         {         
  158.                  DWORD procid;
  159.                 DWORD id=GetWindowThreadProcessId(cwp->hwnd,&procid);
  160.                 if(procid != _gpidSpyxx && id != _gpidSpyxx && GetCurrentThreadId() != _gpidSpyxx)
  161.                         func(2,cwp->lResult,cwp->hwnd,cwp->message,cwp->wParam,cwp->lParam,0,0,0);
  162.         }
  163.         return ret;
  164. }
  165. UINT gmsgOtherProcessData;
  166. HWND gopd;//目标进程窗口句柄,exe在OnIdle例程中修改该处
  167. DWORD goproc;//目标窗口回调函数地址
  168. WNDCLASS WndClass;
  169. LRESULT WINAPI SpyxxGetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
  170. {
  171.         MSG* msg=(MSG*)lParam;
  172.         if(nCode == HC_ACTION && (wParam&PM_REMOVE) && msg && msg->hwnd)
  173.         {
  174.                 if(msg->message == gmsgOtherProcessData)
  175.                 {
  176.                         if(msg->hwnd == gopd && hAccessMutex && !WaitForSingleObject(hAccessMutex,1000))
  177.                         {
  178.                                 TCHAR ClassName[128];
  179.                                 GetClassName(msg->hwnd,ClassName,128);
  180.                                 if(IsWindowUnicode(msg->hwnd))
  181.                                         goproc=GetWindowLongW(msg->hwnd,GWL_WNDPROC);
  182.                                 else
  183.                                         goproc=GetWindowLongA(msg->hwnd,GWL_WNDPROC);
  184.                                 if(GetClassInfoW(NULL,ClassName,&WndClass))
  185.                                 {
  186.                                         if(WndClass.lpszMenuName) {/*...............*/};
  187.                                         if(IsWindowUnicode(msg->hwnd))
  188.                                                 WndClass.lpfnWndProc=(WNDPROC)GetClassLongW(msg->hwnd,GCL_WNDPROC);
  189.                                 }
  190.                                 //..............
  191.                                 msg->message=0;
  192.                                 msg->wParam=0;
  193.                                 msg->lParam=0;
  194.                         }
  195.                 }
  196.                 else if(gfHookEnabled && !gfHookDisabled)
  197.                 {
  198.                         DWORD procid;
  199.                         DWORD id=GetWindowThreadProcessId(msg->hwnd,&procid);
  200.                         if(procid != _gpidSpyxx && id != _gpidSpyxx && GetCurrentThreadId() != _gpidSpyxx)
  201.                                 func(0,0,msg->hwnd,msg->message,msg->wParam,msg->lParam,msg->time,msg->pt.x,msg->pt.y);
  202.                 }
  203.         }
  204.         return CallNextHookEx(_ghhkMsgHook,nCode,wParam,lParam);
  205. }
复制代码



Window编写hook时是要把函数放在专门的dll中,hook后所有程序都会自动加载该dll。
回复

使用道具 举报

1112

主题

1653

回帖

7万

积分

用户组: 管理员

一只技术宅

UID
1
精华
245
威望
744 点
宅币
24265 个
贡献
46222 次
宅之契约
0 份
在线时间
2299 小时
注册时间
2014-1-26
发表于 2015-1-17 12:52:31 | 显示全部楼层
从没注意到GetWindowLong只能对自己进程的窗口用
回复 赞! 靠!

使用道具 举报

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-5-4 20:09 , Processed in 0.036985 second(s), 28 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表