首页
社区
课程
招聘
[旧帖] [讨论]如何把程序的关闭按钮改为最小化! 0.00雪花
发表于: 2008-4-28 16:19 7389

[旧帖] [讨论]如何把程序的关闭按钮改为最小化! 0.00雪花

2008-4-28 16:19
7389
最近看了 《加密解密 2》  的 第9章 增加PE文件功能,有一部分是添加 Exit 菜单,并实现功能,上面提到 "程序是调用 PostQuitMessage(0),即WM_DESTROY 消息的事件代码退出的" 的确,调用该函数是可以退出 程序, 但我现在想实现 当点击 关闭按钮是执行最下化功能.总是搞不定,我甚至把  PostQuitMessage(0) 都 NOP 掉了,也把 调用 PostQuitMessage(0)  的代码 NOP掉, 但 点击关闭按钮 的时候还是能退出,请大侠指点.

我用的是 《加密解密 2》  的 第9章 增加PE文件功能  中提供的 pediy.exe

谢谢!!!

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

收藏
免费 0
支持
分享
最新回复 (4)
雪    币: 722
活跃值: (123)
能力值: ( LV12,RANK:300 )
在线值:
发帖
回帖
粉丝
2
你把PostQuitMessage(0)的代码nop掉了之后,你会发现,点关闭按钮时,桌面上的窗口的确没了,但是进程还在

因为WM_DESTROY实际上已经是程序退出前发出消息的最后一步了,程序响应WM_DESTROY之后就退出消息循环了。在WM_DESTROY消息之前,程序早已经把窗口区域清除掉了。

关闭按钮首先发送的,其实是WM_CLOSE消息,原来的窗口过程收到之后直接由DefWindowProc处理,完成一系列操作之后才发WM_DESTROY

也就是说,关闭窗口的操作,发送的是WM_CLOSE消息,你要拦的也应该是WM_CLOSE消息。

现在就来patch,借用原来的窗口过程:

00401161  |.  817D FC 11010>cmp     dword ptr [ebp-4], 111
00401168  |.  0F84 83000000 je      004011F1
0040116E      E9 BD000000   jmp     00401230                         ;  这里跳到DefWindowProc

在这里把0040116E处的代码改掉,让它跳到我们自己写的代码里。
在这个窗口过程代码下面,0040124C开始的空白位置刚好可以用来装我们自己添加的代码。

于是把0040116E处代码改掉:
0040116E  |. /E9 D9000000   jmp     0040124C                         ;  跳到我们自己添加的代码

我们自己添加的代码,如下:

0040124C  |> \837D FC 10    cmp     dword ptr [ebp-4], 10            ;  判断是否是WM_CLOSE消息
00401250  |.^ 75 DE         jnz     short 00401230                   ;  不是则还是交给DefWindowProc处理
00401252  |.  6A 06         push    6                                ; /ShowState = SW_MINIMIZE
00401254  |.  FF75 08       push    dword ptr [ebp+8]                ; |hWnd
00401257  |.  FF15 18204000 call    dword ptr [<&USER32.ShowWindow>] ; \ShowWindow
0040125D  \.^ EB CD         jmp     short 0040122C                   ;  跳回去return 0

判断是否是WM_CLOSE消息,如不是就仍跳回00401230交给DefWindowProc处理。
如果是WM_CLOSE消息,那就要自己把窗口最小化,调用ShowWindow实现,最后return 0
注意ShowWindow这个API原来就在程序输入表中,原程序中调用它的地方:
004010EB  |.  FF15 18204000 call    dword ptr [<&USER32.ShowWindow>] ; \ShowWindow

所以在这里直接copy这行汇编代码就可以了。

最后把修改复制到可执行文件。
保存之后的程序(见附件),运行后,按关闭按钮,就会最小化。
上传的附件:
2008-4-28 20:49
0
雪    币: 722
活跃值: (123)
能力值: ( LV12,RANK:300 )
在线值:
发帖
回帖
粉丝
3
OK,现在在前面的基础上进一步修改。

因为现在又有一个问题了,我们把WM_CLOSE消息的响应改成最小化之后,没有其他的键来关闭程序了,我们的程序要退出,只能结束进程了 怎么办?
不要忘了这个程序的目的,是要我们为File->Exit这个菜单项加功能,让它能够关闭程序。

光盘中附带源文件pediy.c已经告诉我们怎么改了,那部分被注释掉了:

        //  case IDM_APP_EXIT:
             //  SendMessage (hwnd, WM_CLOSE, 0, 0) ;
             //  return 0 ;

