·汉化新世纪 ·汉化新世纪论坛 ·百家争鸣 ·论坛集萃 ·汉化问答 ·软件介绍
文章首页 >> 汉化教学 >> 编程知识 >> 用 OD 给 EXE 文件添加一个对话框初探    Creative Commons License,创作共用协议(中文版)  署名 非商业性使用 禁止演绎

用 OD 给 EXE 文件添加一个对话框初探

作者: CxLrb 来源:一蓑烟雨 时间:2006-07-02 点击:15279

【文章标题】: 用OD给exe文件添加一个对话框初探
【文章作者】: CxLrb
【作者邮箱】: cxlrb@yahoo.com.cn
【作者主页】: http://unpack.blog.sohu.com/
【作者QQ号】: 21252130
【软件名称】: Pe_optimizer1.4汉化版by.CxLrb
【下载地址】: 自己搜索下载
【使用工具】: OD,HexDecChar,XN Resource Editor
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
     也许你正想者diy一个可执行文件,给一个汉化好的文件加上自己的对话框,或者直接加上帮助文本,或者显示破解
  组织信息。总之是为一个exe文件添加一个对话框,功能类似关于窗口。在此举一个例子供大家参考,实际没什么意义,
  但仅仅是出于兴趣和技术探讨,给大家分享我的成功喜悦!
      我们以Pe_optimizer1.4 (以下简称PO)这个小程序为例来学习:
      1.预备知识----对话框响应原理:
  当我们按下界面上的一个菜单或者一个按钮时,DialogBoxParamA会调用窗口回调函数来处理,即把包含菜单命令
  的信息作为参数送给窗口回调函数,因为一般界面中菜单或按钮有多个,所以很明显会有下面的类型的代码:
  
  cmp     ebx, xxxx1                       比较按下的按钮ID是否等于xxxx1
  jnz     short xxxxxxxx1                  如果不是,跳过继续判断,xxxxxxxx1为下一个比较的地址
  call    xxxxxxxx1                        如果是,调用该按钮响应的操作
  cmp     ebx, xxxx2
  jnz     short xxxxxxxx2
  call    xxxxxxxx2
  .....................
  
  或者
  cmp eax,xxxx1                             比较点击的菜单ID是否等于xxxx1
  jz xxxxxxxx1                              如果是,调用该按钮响应的操作
  cmp eax,xxxx2                             不是,继续判断
  jz xxxxxxxx2                              
  ...................
  
  或者
  cmp ax,xxxx1                              比较点击的菜单ID是否等于xxxx1
  jz xxxxxxxx1                              如果是,调用该按钮响应的操作
  cmp ax,xxxx2                              不是,继续判断
  jz xxxxxxxx2                              
  ...................
  
  也许还有其他形式,但总会类似以上列举的几种。
  本文的例子就是第一种情况。
  
  2. 添加资源按钮和对话框资源
  我们用XN Resource Editor 3.0 来打开,然后在主界面对话框上添加一个按钮,ID改为505 (16进制1F9);
  然后再添加一个对话框,将对话框的资源名(其实就是ID)称改为103 (16进制67),再在103对话框上添加
  一个按钮,ID与关于对话框中关闭的ID (即505)相同即可。最后保存关闭。
   运行程序看看,已经出现添加的按钮,但点击不会出现我们添加的对话框,因为还没有响应代码。
  
  3. 添加响应代码。
  
  我们用OD载入PO,右键-》查找-》所有模块间的调用,在最后几行我们看到两了DialogBoxParamA这个函数
  找到的模块间的调用
  地址       反汇编                                    目标
  0040654E   call    <jmp.&GDI32.CreateFontA>          GDI32.CreateFontA
  00406567   call    <jmp.&USER32.SendDlgItemMessageA  USER32.SendDlgItemMessageA
  004065D1   call    <jmp.&USER32.SetDlgItemTextA>     USER32.SetDlgItemTextA
  00406610   call    <jmp.&USER32.EndDialog>           USER32.EndDialog
  00406634   call    <jmp.&KERNEL32.ExitProcess>       kernel32.ExitProcess
  00406665   call    <jmp.&USER32.EndDialog>           USER32.EndDialog
  004066D7   call    <jmp.&USER32.DialogBoxParamA>     USER32.DialogBoxParamA
  0040675C   push    ebp                               (初始 CPU 选择)
  004067A1   call    <jmp.&USER32.DialogBoxParamA>     USER32.DialogBoxParamA
  
  双击进入第一个看看,到这里:
  004066D7    E8 5CDFFFFF     call    <jmp.&USER32.DialogBoxParamA>
  004066DC    EB 14           jmp     short Pe_optim.004066F2
  004066DE    8B45 08         mov     eax, [ebp+8]
  004066E1    A3 E0844000     mov     [4084E0], eax
  004066E6    E8 F5FDFFFF     call    Pe_optim.004064E0
  004066EB    EB 05           jmp     short Pe_optim.004066F2
  004066ED    E8 16FFFFFF     call    Pe_optim.00406608
  
  往上翻翻,目标出现了
  00406695    81FB F8010000   cmp     ebx, 1F8                             典型的ID对比
  0040669B    75 05           jnz     short Pe_optim.004066A2                ID不正确则执行下一比较
  0040669D    E8 66FFFFFF     call    Pe_optim.00406608                    ID就转到 00406608 执行响应操作
  004066A2    81FB F6010000   cmp     ebx, 1F6                             第二个ID对比
  004066A8    75 05           jnz     short Pe_optim.004066AF
  004066AA    E8 89FCFFFF     call    Pe_optim.00406338
  004066AF    81FB F5010000   cmp     ebx, 1F5
  004066B5    75 05           jnz     short Pe_optim.004066BC
  004066B7    E8 C0ECFFFF     call    Pe_optim.0040537C
  004066BC    81FB F7010000   cmp     ebx, 1F7                        
  004066C2    75 2E           jnz     short Pe_optim.004066F2  
  
  我们用 资源编辑软件打开 PO,看看各按钮的ID,关于按钮ID为503,我们再看这段代码:
  
  004066BC    81FB F7010000   cmp     ebx, 1F7                          1F7是10进制503,正好是关于按钮的ID
  004066C2    75 2E           jnz     short Pe_optim.004066F2              如果ID不是503,跳转到004066f2
  004066C4    6A 00           push    0                                  以下就是关于对话框的响应代码
  004066C6    68 3C664000     push    Pe_optim.0040663C
  004066CB    8B45 08         mov     eax, [ebp+8]
  004066CE    50              push    eax
  004066CF    6A 66           push    66                                66是关于对话框的ID,10进制102
  004066D1    A1 DC844000     mov     eax, [4084DC]
  004066D6    50              push    eax
  004066D7    E8 5CDFFFFF     call    <jmp.&USER32.DialogBoxParamA>
  004066DC    EB 14           jmp     short Pe_optim.004066F2
  004066DE    8B45 08         mov     eax, [ebp+8]
  004066E1    A3 E0844000     mov     [4084E0], eax
  004066E6    E8 F5FDFFFF     call    Pe_optim.004064E0
  004066EB    EB 05           jmp     short Pe_optim.004066F2
  004066ED    E8 16FFFFFF     call    Pe_optim.00406608
  004066F2    8BC6            mov     eax, esi
  004066F4    5E              pop     esi
  004066F5    5B              pop     ebx
  004066F6    5D              pop     ebp
  004066F7    C2 1000         retn    10
  …………………………………
  
  我们就从这里下手,找一段空间,添加一段类似以上这段代码,把
  004066BC    81FB F7010000   cmp     ebx, 1F7
  中的1F7 改为你添加的按钮的ID,比如我们添加的按钮ID为1F9,即505,把
  004066CF    6A 66       push    66  
  这句中的66改为你添加的对话框的资源ID,比如我们添加的为67,即103.
  其他更高深的代码本人就不能企及了,所以就直接仿造关于窗口。
  因此,本人所提到的方法不具有普遍的通用性,还希望抛砖引玉,高人指点,写出一些通用代码给我等菜鸟参考。
  接下来就是添加代码了
  
  我们首先找一处空间,文件末端有很多,所以就用那里的,选择一个比较好记忆的地址,如:0040B333,然后我们将上面
  比较的代码改成下面这样:
  00406693   /75 5D           jnz     short Pe_optim.004066F2
  00406695   |81FB F8010000   cmp     ebx, 1F8
  0040669B   |75 05           jnz     short Pe_optim.004066A2
  0040669D   |E8 66FFFFFF     call    Pe_optim.00406608
  004066A2   |E9 8C4C0000     jmp     Pe_optim.0040B333
  004066A7   |90              nop
  004066A8   |90              nop
  004066A9   |90              nop
  004066AA   |90              nop
  004066AB   |90              nop
  004066AC   |90              nop
  004066AD   |90              nop
  004066AE   |90              nop
  004066AF   |81FB F5010000   cmp     ebx, 1F5
  004066B5   |75 05           jnz     short Pe_optim.004066BC
  004066B7   |E8 C0ECFFFF     call    Pe_optim.0040537C
  004066BC   |81FB F7010000   cmp     ebx, 1F7
  004066C2   |75 2E           jnz     short Pe_optim.004066F2
  
  即从
  004066A2    81FB F6010000   cmp     ebx, 1F6     
  处直接跳转  0040B333,然后再把这段比较代码加上去即可,其他两句先nop掉。
  
  我们再 0040B333 处加上以下代码:
  0040B333    81FB F6010000   cmp     ebx, 1F6                     把上面nop掉的代码补回
  0040B339    75 05           jnz     short Pe_optim.0040B340          0040B340是我们新增的比较的地址
  0040B33B    E8 F8AFFFFF     call    Pe_optim.00406338             这一句不变
  0040B340    81FB F9010000   cmp     ebx, 1F9                     1F9这是我们添加的按钮的ID
  0040B346  ^ 0F85 63B3FFFF   jnz     Pe_optim.004066AF            注1
  0040B34C    6A 00           push    0
  0040B34E    68 3C664000     push    Pe_optim.0040663C
  0040B353    8B45 08         mov     eax, [ebp+8]
  0040B356    50              push    eax
  0040B357    6A 67           push    67                          67是我们添加的对话框的ID
  0040B359    A1 DC844000     mov     eax, [4084DC]
  0040B35E    50              push    eax
  0040B35F    E8 D492FFFF     call    <jmp.&USER32.DialogBoxParamA>
  0040B364    EB 14           jmp     short Pe_optim.0040B37A
  0040B366    8B45 08         mov     eax, [ebp+8]
  0040B369    A3 E0844000     mov     [4084E0], eax
  0040B36E    E8 6DB1FFFF     call    Pe_optim.004064E0
  0040B373    EB 05           jmp     short Pe_optim.0040B37A
  0040B375    E8 8EB2FFFF     call    Pe_optim.00406608
  0040B37A    8BC6            mov     eax, esi
  0040B37C    5E              pop     esi
  0040B37D    5B              pop     ebx
  0040B37E    5D              pop     ebp
  
  注1:0040B346  ^ 0F85 63B3FFFF   jnz     Pe_optim.004066AF  这一句要掉转到下一个比较
  004066AF   |81FB F5010000   cmp     ebx, 1F5
  
  然后就是保存代码,测试程序,终于,我们添加的对话框显示出来了。
  没什么技术含量,请不要转载。
  
