【文章标题】: 为程序添加右键快捷菜单
【文章作者】: laomms
【软件名称】: 附件下载
【操作平台】: winxp
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
WINRAR、FLASHGET等的右键快捷菜单很让人羡慕,它是通过Windows Shell扩展编程实现的,所谓的Shell扩展就是添加某种功能到Windows Shell的COM对象,然后通过注册COM控件在注册表中增加或删除相关键值。如果打开FLASHGET会发现目录有个上下文菜单扩展控件Jccatch.dll,通过注册该DLL实现右键菜单关联。本篇文章通过DIY为程序添加右键关联菜单。
我们就拿看雪大哥的pediy.EXE来做实验,要实现下图的功能:
一、编写COM控件。
首先我们需要写一个上下文菜单扩展控件控件供程序调用,网上有很多的相关代码,我找了个DELPHI的,稍微修改了一下,源码看附件,名称是contextmenu.dll,跟其它的COM控件一样,也有四个输出函数:DllGetClassObject, DllCanUnloadNow, DllRegisterServer, DllUnregisterServer。我们想实现按下“添加右键关联”时调用DllRegisterServer注册控件,按下“取消右键关联”时调用DllUnregisterServer取消注册。
二、为程序添加DLL链接。
接下来我们要做的就是将DLL引入到程序中,可以利用Loadlibrary函数和GetProcessAddress函数相结合,然后获取需要的函数的地址,也可以用LOADPE、IIDKING等工具加载,类似的文章已经很多了。我选择用IIDKing2.01。用IIDKing打开PEDIY.EXE,选择contextmenu.dll,IIDKing自动显示了DLL的所有输出函数,选中后添加,输入表中便已经有了contextmenu.dll。我们用LOADPE载入PEDIY.EXE,看看输入表中contextmenu.dll各函数的THUNKRVA值
DllRegisterServer为00005080,DllUnregisterServer为005084,那调用时就可以用基地址+THUNKRVA值的方法(记住勾选始终查看FIRSTTHUNK值)。
CALL DWORD PTR DS:[405080]调用DllRegisterServer
CALL DWORD PTR DS:[405084]调用DllUnregisterServer
三、为程序添加菜单项目
我们先用Resource Hacker为程序添加两个子菜单:
已知“ABOUT MENUDEMO”的菜单ID为40019(9C53H),再设置“添加右键关联”为40020(9C54H),“取消右键关联”40021(9C55H)。
由于原程序的关于的窗口是引用MessageBox消息框的,所以弹出的对话框信息我们就直接引用原来的MessageBoxA。
四、添加响应代码。
简单讲一下程序是如何处理菜单响应的:当你按下菜单执行相应的命令后,CreateDialogBoxParamA会调用窗口回调函数来处理,即把包含菜单命令的信息作为参数送给窗口回调函数,有时候是CreateWindowsEx或者MessageBoxA,因为一般界面中菜单或按钮有多个,所以代码组合一般都是这样:
cmp eax,xxxx(菜单id) ;比较一下是不是这个菜单命令
jz label1 ;如果是就转到这个菜单的响应函数
jmp label2 ;如果不是就对比是否为下一个菜单
……
Label2:
cmp eax,xxx2(菜单id2) ;比较一下是不是这个菜单
jz xxxxxxxx2 ;如果是就转到这个菜单的响应函数
jmp label3 ;不是继续判断下一个
查看PEDIY.EXE的输入表,知道关于的菜单响应函数是MessageBoxA,所以我们在OD中对MessageBoxA下断,F9运行程序后,按下ABOUT MENUDEMO,程序就被断下了。我们向上看,很容易看到菜单ID对比的地方:
004011FA |. 8955 F8 MOV DWORD PTR SS:[EBP-8],EDX
004011FD |. 817D F8 539C0>CMP DWORD PTR SS:[EBP-8],9C53 ; 是不是关于对话框的ID
00401204 |. /74 02 JE SHORT 00401208 ; 更改这里的代码,跳到下面执行
00401206 |> EB 1A JMP SHORT 00401222
00401208 |> 6A 40 PUSH 40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
0040120A |. 68 00304000 PUSH 00403000 ; |Title = "pediy"
0040120F |. 68 44304000 PUSH 00403044 ; |Text = "逆向分析技术
(c) 段钢, 2002"
00401214 |. 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8] ; |
00401217 |. 50 PUSH EAX ; |hOwner
00401218 |. FF15 44204000 CALL DWORD PTR DS:[<&USER32.MessageBoxA>>; \MessageBoxA
0040121E |. 33C0 XOR EAX,EAX
我们需要对00401204处的代码进行更改,以便它跳到我们添加的其它菜单的ID对比,并执行相应的响应事件。找到空余的地方00401250处开始修改:
00401204 |. /74 02 JE SHORT 00401208 ; 更改这里的代码,跳到下面执行,改为:
00401204 |. EB 4A JMP SHORT 00401250
00401250 |>^\74 B6 JE SHORT 00401208 ; 如果是关于对话框的ID,跳回到上面的对话框调用处
00401252 |. 817D F8 549C0>CMP DWORD PTR SS:[EBP-8],9C54 ; 如果不是,则判断不是添加右键关联的ID
00401259 |. 74 15 JE SHORT 00401270 ; 如果是,就跳到401270处处理相关信息
0040125B |. 817D F8 559C0>CMP DWORD PTR SS:[EBP-8],9C55 ; 如果不是,判断不是取消右键关联的ID
00401262 74 1C JE SHORT 00401295 ; 如果是,就跳到401295处处理相关信息
00401264 |.^ EB A0 JMP SHORT 00401206 ; 跳回原来的地方
00401266 | 00 DB 00
00401267 | 00 DB 00
00401270 60 PUSHAD ; 保护现场
00401271 FF75 08 PUSH DWORD PTR SS:[EBP+8] ; 压入添加右键关联的ID
00401274 FF15 80504000 CALL DWORD PTR DS:[405080] ; 调用contextm.Dll的DLLRegisterServer函数
0040127A 6A 40 PUSH 40 ; 对话框风格
0040127C 68 BA124000 PUSH 004012BA ; 对话框标题“关于”,写在了4012BA处
00401281 68 C5124000 PUSH 004012C5 ; 对话框内容:已关联菜单,在4012C5处
00401286 6A 00 PUSH 0 ; 对话框句柄
00401288 FF15 44204000 CALL DWORD PTR DS:[402044] ; 呼叫MessageBoxA函数
0040128E 61 POPAD ; 恢复现场
0040128F |.^ EB B5 JMP SHORT pediy.00401246 ; 跳回到正常流程
00401291 00 DB 00
00401292 00 DB 00
0040127E 90 NOP
0040127F 90 NOP
00401295 |> \60 PUSHAD ; 保护现场
00401296 |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; 压入取消右键关联的ID
00401299 |. FF15 84504000 CALL DWORD PTR DS:[405084] ; 调用contextm.Dll的DllUnregisterServer函数
0040129F |. 6A 40 PUSH 40 ; 对话框风格
004012A1 |. 68 BA124000 PUSH pediy.004012BA ; 对话框标题“关于”,写在了4012BA处
004012A6 |. 68 D1124000 PUSH pediy.004012D1 ; 对话框内容:已取消关联,在4012D1处
004012AB |. 6A 00 PUSH 0 ; 对话框句柄
004012AD |. FF15 44204000 CALL DWORD PTR DS:[402044] ; 呼叫MessageBoxA函数
004012B3 |. 60 POPAD ; 恢复现场
004012B4 ^ EB 90 JMP SHORT 00401246 ; 跳回到正常流程
00401291 00 DB 00
00401292 00 DB 00
004012BA CC INT3 ; ASCII:关于
004012BB ^ E1 CA LOOPDE SHORT 00401287
004012BD BE 00000000 MOV ESI,0
004012C2 00 DB 00
004012C3 00 DB 00
004012C4 00 DB 00
004012C5 D2D1 RCL CL,CL ; ASCII:已关联菜单
004012C7 B9 D8C1AAB2 MOV ECX,B2AAC1D8
004012CC CB RETF ; 远距返回
004012CD B5 A5 MOV CH,0A5
004012CF 00 DB 00
004012D0 00 DB 00
004012D1 D2D1 RCL CL,CL ; ASCII:已取消关联
004012D3 C8 A1CFFB ENTER 0CFA1,0FB
004012D7 B9 D8C1AA00 MOV ECX,0AAC1D8
004012DC 00 DB 00
打好补丁后另存为一个可执行文件,这时打开这个文件,按下“添加右键关联”,程序并在系统中注册了contextmenu.dll,并弹出对话框提示已关联菜单,按下“取消右键关联”则反注册DLL控件。可以在任意文件上右击,菜单中已经出现了“打开PEDIY”选项。当然直接注册DLL控件也能实现这样的功能,或者直接修改注册表键值也能达到效果。
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2006年08月17日 8:56:19