首页
社区
课程
招聘
[原创][原创]窗口句柄查看器改造成可“十六进制”显示
发表于: 2013-4-3 08:51 3888

[原创][原创]窗口句柄查看器改造成可“十六进制”显示

2013-4-3 08:51
3888
网上的一款工具“窗口句柄查看器”具有神奇的功能,当鼠标移到任何窗口,都会显示窗口句柄,鼠标位置,窗口类名,颜色等,我是十分佩服软件作者厉害。但是,鼠标位置和窗口句柄都是十进制显示,一些软件如OD等一般是十六进制使用句柄,内部也是十六进制,十六进制显示用起来更加方便,就想把这款工具改造一下:根据需要,用户可以选择是“十进制”或者“十六进制”。
  “喊破嗓子不如甩开膀子”,这就“操刀”。使用工具“ollydbg1.1”,改造对象:“GetHND.exe”,运行OD,打开“GetHND.exe”,F9,好了。屏幕左上角出现了一个小窗口,这就是“GetHND.exe”的输出窗口,显示内容为:Point:[xx,yyy];HWND: [xxxxxx]。。。。
[xx,yyy]是鼠标位置,HWND:[xxxxxx]是窗口句柄,都是十进制的。我们知道,内存中的东西都是十六进制的,要显示输出,必须装换成ASCII码的字符。进内存搜搜看,运气好的话找到“Point”,“HWND”字样就有线索了。来到OD界面,左单击工具菜单的M按钮,打开内存映射,使用OD的查找功能,在内存中查找ASCII“Point”,找到几处,都不是目标,放弃。换成查找UNICODE“Point”哈哈,感谢上帝,找到了,后面还有“HWND”,“ClassName”等等,就是它了。我的电脑中地址为“394F80”,回到OD界面,在数据窗口(即OD的左下角窗口)右单击鼠标,来到地址:00 39F80,就在这个内存处下内存访问断点,看是谁访问了了那串可爱的字符串。动一下鼠标,断下了。地址为0038B33A ,看代码
0038B33A  F3:66:A5  REP MOVS ES:[EDI],  DS:[ESI],
这是干啥的,大家都知道要“搬家了”,把ESI出的东东搬到EDI处。
接下来干什么?追呀,追谁?显然是EDI,ESI是源操作数,EDI是目的地,来到EDI指定的地址,删除原来内存断点,在这里下内存写入断点,范围就选出32个字节,n次F9键,你看到了什么?注意Point后面的内容,是什么,就是鼠标坐标。现在目标缩小了,选取代表鼠标坐标的四个字节,下内存写入断点,动一下鼠标,断下了
0038B33A F3:66:A5 REP MOVS WORD ES:[EDI],WORD  DS:[ESI]
这次追谁?EDI? 错了,是ESI,我们要找到ESI指定的位置,看是谁写入的那个代表坐标的数值。转到esi指定的位置,下内存写入断点,4个字节。动一下鼠标,断下了。
0038A5E4  66:8916     |MOV WORD PTR DS:[ESI],DX
好呀DX,就是你,放大一下代码范围

0038A5C8 /$ B9 0A000000 MOV ECX,0A  ;ECX,赋值十进制:10
0038A5CD |>  52    PUSH EDX    ;保护EDX
0038A5CE |.  56     PUSH ESI      ;保护ESI
0038A5CF |> 31D2  /XOR EDX,EDX ;扩展除法运算源操作数EAX
0038A5D1  |.  F7F1  |DIV ECX  ;除以10,余数在EDX ,有效数                                                     字在DX
0038A5D3  |.  66:83C2 30 |ADD  DX,30      ;数字转换成ASCII                                              码输出可见格式
0038A5D7  |.  83EE 02       |SUB ESI,2
0038A5DA  |.  66:83FA 3A    |CMP DX,3A
0038A5DE  |.  72 04         |JB SHORT MHook.0038A5E4
0038A5E0 66:83C2 07| ADD DX,7 ;字母转换成ASCII                                                     码输出可见格式
0038A5E4  |>  66:8916     |MOV WORD PTR DS:[ESI],DX
这段代码好面熟,是把内存中十六进制数,变为十进制数的ASCII,猜想是在做窗口输出前的准备工作!“秘密”全在这里了
0038A5C8 /$ B9 0A000000 MOV ECX,0A ,
为了好读,我在代码后加了一些注释。
我们的任务是,保留十六进制数,变为可见输出格式输出。算法很简单,只需把MOV ECX,0A中的0A改为10,就OK了。修改这句代码038A5C8  /$  B9 0F000000   MOV ECX,10  修改完毕,存盘,哇,在DLL中,作者使用了HOOK钩子技术,把鼠标HOOK了,难怪他能得到鼠标位置信息,这个HOOK钩子真是强大呀,值得好好学习呀!!
  好事做到底,为了还能保留原来用十进制显示的功能,干脆来个“绝活”,既然你HOOK了鼠标,我要好好利用一下你的HOOK成果,干脆做成一个“点一下鼠标,十进制显示,再点一下,又变成十六进制显示”,这样比较爽。下面是具体方法。
     查找HOOK钩子回调函数过程地址,使用OD,查找钩子在何处安装。找到两处
A处:
0046D141  |.  50       PUSH EAX        ; /ThreadID
0046D142  |.  6A 00    PUSH 0           ; |hModule = NULL
0046D144  |.  A1 10424800   MOV EAX,DWORD PTR DS:[484210] 0046D149  |.  50 PUSH EAX;  |Hookproc => GetHWND.0046D0E0
0046D14A  |.  6A 03 PUSH 3   ; |HookType = WH_GETMESSAGE
0046D14C  |.E83B4F9FFCALL<JMP.&user32.SetWindowsHookExW>
003950E0 >/$  6A 00    PUSH 0          ; /ThreadID = 0