--------------------------------------------------------------------------------
【经验总结】
  只是尝试用一种另类的方法给exe文件加一个对话框,没有什么技术含量,希望那位高手能做一个全自动的工具,那才是我 等所期待的。
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于一蓑烟雨技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2006年06月08日 16:18:37


做一些改进,将最后一段代码改为以下的,通用性及独立性增强了一些。
0040B333 81FB F6010000 cmp ebx, 1F6
0040B339 75 05 jnz short Pe_optim.0040B340
0040B33B E8 F8AFFFFF call Pe_optim.00406338
0040B340 81FB F9010000 cmp ebx, 1F9
0040B346 ^ 0F85 63B3FFFF jnz Pe_optim.004066AF
0040B34C 6A 00 push 0
0040B34E 68 6EB34000 push Pe_optim.0040B36E ---------响应关闭、最大化、最小化
0040B353 8B45 08 mov eax, [ebp+8]
0040B356 50 push eax
0040B357 6A 67 push 67
0040B359 A1 DC844000 mov eax, [4084DC]
0040B35E 50 push eax
0040B35F E8 D492FFFF call <jmp.&USER32.DialogBoxParamA>
0040B364 8BC6 mov eax, esi
0040B366 5E pop esi
0040B367 5B pop ebx
0040B368 5D pop ebp
0040B369 C2 1000 retn 10
0040B36C 0000 add [eax], al------------无用代码
0040B36E 55 push ebp --------------从这里到代码结束,完成对话框的关闭、最大化、最小化响应功能
0040B36F 8BEC mov ebp, esp
0040B371 53 push ebx
0040B372 8B45 0C mov eax, [ebp+C]
0040B375 33DB xor ebx, ebx
0040B377 83F8 02 cmp eax, 2
0040B37A 74 0C je short Pe_optim.0040B388
0040B37C 83F8 10 cmp eax, 10
0040B37F 74 07 je short Pe_optim.0040B388
0040B381 3D 11010000 cmp eax, 111
0040B386 75 0B jnz short Pe_optim.0040B393
0040B388 6A 00 push 0
0040B38A 8B45 08 mov eax, [ebp+8]
0040B38D 50 push eax
0040B38E E8 AD92FFFF call <jmp.&USER32.EndDialog>
0040B393 8BC3 mov eax, ebx
0040B395 5B pop ebx
0040B396 5D pop ebp
0040B397 C2 1000 retn 10
增加已个添加资源的动画:点击下载


