【文章标题】: 给记事本添加最小化到系统托盘的功能
【文章作者】: Suyana
【作者邮箱】: Suyasha@163.com
【作者QQ号】: 517949855(请注明来自看雪论坛)
【软件名称】: Notepad
【下载地址】: WinXP自带
【使用工具】: OD
【作者声明】: 我只是一只小菜鸟,失误之处难免,敬望诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
阅读之前应懂得的东东:![]()
在系统托盘加入图标需定义一NOTIFYICONDATAA结构,如下
NOTIFYICONDATAA STRUCT
cbSize DWORD ? ;长度,为58
hwnd DWORD ?
uID DWORD ? ;0
uFlags DWORD ? ;7
uCallbackMessage DWORD ? ;WM_USER+5=405
hIcon DWORD ?
szTip BYTE 64 dup (?) ;鼠标指向图标时显示的字符串
NOTIFYICONDATAA ENDS
该结构内容可用代码填充,但为节省代码,我直接写入数据段,该结构的hwnd和hIcon是可变的,其它都是不变的。
用WinHex在00030256处添加数据:
58000000 00000000 00000000 07000000
05040000 00000000 44495920504520666F72204E6F7465706164
保存就可以了。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
一些消息处理变量对应的汇编码:
uMsg = dword ptr [ebp+C]
wParam = dword ptr [ebp+10]
lParam = dword ptr [ebp+14]
______________________________________________________________________________________
步骤:
1.添加函数和数据
所用到的函数: LoadIcon,ShowWindow,Shell_NotifyIconA,SendMessage。其中没有Shell_NotifyIcon函数,手工添加。添加后的函数指针为:010130E4
数据的添加看上面
-------------------------------------------------------------------
2.写出程序伪代码:
---------------------------------------------------------------代码:.if uMsg == WM_SIZE ;WM_SIZE equ 5h
.if wParam==SIZE_MINIMIZED ;SIZE_MINIMIZED equ 1
push dword ptr [1008810] ;hWnd
pop dword ptr [ ? +4] ;NOTIFYICONDATAA第2项
push 2
push 01000000
call [10011FC] ;invoke LoadIconW,hInstance,2
mov dword ptr [ ? +14],eax ;NOTIFYICONDATAA第6项
invoke ShowWindow,hWnd,SW_HIDE ;SW_HIDE equ 0
invoke Shell_NotifyIcon,NIM_ADD,addr note
.endif
.elseif uMsg==WM_COMMAND ;WM_COMMAND equ 111h
.if lParam==0
mov eax,wParam
.if ax==3e8
invoke ShowWindow,hWnd,SW_RESTORE ;SW_RESTORE equ 9
invoke Shell_NotifyIcon,NIM_DELETE,addr note ;NIM_DELETE equ 2h
.endif
.endif
.elseif uMsg==WM_SHELLNOTIFY ;WM_SHELLNOTIFY equ 405h=400+5
.if wParam==0
.if lParam==WM_RBUTTONDOWN || lParam==WM_LBUTTONDBLCLK || WM_LBUTTONUP
invoke SendMessage,hWnd,WM_COMMAND,3e8,0
.endif
.endif
.endif
3.找出程序的消息处理地址
下断"RegisterClassExW",运行。中断在010041BA,看堆栈:
0006FDF8 0006FE00 \pWndClassEx = 0006FE00
0006FDFC 77D14B20 USER32.LoadCursorW
0006FE00 00000030
0006FE04 00000000
0006FE08 01003134 NOTEPAD.01003134 ;这就是消息处理函数的地址了
来到01003134:
.......
0100313D cmp esi, 1C ; Switch (cases 2..8001)
01003140 push edi
01003141 push 8
01003143 pop edx
01003144 ja 0100338B ; WM_COMMAND equ 111h > 1C,跳到0100338B
...
0100338B mov edi, [ebp+14] ;跳到这里
0100338E mov eax, esi
01003390 sub eax, 111
01003395 je 010035D0 ;是WM_COMMAND消息跳到010035D0,修改为je 01007D76
------------------------------------------------------------
4.WM_COMMAND消息处理代码:
A.01003395 je 010035D0 ; 修改为je 01007D76
B.在01007D76处写入:
---------------------------------------------------------------代码:pushad
cmp dword ptr [ebp+14],0
jnz short 01007DA2 ; 不为0则跳到 exit
mov eax,dword ptr [ebp+10]
cmp ax,3e8
jnz short 01007DA2 ; 不等则跳到 exit
push 01008430
push 2
call [10130E4] ; SHELL32.Shell_NotifyIconA
push 9
push dword ptr [1008810]
call [10011CC] ; USER32.ShowWindow
popad ; exit:(跳到这里)
jmp 010035D0
5.WM_SIZE消息处理代码:
A.把010031D8 je 01003223;改为jmp 01007DB0。查找方法同上。
B.在01007DB0输入:
--------------------------------------------------------------代码:
新增内容:
----------------------------
mov eax, [ebp+10] ; 取wParam
dec eax
test eax, eax ; 是否为1,SIZE_MINIMIZED
jne 010031DD ; 不是SIZE_MINIMIZED消息直接返回
----------------------------------
pushad
push dword ptr [1008810]
pop dword ptr [1008434]
push 2 ; /RsrcName = 2.
push 01000000 ; |hInst = 01000000
call [10011FC] ; \LoadIconW
mov [1008444], eax
push 0 ; /ShowState = SW_HIDE
push dword ptr [1008810] ; |hWnd = NULL
call [10011CC] ; \ShowWindow
push 01008430
push 0
call [10130E4] ; SHELL32.Shell_NotifyIconA
popad
je 01003223
dec eax
jnz 010031C6
jmp 010031DD
6.WM_SHELLNOTIFY(405)消息处理代码:
A.由于空间不够,所以新建一个节01014000。
B.把010033C8 sub eax, 7CE8 ; 改成sub eax, 0EB
010033CD je 010034EA ; 改成ja 01014000
C.在01014000(我新建的节)输入:
---------------------------------------------------------代码:dec eax
je short 01014013
sub eax, 7BFC
je 010034EA
jmp 010033D3
cmp dword ptr [ebp+10], 0
jnz 010033D3
cmp dword ptr [ebp+14], 201
jnz 010033D3
jmp short 01014050 ; jmp _send
cmp dword ptr [ebp+14], 203
jnz 010033D3
jmp short 01014050 ; jmp _send
cmp dword ptr [ebp+14], 204
jnz 010033D3
jmp short 01014050
nop
nop
nop
nop
nop
nop
nop
push 0 ; _send:
push 3E8
push 111
push dword ptr [1008810]
call [1001220] ; USER32.SendMessageW
jmp 010033D3
7.保存就可以了,等着看运行结果吧。写代码一定要细心、失败了也不要灰心。偶可以试了n次才成功滴!
建议为OllyDbg装个NonaWrite的插件,这样比较方便。
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
----------------
文章写于2007-7-24