【文章标题】: 给记事本添加最小化到系统托盘的功能
【文章作者】: 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