再次优化:去了几行不大相关的响应代码
所有代码基本与关于窗口没有关系,以下代码可以独立完成打开和关闭对话框操作。
0040B333 81FB F6010000 cmp ebx, 1F6
0040B339 75 05 jnz short Pe_optim.0040B340
0040B33B E8 F8AFFFFF call Pe_optim.00406338
0040B340 81FB F9010000 cmp ebx, 1F9
0040B346 ^ 0F85 63B3FFFF jnz Pe_optim.004066AF
0040B34C 6A 00 push 0
0040B34E 68 6EB34000 push Pe_optim.0040B36E ------调用关闭、最大化、最小化响应代码:以下红色部分
0040B353 8B45 08 mov eax, [ebp+8]
0040B356 50 push eax
0040B357 6A 67 push 67
0040B359 A1 DC844000 mov eax, [4084DC] ----4084DC 可以是任意一个未占用的地址
0040B35E 50 push eax
0040B35F E8 D492FFFF call <jmp.&USER32.DialogBoxParamA>
0040B364 8BC6 mov eax, esi
0040B366 5E pop esi
0040B367 5B pop ebx
0040B368 5D pop ebp
0040B369 C2 1000 retn 10
0040B36C 0000 add [eax], al ------------无用代码,区隔一下
0040B36E 55 push ebp
0040B36F 8BEC mov ebp, esp
0040B371 53 push ebx
0040B372 8B45 0C mov eax, [ebp+C]
0040B375 33DB xor ebx, ebx
0040B377 3D 11010000 cmp eax, 111
0040B37C 75 0B jnz short Pe_optim.0040B389
0040B37E 6A 00 push 0
0040B380 8B45 08 mov eax, [ebp+8]
0040B383 50 push eax
0040B384 E8 B792FFFF call <jmp.&USER32.EndDialog>
0040B389 8BC3 mov eax, ebx
0040B38B 5B pop ebx
0040B38C 5D pop ebp
0040B38D C2 1000 retn 10