B处:
003950E2  |.  A1 18BB3900  MOV EAX,DWORD PTR DS:[39BB18] 003950E7  |.  50  PUSH EAX   ; |hModule => 00380000 (MHook)
003950E8  |.  B8 EC4C3900  MOV EAX,394CEC   ; ||Hookproc =>                                           MHook.MouseHook
003950ED  |. 50  PUSH  EAX ;  |Hookproc => MHook.MouseHook
003950EE  |.  6A 0E  PUSH  0E  ; |HookType = 14.
003950F E8 DB18FFFF CALL <JMP.&user32.SetWindowsHookExW>   从注释上可以看出A段HOOK,HookType为WH_GETMESSAGE,消息钩子,不是,放弃
B:段的Hookproc是:|Hookproc => MHook.MouseHook,鼠标钩子   是正解。
003950E2  |. A1 18BB3900  MOV EAX,DWORD PTR DS:[39BB18]
这句蕴藏着“宝贝”,[39BB18]存着钩子模块的句柄,有用的东西。

003950E8  |.  B8 EC4C3900  MOV EAX,394CEC   ; ||Hookproc =>                                           MHook.MouseHook
这句表明钩子回调函数过程地址为:00394CEC    ; 
到那里瞧瞧“庐山真面目”
00394CEC >/$  55                  PUSH EBP
00394CED  |.  8BEC                MOV EBP,ESP
00394CEF  |.  81C4 7CFDFFFF     ADD ESP,-284
00394CF5  |.  53                  PUSH EBX
00394CF6  |.  56                  PUSH ESI
00394CF7  |.  57                  PUSH EDI
。。。。。。。。。。             。。。。。。。。。。。。。。。。
00394F1D  |.  56    PUSH ESI      ; /lParam
00394F1E  |.  8B45 0C  MOV EAX,DWORD PTR SS:[EBP+C]  ; |
00394F21  |.  50    PUSH EAX       ; |wParam
00394F22  |.  8B45 08  MOV EAX,DWORD PTR SS:[EBP+8]   ; |
00394F25  |.  50   PUSH EAX               ; |HookCode
00394F26  |.  A1 78003A00    MOV EAX,DWORD PTR DS:[3A0078]                ; |
00394F2B  |.  50    PUSH EAX         ; |hHook => 05DA0281
00394F2C  |.  E8 471AFFFF CALL <JMP.&user32.CallNextHookEx> ;                                            \CallNextHookEx
00394F2C这句代码清楚表明这是钩子回调过程确信无疑。
鼠标钩子安装好了,已有鼠标消息,Windows就会来到这里执行这些代码,参数就包括有鼠标动作代码,到哪里去找那个参数?[EBP+N]处就是,在这里设断点,动一下鼠标,这里一定断下,到堆栈窗口找一下,值为200的便是“鼠标移动代码”。
00394CEF  |.  81C4 7CFDFFFF  ADD ESP,-284
占用6个字节,就把它作为“开口处”好了,改为
00394CEF    Call  [XXXXXXXX],正好6字节。
这里用接调用保险,我设定为[484FF8],真正子程序入口存储在484FF8处,之所以选取这里也是为了稳妥,从482000处开始是主程序的数据段,这个段跟着主程序走,位置是相对固定的。484FF8是数据段的末尾,主程序的全局变量一般用不到这么远。为什么要简介调用?因为这是在DLL之中“开子程序入口”,DLL文件装入内存它的基地址是可变的,只有采用间接调用才能确保调用到子程序。下面还有个关键问题要解决,不要忘了 ADD ESP,-284被改动了,在子程序结束前要恢复。一般指令原来是啥,子程序结束前写上同样的指令简单恢复一下就行,涉及到ESP问题就大了,就本例讲不能简单地 
XXXXXXXX   ADD ESP  ,  -284
XXXXXXXX   RET
真要这样做那就麻烦了,RET到十万八千里之外,返回不了了。Esp动了,必须先在ESP处安排返回正确地址,下面是正确代码。
00480B97 8F8424 78FDFF   POP  DWORD PTR SS:[ESP-288];
                  ;这句代码非常关键关键,安排好正确返回地址
00480B9E  81C4 78FDFFFF   ADD ESP  ,  -288
             ;恢复指令,为什么-284变成-288,因后面有RET,               执行后会ESP+4,为了确保返回后ESP和不调用子               程序时是一样的数值就需要这样“校正”。
00480BA4  C3   RET

以上是“开口”问题,子程序代码应该是这个样子:
响应鼠标单击事件,可用左键UP为标志(代码201),
0038A5C8 /$ B9 0F000000 MOV ECX,0A 中的0A改为10
再次单击鼠标,把10改为0A。改代码,比较繁琐,初次接触感觉很复杂,习惯了就很简单。无非是调用API,GetModuleHandleA,OpenProcessMemory,WriteProcessMemory,这些是改代码必须的,你想用“mov ”的方法改代码人家Windows不批准,说你“非法操作”,这些API一般都不是现成的拿过来就用,得用GetProce一一找到,把代码都列出来就很多。我把改好的GetHND.exe作为附件,有兴趣的可以用OD仔细研究。不足之处和不对的地方请高手指正!
 不会排版,委屈大家了凑合着看吧!也不知那些“草木皆兵”的杀毒软件会不会报病毒。

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 185
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
楼主说的这个工具 在VC里面叫做spy++  在<windows核心编程> 这本书中。有详细的源代码。 直接修改展示页就可以啦
2013-4-3 08:56
0
游客
登录 | 注册 方可回帖
返回
//