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

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

2013-4-3 09:18
8032

网上的一款工具“窗口句柄查看器”具有神奇的功能,当鼠标移到任何窗口,都会显示窗口句柄,鼠标位置,窗口类名,颜色等,

,我是十分佩服软件作者厉害。但是,鼠标位置和窗口句柄都是十进制显示,一些软件如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的便是“鼠标移动代码”。根据200

所长在位置和此时的EBP值不难确定[EBP+N]当中的N是多少,这个N要记下,以备后面写子程序代码时拿到鼠标单击代码之用。

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处安排返回正确地址,然后再RET

下面是正确代码。

00480B97 8F8424 78FDFF   POP  DWORD PTR SS:[ESP-288];;这句代码非常关键关键,把返回地址安排在正确位置

00480B9E  81C4 78FDFFFF   ADD ESP  ,  -288;恢复指令,为什么-284变成-288,因后面有RET,

00480BA4  C3   RET

执行RET指令有两个作用,一是返回,二是会ESP+4,为了确保返回后ESP和不调用子程序时是一样的数值就需要这样“校正”。

以上是子程序的“开口”问题,子程序代码应该是这个样子或者说实现这样的功能:

响应鼠标单击事件,可用鼠标左键UP为标志(代码201),事件发生后要把地址0038A5C8一句代码

0038A5C8 /$ B9 0F000000 MOV ECX,0A 中的0A改为10

再次单击鼠标,把10改为0A。改代码,比较繁琐,初次接触感觉很复杂,习惯了就很简单。无非是调用API,

GetModuleHandleA,OpenProcessMemory,WriteProcessMemory,这些是改代码必须的,你想用“mov ”的方法改代码人

家Windows不批准,说你“非法操作”,这些API一般都不是现成的拿过来就用,得用GetProcAddress一一找到,把代码都列出

比较繁琐多。我把改好的GetHND.exe作为附件,有兴趣的可以用OD仔细研究。不足之处和不对的地方请高手指正!

不会排版,委屈大家了凑合着看吧!也不知那些“草木皆兵”的杀毒软件会不会报病毒。


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 6
支持
分享
最新回复 (2)
雪    币: 350
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hcg
2
感謝分享下載收藏!^^
學習了,受益匪淺
2013-4-4 11:09
0
雪    币: 6525
活跃值: (3428)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
3
不错,受益匪淺
2013-4-4 14:06
0
游客
登录 | 注册 方可回帖
返回
//