其中
call <jmp.&USER32.DialogBoxParamA>
call <jmp.&USER32.EndDialog>
这两个函数,一般的程序都会有,在 所有模块间的调用 中可找到,直接借用即可。


雅枫
其实我以前的那篇加对话框的文章也是类似的,只不过我利用了原软件关于对话框的响应函数.那样更简单一些.至于响应函数,我也优化了个版本,似乎更简洁一些smile.gif
. 8B4424 08 MOV EAX,DWORD PTR SS:[ESP+8]
. 3D 11010000 CMP EAX,111
. 75 07 JNZ SHORT uselib.00401039
. 837C24 0C 01 CMP DWORD PTR SS:[ESP+C],1
. 74 05 JE SHORT uselib.0040103E
> 83F8 10 CMP EAX,10
. 75 0B JNZ SHORT uselib.00401049
> 6A 00 PUSH 0
. FF7424 08 PUSH DWORD PTR SS:[ESP+8]
. E8 11000000 CALL <JMP.&user32.EndDialog>
> 33C0 XOR EAX,EAX
. C2 1000 RETN 10
在你的功能基础上还加了个id是1的按钮代码^^

如果不要按钮了代码就是:
8B4424 08 MOV EAX,DWORD PTR SS:[ESP+8]
83F8 10 CMP EAX,10
75 0B JNZ SHORT uselib.0040103B
6A 00 PUSH 0
FF7424 08 PUSH DWORD PTR SS:[ESP+8]
E8 11000000 CALL <JMP.&user32.EndDialog>
33C0 XOR EAX,EAX
C2 1000 RETN 10