原来的意思是,只需要再向窗口发送WM_CLOSE消息就足够了。

慢着,现在不行了!因为这样做的话,就会再进入一次窗口过程,而这次因为我们已经把WM_CLOSE消息给挡住了,变成了最小化,所以还是不能关闭。
于是,我们只能换一种方式:直接把接收的消息改为WM_CLOSE消息之后,再自己调用DefWindowsProc处理。
OK,接下来patch。

首先找到case WM_COMMAND的代码,为其添加分支:

00401161  |.  817D FC 11010>cmp     dword ptr [ebp-4], 111           ;  是否WM_COMMAND
00401168  |.  0F84 83000000 je      004011F1
……
004011F1  |> \8B55 10       mov     edx, dword ptr [ebp+10]
004011F4  |.  81E2 FFFF0000 and     edx, 0FFFF
004011FA  |.  8955 F8       mov     dword ptr [ebp-8], edx
004011FD  |.  817D F8 539C0>cmp     dword ptr [ebp-8], 9C53          ;  About的菜单项的ID
00401204  |.  74 02         je      short 00401208
00401206  |.  EB 1A         jmp     short 00401222                   ;  其他的跳走
……
00401222  |> \EB 0C         jmp     short 00401230                   ;  跳去调用DefWindowProc

可以看到,在00401222这一句,又跳去调用DefWindowProc了,我们可以从这里修改,跳到我们自己的代码里。
与上次一样,在上次patch的代码后面,0040125F处开始写自己添加的代码,于是把00401222处代码改为:

00401222  |> \EB 3B         jmp     short 0040125F                   ;  跳到自己添加的代码

在写代码之前,我们要知道Exit菜单项的ID,用eXeScope查pediy_1.exe的资源,就可以知道Exit菜单项的ID是40005(十六进制9C45)。

于是,我们接着原代码的流程来,添加的代码:

0040125F  |> \817D F8 459C0>cmp     dword ptr [ebp-8], 9C45          ;  是否是Exit菜单项的ID
00401266  |.^ 75 C8         jnz     short 00401230                   ;  不是则又交回DefWindowProc
00401268  |.  C745 0C 10000>mov     dword ptr [ebp+C], 10            ;  改MSG参数为WM_CLOSE
0040126F  |.  C745 10 00000>mov     dword ptr [ebp+10], 0            ;  改wparam为0
00401276  |.  C745 14 00000>mov     dword ptr [ebp+14], 0            ;  改lparam为0
0040127D  \.^ EB B1         jmp     short 00401230                   ;  跳回去让DefWindowProc处理

判断ID是否是Exit菜单项的,不是则交回DefWindowProc
是则自己修改MSG为WM_CLOSE,然后自己返回去调用DefWindowProc

可以看到,由于这样并没有用SendMessage,所以WM_CLOSE消息不会再走一次窗口过程,而是在这次就被处理了,所以不会被我们之前所添加的代码给拦住。

修改后的文件(见附件),除了点关闭按钮会最小化之后,点击Exit菜单项,就会正常关闭了。
上传的附件:
2008-4-28 21:34
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
真没想到,这位大侠肯花这么长时间回答小菜我的问题,谢谢啦!
这位大侠的热心让小菜我看到了希望,让我觉得继续坚持在看雪学习,会学到很多东西!谢谢!

看了三遍大侠的回答,有很多不懂的地方:

1)


这个问题我的确发现了,但当时没在意!
大侠在回答中提到  DefWindowProc  ,但我在看 加密解密 的时候 说上 说的是  WinProc
不知两者 有什么区别和联系!

2)大侠在在修改关闭按钮未最小化的时候是执行自己编写的代码!
我想问 既然原程序有响应 关闭按钮 事件的代码,也应该有响应 最小化按钮 事件的代码吧,
可不可以让程序在判断出如果是 点击了关闭按钮  就跳转到最小化按钮的事件代码(源程序中有的)!

3)要使程序退出可不可以用《加密解密 2》 第9章 增加PE文件功能 中提到的办法,直接调用 PostQuitMessage(0) 呢?
     这样调用,是不是 只是窗口没了,但是进程还在!
2008-4-29 09:51
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
各位再帮忙看一下呀!!!!!!!!!!!
2008-4-30 09:07
0
游客
登录 | 注册 方可回帖
返回
//