还有,就是你的调用DialogBoxParam函数的代码也有些冗长不就是那5个参数么
push 0
push [Dlg] ;响应函数地址
push 0
push 101 ;对话框ID
push 400000h
call DialogBoxParam

这种代码我一般是先用ASM写,然后参考反汇编代码,下面就是我最终的实验代码(MASM汇编通过):
.386
.model flat, stdcall ;32 bit memory model
option casemap :none ;case sensitive

include user32.inc
includelib user32.lib
.code

start:
push 0
push [Dlg]
push 0
push 101
push 400000h
call DialogBoxParam
ret 0
Dlg: cmp dword ptr [esp+8],10h
jne a1
invoke EndDialog,dword ptr [esp+8],0
a1: xor eax,eax
ret 16
end start



CxLrb
试了一下效果,不错,但是出现一个问题,创建的对话框看不到背景,也看不到边框,只有一个ID为1的关闭按钮,如果添加了其他控件是可以看到的。

0040B333 81FB F6010000 cmp ebx, 1F6
0040B339 75 05 jnz short Pe_optim.0040B340
0040B33B E8 F8AFFFFF call Pe_optim.00406338
0040B340 81FB F9010000 cmp ebx, 1F9
0040B346 ^ 0F85 63B3FFFF jnz Pe_optim.004066AF
0040B34C 6A 00 push 0
0040B34E 68 84B34000 push Pe_optim.0040B384
0040B353 8B45 08 mov eax, [ebp+8]
0040B356 50 push eax
0040B357 6A 67 push 67
0040B359 A1 DC844000 mov eax, [4084DC]
0040B35E 50 push eax
0040B35F E8 D492FFFF call <jmp.&USER32.DialogBoxParamA>
0040B364 EB 14 jmp short Pe_optim.0040B37A
0040B366 8B45 08 mov eax, [ebp+8]
0040B369 A3 E0844000 mov [4084E0], eax
0040B36E E8 6DB1FFFF call Pe_optim.004064E0
0040B373 EB 05 jmp short Pe_optim.0040B37A
0040B375 E8 8EB2FFFF call Pe_optim.00406608
0040B37A 8BC6 mov eax, esi
0040B37C 5E pop esi
0040B37D 5B pop ebx
0040B37E 5D pop ebp
0040B37F C2 1000 retn 10
0040B382 0000 add [eax], al
0040B384 8B4424 08 mov eax, [esp+8]
0040B388 3D 11010000 cmp eax, 111
0040B38D 75 19 jnz short Pe_optim.0040B3A8
0040B38F 837C24 0C 01 cmp dword ptr [esp+C], 1
0040B394 74 05 je short Pe_optim.0040B39B
0040B396 83F8 10 cmp eax, 10
0040B399 75 00 jnz short Pe_optim.0040B39B
0040B39B 6A 00 push 0
0040B39D FF7424 08 push dword ptr [esp+8]
0040B3A1 E8 9A92FFFF call <jmp.&USER32.EndDialog>
0040B3A6 33C0 xor eax, eax
0040B3A8 C2 1000 retn 10


雅枫

jnz short Pe_optim.0040B3A8

这句不对,应该跳到0040B396
你的用跟我的不一样把,仔细看看
函数必须返回0才成,那句XOR EAX,EAX就是这个作用
我的是
. 75 07 JNZ SHORT uselib.00401039
你的是
0040B38D 75 19 jnz short Pe_optim.0040B3A8
跳到最后了,估计连关闭按钮都不管用了

我改的一个例子
00400350 3D 75270000 CMP EAX,2775
00400355 75 05 JNZ SHORT AddMenu.0040035C
00400357 -E9 F60D0000 JMP AddMenu.00401152
0040035C 3D 76270000 CMP EAX,2776
00400361 -0F85 340E0000 JNZ AddMenu.0040119B
00400367 6A 00 PUSH 0
00400369 68 90034000 PUSH AddMenu.00400390
0040036E 6A 00 PUSH 0
00400370 68 E9030000 PUSH 3E9
00400375 68 00004000 PUSH AddMenu.00400000
0040037A E8 350E0000 CALL <JMP.&user32.DialogBoxParamA>
0040037F -E9 170E0000 JMP AddMenu.0040119B

00400390 8B4424 08 MOV EAX,DWORD PTR SS:[ESP+8]
00400394 3D 11010000 CMP EAX,111
00400399 75 07 JNZ SHORT AddMenu.004003A2
0040039B 837C24 0C 01 CMP DWORD PTR SS:[ESP+C],1
004003A0 74 05 JE SHORT AddMenu.004003A7
004003A2 83F8 10 CMP EAX,10
004003A5 75 0B JNZ SHORT AddMenu.004003B2
004003A7 6A 00 PUSH 0
004003A9 FF7424 08 PUSH DWORD PTR SS:[ESP+8]
004003AD E8 0E0E0000 CALL <JMP.&user32.EndDialog>
004003B2 33C0 XOR EAX,EAX
004003B4 C2 1000 RETN 10

示例下载

CxLrb
老兄这段代码应该是最经典的了,其他代码都理解了,希望老兄解释这一句,在此起什么作用,刚刚学asm,所以希望前辈多多指点:
00400375 68 00004000 PUSH AddMenu.00400000

根据雅枫前辈的指导,最终优化代码为:
对菜单的响应有点不太懂,不知能否和按钮的判断一起判断ID?

0040B346 ^ 0F85 63B3FFFF jnz Pe_optim.004066AF
0040B34C 6A 00 push 0
0040B34E 68 84B34000 push Pe_optim.0040B384
0040B353 8B45 08 mov eax, [ebp+8]
0040B356 50 push eax
0040B357 6A 67 push 67
0040B359 68 00004000 push Pe_optim.00400000 ; ASCII "MZP"
0040B35E E8 D592FFFF call <jmp.&USER32.DialogBoxParamA>
0040B363 ^ E9 47B3FFFF jmp Pe_optim.004066AF
...................

0040B384 8B4424 08 mov eax, [esp+8]
0040B388 3D 11010000 cmp eax, 111
0040B38D 75 17 jnz short Pe_optim.0040B3A6
0040B38F 837C24 0C 01 cmp dword ptr [esp+C], 1
0040B394 74 05 je short Pe_optim.0040B39B
0040B396 83F8 10 cmp eax, 10
0040B399 75 00 jnz short Pe_optim.0040B39B
0040B39B 6A 00 push 0
0040B39D FF7424 08 push dword ptr [esp+8]
0040B3A1 E8 9A92FFFF call <jmp.&USER32.EndDialog>
0040B3A6 33C0 xor eax, eax
0040B3A8 C2 1000 retn 10


雅枫

00400375 68 00004000 PUSH AddMenu.00400000

这句的作用是压入进程的句柄,也就是GetModuleHandle的返回值,由于一般EXE一般都载入到400000处,所以我直接用这个值代替了,其实这个对话框还有个瑕疵,就是相对于主对话框或者主窗口不是模态对话框,如果要模态,则必须在DialogBoxParamA的第三个参数应该是父窗口的句柄.还有,LZ最后的代码估计还是有一些问题,就是标题栏的关闭按钮应该失去响应了,
0040B388 3D 11010000 cmp eax, 111
0040B38D 75 17 jnz short Pe_optim.0040B3A6
这句的问题,应改为
jnz short Pe_optim.0040B396

给你段代码参考

Dlg: cmp dword ptr [esp+8],WM_COMMAND
jne a2
cmp dword ptr [esp+12],1 ;按钮ID
je a3
a2: cmp dword ptr [esp+8],WM_CLOSE
jne a1
a3: invoke EndDialog,dword ptr [esp+8],0
a1: xor eax,eax
ret 16


还有,大家都是兄弟,不要老是前辈啥的,怪不舒服的,我也就二十几岁,还没那么老,呵呵


CxLrb
多谢老兄指点,标题中的关闭按钮还可以,0040B38D 75 17 jnz short Pe_optim.0040B3A6
这一句是对的,如果改了,点击按钮便无反应;
称您前辈,只是对您的尊敬,没有指您老,希望不要见怪,当然大家都是兄弟,既然老兄不怪,那就直呼兄弟了,对您的指点很是感谢,Thanks!

我想像老兄那样从菜单调用关于对话框,不知道cmp eax ID,的代码应该放在何处?程序传上来了,老兄有时间就帮我看看。
示例文件

雅枫
呵呵,仔细看了看你的响应代码,发现还是有些问题的,(最明显的就是无论按钮ID是多少,对话框都会关闭)下边的是我调整后的。
0040B384   8B4424 08        MOV EAX,DWORD PTR SS:[ESP+8]  /////取出第二个参数,即uMsg
0040B388   3D 11010000      CMP EAX,111//////////////////比较是不是WM_COMMAND
0040B38D   75 07            JNZ SHORT Pe_optim.0040B396    //////如果不是WM_COMMAND,如果不是则转往0040B396
0040B38F   837C24 0C 01     CMP DWORD PTR SS:[ESP+C],1    //////如果ID是1
0040B394   74 05            JE SHORT Pe_optim.0040B39B    //////则执行EndDialog
0040B396   83F8 10          CMP EAX,10    ////////////////比较是不是WM_CLOSE,即标题栏退出按钮。
0040B399   75 0B            JNZ SHORT Pe_optim.0040B3A6////如果是WM_CLOSE,执行EndDialog
0040B39B   6A 00            PUSH 0
0040B39D   FF7424 08        PUSH DWORD PTR SS:[ESP+8]
0040B3A1   E8 9A92FFFF      CALL <JMP.&USER32.EndDialog>
0040B3A6   33C0             XOR EAX,EAX
0040B3A8   C2 1000          RETN 10

解释一下消息处理:
点击按钮或菜单后,消息循环会向窗口处理函数发送WM_COMMAND消息,消息的wParam则是按钮的id。消息处理函数的原型是
WndProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
即点击id为1的按钮后,uMsg是111h(WM_COMMAND),wParam中的值则为1。
点击标题栏的退出按钮后,发送的则是WM_CLOSE消息,即uMsg是10h(WM_CLOSE)
而你的响应代码是:
0040B384   8B4424 08        MOV EAX,DWORD PTR SS:[ESP+8]
0040B388   3D 11010000      CMP EAX,111///比较是不是WM_COMMAND
0040B38D   75 17            JNZ SHORT Pe_optim.0040B3A6///不是WM_COMMAND则直接退出消息处理
0040B38F   837C24 0C 01     CMP DWORD PTR SS:[ESP+C],1//////如果ID是1
0040B394   74 05            JE SHORT Pe_optim.0040B39B//////则执行EndDialog
0040B396   83F8 10          CMP EAX,10///id不是1执行这里
0040B399   75 00            JNZ SHORT Pe_optim.0040B39B///等于不等于10都执行EndDialog
0040B39B   6A 00            PUSH 0
0040B39D   FF7424 08        PUSH DWORD PTR SS:[ESP+8]
0040B3A1   E8 9A92FFFF      CALL <JMP.&USER32.EndDialog>
0040B3A6   33C0             XOR EAX,EAX
0040B3A8   C2 1000          RETN 10
也就是说,这段代码只要触发了WM_COMMAND消息,对话框都会退出,因为点击标题栏的退出按钮后,除了发送WM_CLOSE消息后还发送一个id为2的按钮消息(ID_CANCLE),所以你的代码也可以在点击标题栏的退出按钮后,也可以退出对话框。基于这个原理,这个响应代码还可以精简:把WM_CLOSE的判断去掉,把对话框按钮的id改成2即可,代码如下
Dlg:        cmp dword ptr [esp+8],111h
        jne a1
        cmp dword ptr [esp+12],2
        jne a1
a3:         invoke EndDialog,dword ptr [esp+8],0
a1:        xor        eax,eax
        ret 16
反汇编代码则为:
00401016   . 817C24 08 11010000    CMP DWORD PTR SS:[ESP+8],111
0040101E   . 75 12                 JNZ SHORT uselib.00401032
00401020   . 837C24 0C 02          CMP DWORD PTR SS:[ESP+C],2
00401025   . 75 0B                 JNZ SHORT uselib.00401032
00401027   . 6A 00                 PUSH 0    
00401029   . FF7424 08             PUSH DWORD PTR SS:[ESP+8]
0040102D   . E8 0C000000           CALL <JMP.&user32.EndDialog>
00401032   > 33C0                  XOR EAX,EAX
00401034   . C2 1000               RETN 10
这段代码除了可以相应退出标题栏关闭按钮外,还可以响应一个ID为2的按钮。

示例文件修改

汉化新世纪 责任编辑: 乾 .:|:. 标签(Tag): 调试 对话框

·上一篇: 3款字符串、16进制、PE地址转换处理工具 ·下一篇: PASSOLO 汉化时的一个处理 & 符号的小办法, 可能高手会使用宏来解决

· 版权申明: 本文引自《一蓑烟雨》,如有版权疑问请及时联系本站,以便本站处理。

· 转载申明: 本文引自《一蓑烟雨》[ 作者: CxLrb],如需转载请直接联系原始作者,并请注明原始出处。

相关文章                                                                                发表评论 打印此文 关闭窗口

| 设为首页 | 加入收藏 | 联系我们 | 友情链接
Creative Commons License,创作共用协议(中文版)  署名 非商业性使用 禁止演绎
本站内容,除转载或版权特别申明的内容外,皆遵守 创造共用协议中文版之“署名-非商业性使用-禁止演绎 2.5 中国大陆”条款
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 2.5 China License.
本网站内容源自汉化新世纪论坛的摘录和汉化新世纪成员的原创文章。
凡汉化新世纪论坛的文字皆默认为汉化新世纪与原作者共同拥有并授权发布。
如对本站发布文章有所异议请来信告知,我们将及时删除。
凡商业摘录本站文字请先与我们联系,本站将保留非授权商业发布的追究权利。
凡非商业摘录本站文字请明显注明出处和原作者,并不得改动,凡改动必先征求原作者同意。
苏ICP备05002283号