【文章标题】: pediy 打造专属的 Malware Defender
【文章作者】: FishSeeWater
【作者邮箱】: FishSeeWater@gmail.com
【软件名称】: Malware Defender
【下载地址】: 自己搜索下载
【使用工具】: ollyice ,lordPe,010Editor
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  Malware Defender 是一个主动防御软件,也就是HIPS。以下简称MD, 很早以前使用这个软件,给作者提过不少建议。
其中一个加入“暂停保护”的功能,却没有提供热键支持,最近心起,使用这个软件时,感觉太需要这个功能了,没办法只好自己动手解决了:).

  绝无恶意,作者莫怪~~:)
  最新版是2.7.2.0001
  
  下载安装后,把主程序拷贝出来,扔到IDA中直接加工。生成MAP文件,然后用OD载入开始分析。
  开始前我们先理一下思路:
       暂停保护的功能作者已经加入了(1,5,15,30,60,自定义 6项功能),
  只是需要在托盘用鼠标操作。我们只要找到这些消息的处理过程,用我们注册的热键来调用就OK了。
  
  具体分步如下:
           1。找到响应“暂停保护XX分钟”鼠标操作的消息处理例程
           2。找到MD中注册热键的例程,加入我们定义的新热键。
                        SHITF+CTRL+ALT+1......6来调用作者提供的6项功能。
           3。找到MD中反注册热键的例程,反注册我们的热键.
           4。找到MD中响应热键的消息处理例程,加入我们的热键处理代码,在这里调用1的入口
  首先进行一步:
  OD载入MD,
  在“暂停保护”选项处有个“自定义”选项,选这个功能会跳出一个对话框
  
  这时按“F12,Alt+F9”再点击确定,程序会断在下图中:
  
  返回后,
  
  我们可以看到,00490821 这一行,F7进
  

代码:
  00490683   /$ >push    ebp                                
  00490684   |. >mov     ebp, esp
  00490686   |. >push    ecx
  
  在00490683   上F2下断点,F9运行。这时确定一下这个CALL是不是停止保护的功能CALL 点“暂停保护1分钟”,程序顺利的断下,Ctrl+F9返回到 004907A2,这时我们可以看到已经找到想要的功能代码了。
  
代码:
  0049079B <>/$ >push    1                                    ;  stop_1_Minute
  0049079D   |. >call    MalwareD.00490683
  004907A2   |. >xor     eax, eax
  004907A4   \. >retn    10
  004907A7 <>/$ >push    5                                    ;  stop_5_Minute
  004907A9   |. >call    MalwareD.00490683
  004907AE   |. >xor     eax, eax
  004907B0   \. >retn    10
  004907B3 <>/$ >push    0A                                   ;  stop_15_Minute
  004907B5   |. >call    MalwareD.00490683
  004907BA   |. >xor     eax, eax
  004907BC   \. >retn    10
  004907BF <>/$ >push    1E                                   ;  Stop_30_Minute
  004907C1   |. >call    MalwareD.00490683
  004907C6   |. >xor     eax, eax
  004907C8   \. >retn    10
  004907CB <>/$ >push    3C                                   ;  Stop_60_Minute
  004907CD   |. >call    MalwareD.00490683
  004907D2   |. >xor     eax, eax
  004907D4   \. >retn    10
 ......省略一些
  
   第一步完成。
  小结:我们找到了6个CALL分别对应着暂停保护的6项功能,
  
代码:
  0049079B <>/$ >push    1                                     ;  stop_1_Minute
  004907A7 <>/$ >push    5                                     ;  stop_5_Minute
  004907B3 <>/$ >push    0A                                    ;  stop_15_Minute
  004907BF <>/$ >push    1E                                    ;  Stop_30_Minute
  004907CB <>/$ >push    3C                                    ;  Stop_60_Minute
  004907D7 <>/$ >mov     eax, <MalwareD.loc_581A60>            ;  StopCustomTime
  
  第二步:
  OD重新载入MD,下断点 bpx RegisterHotKey,F9运行程序。
  断在 0047BE0B
  
代码:
  0047BDF7   |. >test    ax, ax
  0047BDFA   |. >je      short <MalwareD.loc_47BE70>
  0047BDFC   |. >mov     ebx, [arg.2]
  0047BDFF   |. >movzx   ecx, di
  0047BE02   |. >push    ecx                            ; /Key
  0047BE03   |. >movzx   eax, ax                        ; |
  0047BE06   |. >push    eax                            ; |Modifiers
  0047BE07   |. >push    ebx                            ; |HotKeyID
  0047BE08   |. >push    dword ptr ds:[esi+4]           ; |hWnd
  0047BE0B   |. >call    dword ptr ds:[<&USER32.Registe>; \RegisterHotKey
  0047BE11   |. >test    eax, eax
  0047BE13   |. >jnz     short <MalwareD.loc_47BE83>
  
  Ctrl+F9返回两次(为什么是两次?因为我们需要找到高层的处理过程,理清程序的流程,至于细节,修改代码时再细看),我们可以看到这里就是MD的注册热键的流程了。
  其先反注册所有的热键(在47be9c处),然后再注册新的热键。(相关行我做了标注 :))
  
代码:
  0047BE8D <>/$ >mov     eax, <MalwareD.loc_580D22>     ;  _ProcessHotKey
  0047BE92   |. >call    <MalwareD.__EH_prolog>
  0047BE97   |. >push    ecx
  0047BE98   |. >push    ecx
  0047BE99   |. >push    esi
  0047BE9A   |. >mov     esi, ecx
  0047BE9C   |. >call    <MalwareD._UnAllHotKey>
  ...............
  0047BEBB   |. >lea     eax, [local.4]
  0047BEBE   |. >push    eax
  0047BEBF   |. >push    dword ptr ds:[<_HotKey_Ctrl_1>>
  0047BEC5   |. >mov     ecx, esi
  0047BEC7   |. >push    1
  0047BEC9   |. >push    offset <MalwareD._HotKey_1>
  0047BECE   |. >call    <MalwareD._RegHotKey>
  .............
  0047BF7F   |. >push    dword ptr ds:[<_HotKey_Ctrl_9>]
  0047BF85   |. >mov     ecx, esi
  0047BF87   |. >push    9
  0047BF89   |. >push    offset <MalwareD._HotKey_9>
  0047BF8E   |. >call    <MalwareD._RegHotKey>
  0047BF93      >mov     edi, dword ptr ss:[ebp-10]
  0047BF96      >cmp     dword ptr ds:[edi-8], 0
  0047BF9A   |. >je      short <MalwareD.loc_47BFE6>     ;这里判断是否注册成功,否则弹框提示
  ..........
  0047BFCE   |. >push    30                                    ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
  0047BFD0   |. >push    0                                     ; |Title = NULL
  0047BFD2   |. >push    [local.5]                             ; |Text
  0047BFD5   |. >push    dword ptr ds:[esi+4]                  ; |hOwner
  0047BFD8   |. >call    dword ptr ds:[<&USER32.MessageBoxW>]  ; \MessageBoxW
  0047BFDE   |. >lea     ecx, [local.5]
  
  OK 第二步完成。
  小结:我们找到了注册热键的位置.
  1.每个热键的注册流程如下:
  
代码:
  0047BF7B   |. >lea     eax, [local.4]                      
  0047BF7E   |. >push    eax               ;压入this
  0047BF7F   |. >push    dword ptr ds:[<_HotKey_Ctrl_9>];压入热键码,高位VK,低位fsModifiers
  0047BF85   |. >mov     ecx, esi
  0047BF87   |. >push    9               ;压入ID
  0047BF89   |. >push    offset <MalwareD._HotKey_9>  ;压入一个变量,用来保存ID的,在UnhotKey时需要用到这个变量
  0047BF8E   |. >call    <MalwareD._RegHotKey>           ;调用注册CALL
  
  2.
  
代码:
  0047BF8E   |. >call    <MalwareD._RegHotKey>这一行是最后一个热键的注册,从下一行0047BF93跳到我们的代码中注册新的热键。
  
  第三步:
  在上二步中,我们已经找到反注册的入口了,0047BE9C   |. >call    MalwareD.004628F9
  
代码:
  004628F9 <>/$ >push    esi                                   ;  _UnAllHotKey
  004628FA   |. >push    offset <MalwareD._HotKey_1>
  004628FF   |. >mov     esi, ecx
  00462901   |. >call    <MalwareD._UnregisterHotKey>
  00462906   |. >push    offset <MalwareD._HotKey_2>
  0046290B   |. >mov     ecx, esi
  0046290D   |. >call    <MalwareD._UnregisterHotKey>
  00462912   |. >push    offset <MalwareD._HotKey_3>
  00462917   |. >mov     ecx, esi
  .........
  00462955   |. >call    <MalwareD._UnregisterHotKey>
  0046295A   |. >push    offset <MalwareD._HotKey_9>
  0046295F      >mov     ecx, esi
  00462961      >call    <MalwareD._UnregisterHotKey>
  00462966   |. >pop     esi
  00462967   \. >retn
  
  直接小结:  用"压入一个变量,用来保存ID的,在UnhotKey"来调用UnRegisterHotKey.  我们将在 0046295F处修改代码跳到我们的代码处反注册热键.

  第四步:
    要找热键的消息入口,着实费了把劲,后来才发现一个好方法.  在MD的默认热键中有两个热键是开启与关闭保护的,当切换这两种状态时,状态栏的图标会变化,
  我们直接下断 bpx  SHELL32.Shell_NotifyIconW,然后 CTRL+SHIFT+ALT+F,直接就断下来了,
  按老思路,不断返回到高层调用者
  
代码:
  004A65F5 <>|> \B>mov     ecx, 312                                      ;  从这里我们可以看到 WM_HOTKEY 312
  004A65FA   |.  3>cmp     eax, ecx
  004A65FC   |.  7>jnz     short <MalwareD.loc_4A6617>
  ............
  004A660D   |.  E>call    MalwareD.0048F684                     ;这里肯定就是处理流程了
  004A6612   |.^ E>jmp     <MalwareD.loc_4A63DB>
  /////////////////////////////
  0048F684   /$  5>push    esi                                           ; 
  0048F685   |.  5>push    edi
  0048F686   |.  3>xor     edi, edi
  0048F688   |.  8>mov     esi, ecx
  0048F68A   |.  3>cmp     dword ptr ds:[<dword_5D4D58>], edi
  0048F690   |.  0>jnz     <MalwareD.loc_48F7EF>
  0048F696   |.  8>mov     eax, dword ptr ss:[esp+10]        ;这里将热键的ID传入eax,然后进行查找匹配的分支.
  0048F69A       3>xor     ecx, ecx
  0048F69C       4>inc     ecx
  0048F69D       3>cmp     eax, ecx
  0048F69F   |.  7>jnz     short <MalwareD.loc_48F6AD>
  0048F6A1   |.  8>mov     ecx, esi
  0048F6A3   |.  E>call    <MalwareD._ShowMainWindow>
  0048F6A8   |.  E>jmp     <MalwareD.loc_48F7EF>
  0048F6AD <>|>  3>cmp     dword ptr ds:[<_IsLocking***>], edi           ;  loc_48F6AD
  0048F6B3   |.  0>jnz     <MalwareD.loc_48F7EF>
  0048F6B9   |.  6>push    2
  0048F6BB   |.  5>pop     edx
  
  小结: 通过动态调试,我们可以知道 程序是根据 WM_HotKey 的 ID 来进行分支匹配的.在 0048F69A跳到我们的代码进行分支调用.
  
  
  至此,所需的所有必备条件已具备.下面开始进行patch代码和找空间写我们的代码.
  原以为很容易就能找到大片的空隙来写代码了,但经过测试发现,程序的.text段的空隙很小(为了这个问题可是PE头搞个差不多明白了:))
  
  
  没办法,只好增加区段了.正好利用所学,手动增加区段:
  整理一下思路:
  首先需要构建并增加一个段头,然后修改文件的NumberOfSections,SizeofImages,  根据lordPE的区段数据,我们构建的新区段头如下:
  
代码:
  typedef struct _IMAGE_SECTION_HEADER {
      BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];     ".FSW"
      union {
              DWORD   PhysicalAddress;                    00000800h //我们需要的大小
              DWORD   VirtualSize;
      } Misc;
      DWORD   VirtualAddress;    00264000h  // .rsrc 段的Voffset+Vsize后1000对齐
      DWORD   SizeOfRawData;    00000800h  // 磁盘文件对齐大小.
      DWORD   PointerToRawData;    0024F200h  //  .rsrc 段的Roffset+RSize后200对齐
      DWORD   PointerToRelocations;    00000000h
      DWORD   PointerToLinenumbers;  00000000h  
      WORD    NumberOfRelocations;    0000h  
      WORD    NumberOfLinenumbers;    0000h  
      DWORD   Characteristics;    E0000020h // 可读可写可执行+代码.
  } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
  
  将以上数值展开后如下:
  
代码:
  2E465357 00000000 00080000 00402600 00080000 00F22400 00000000  00000000  0000  0000  200000E0
  
  用十六进制工具将区段头写入exe文件
  
  然后修改
  NumberOfSections  4->5
  SizeofImages   (00264000h  +800h) 1000对齐=265000h
  
  然后用16进制编辑器在文件的24f200后插入800h的数据块 (插入数据时,发现这里竟然有数据,不知什么原因,请大牛指点).
  最后的效果如图:
  
  好了,有足够的空间了,下面我们就开始写代码了.
  需要Patch3个地方
      1. 响应热键的地方
      2.反注册热键的地方
      3.注册热键的地方
  先规划一下我们空间的使用:
      由于注册热键时,需要用到ID,fsModifiers,VK,   其中ID是一个DWORD变量,用来UnRegisterHotKey.
  fsModifiers,VK这两个合并成一个DWORD,用来注册热键(如 CTRL+SHIFT+ALT+1 就是 00070031 )
  我们要注册的6个热键转换过来就是
  00070031
  00070032
  00070033
  00070034
  00070035
  00070036
  这6个DWORD数据加上6个DOWRD变量共需要48个字节的空间.  这些数据就放在我们新开辟空间的起始位置: VA :664000 后面再跟 6个DWORD的变量. 
  先把这几个热键码写到程序中(十六进制编辑器搞定)注意字节序.
  ////////
  这样我们就把代码位置放在 664000h+40h的地方.
  开始处理"响应热键"的地方
  
代码:
  0048F684   /$ >push    esi
  0048F685   |. >push    edi
  0048F686   |. >xor     edi, edi
  0048F688   |. >mov     esi, ecx
  0048F68A   |. >cmp     dword ptr ds:[5D4D58], edi
  0048F690   |. >jnz     MalwareD.0048F7EF
  0048F696   |. >mov     eax, dword ptr ss:[esp+10]
  0048F69A      >xor     ecx, ecx                                         // 改成 jmp     MalwareD.00664040
  0048F69C      >inc     ecx
  0048F69D     >cmp     eax, ecx                                       // 会占用到这里,这三行代码将在我们的代码中实现
  0048F69F   |. >jnz     short MalwareD.0048F6AD
  0048F6A1   |. >mov     ecx, esi
  
  在00664040 处写代码处理相应的热键消息
  
代码:
  00589D80      >pushad
  00589D81      >cmp     dword ptr ds:[5D4A5C], edi
  00589D87      >jnz     short MalwareD.00589DA1
  00589D89      >cmp     dword ptr ds:[5D4A60], edi
  00589D8F      >jnz     short MalwareD.00589DA1
  00589D91      >cmp     dword ptr ds:[5D4A64], edi
  00589D97      >jnz     short MalwareD.00589DA1
  00589D99      >cmp     dword ptr ds:[5D4A68], edi
  00589D9F      >je      short MalwareD.00589DFE
  00589DA1      >cmp     eax, 101
  00589DA6      >jnz     short MalwareD.00589DAF
  00589DA8      >call    MalwareD.0049079B
  00589DAD      >jmp     short MalwareD.00589DF5
  00589DAF      >cmp     eax, 102
  00589DB4      >jnz     short MalwareD.00589DBD
  00589DB6      >call    MalwareD.004907A7
  00589DBB      >jmp     short MalwareD.00589DF5
  00589DBD      >cmp     eax, 103
  00589DC2      >jnz     short MalwareD.00589DCB
  00589DC4      >call    MalwareD.004907B3
  00589DC9      >jmp     short MalwareD.00589DF5
  00589DCB      >cmp     eax, 104
  00589DD0      >jnz     short MalwareD.00589DD9
  00589DD2      >call    MalwareD.004907BF
  00589DD7      >jmp     short MalwareD.00589DF5
  00589DD9      >cmp     eax, 105
  00589DDE      >jnz     short MalwareD.00589DE7
  00589DE0      >call    MalwareD.004907CB
  00589DE5      >jmp     short MalwareD.00589DF5
  00589DE7      >cmp     eax, 106
  00589DEC      >jnz     short MalwareD.00589DFE
  00589DEE      >call    MalwareD.004907D7
  00589DF3      >jmp     short MalwareD.00589DF5
  00589DF5      >sub     esp, 10                                         // 注意 这里,完全是为是平衡栈
  00589DF8      >popad
  00589DF9     ^>jmp     MalwareD.0048F7EF
  00589DFE      >popad
  00589DFF      >xor     ecx, ecx
  00589E01      >inc     ecx
  00589E02      >cmp     eax, ecx                                      //00589DFF-00589E02是实现原始代码.
  00589E04     ^>jmp     MalwareD.0048F69F
  
  ////////////////////////// OK响应热键的消息处理功能添加完成.
  下面开始反注册热键:
  
代码:
  0046294E   |. >push    MalwareD.005D4BB4
  00462953   |. >mov     ecx, esi
  00462955   |. >call    MalwareD.004628DD
  0046295A   |. >push    MalwareD.005D4BB8
  0046295F      >mov     ecx, esi    // 改 jmp     MalwareD.006640CD
  00462961      >call    MalwareD.004628DD  // 填充 2个 nop 同样,把这些原始代码搬到我们的空间中.   
  00462966   |. >pop     esi
  
  在.006640CD处写代码反注册热键
  
代码:
  006640CD     8>mov     ecx, esi
  006640CF     E>call    MalwareD.004628DD
  006640D4     6>push    MalwareD.00664018
  006640D9     8>mov     ecx, esi
  006640DB     E>call    MalwareD.004628DD
  006640E0     6>push    MalwareD.0066401C
  006640E5     8>mov     ecx, esi
  006640E7     E>call    MalwareD.004628DD
  006640EC     6>push    MalwareD.00664020
  006640F1     8>mov     ecx, esi
  006640F3     E>call    MalwareD.004628DD
  006640F8     6>push    MalwareD.00664024
  006640FD     8>mov     ecx, esi
  006640FF     E>call    MalwareD.004628DD
  00664104     6>push    MalwareD.00664028
  00664109     8>mov     ecx, esi
  0066410B     E>call    MalwareD.004628DD
  00664110     6>push    MalwareD.0066402C
  00664115     8>mov     ecx, esi
  00664117     E>call    MalwareD.004628DD
  0066411C   - E>jmp     MalwareD.00462966
  
  ////////////////////////// OK反注册热键功能添加完成.
  下面开始注册热键:
  
代码:
  0047BF87   |. >push    9
  0047BF89   |. >push    MalwareD.005D4BB8
  0047BF8E   |. >call    MalwareD.0047BDD8
  0047BF93      >mov     edi, dword ptr ss:[ebp-10] // 改  jmp     MalwareD.00664125
  0047BF96      >cmp     dword ptr ds:[edi-8], 0      // 填充 2个 nop 同样,把这些原始代码搬到我们的空间中.       
  0047BF9A   |. >je      short MalwareD.0047BFE6
  0047BF9C   |. >mov     eax, dword ptr ds:[5C9084]
  
  在.00664125处写代码注册热键
  
代码:
  00664125     6>pushad
  00664126     8>lea     eax, dword ptr ss:[ebp-10]
  00664129     5>push    eax
  0066412A     B>mov     eax, MalwareD.00664000
  0066412F     F>push    dword ptr ds:[eax]
  00664131     8>mov     ecx, esi
  00664133     6>push    101
  00664138     6>push    MalwareD.00664018
  0066413D     E>call    MalwareD.0047BDD8
  00664142     8>lea     eax, dword ptr ss:[ebp-10]
  00664145     5>push    eax
  00664146     B>mov     eax, MalwareD.00664004
  0066414B     F>push    dword ptr ds:[eax]
  0066414D     8>mov     ecx, esi
  0066414F     6>push    102
  00664154     6>push    MalwareD.0066401C
  00664159     E>call    MalwareD.0047BDD8
  0066415E     8>lea     eax, dword ptr ss:[ebp-10]
  00664161     5>push    eax
  00664162     B>mov     eax, MalwareD.00664008
  00664167     F>push    dword ptr ds:[eax]
  00664169     8>mov     ecx, esi
  0066416B     6>push    103
  00664170     6>push    MalwareD.00664020
  00664175     E>call    MalwareD.0047BDD8
  0066417A     8>lea     eax, dword ptr ss:[ebp-10]
  0066417D     5>push    eax
  0066417E     B>mov     eax, MalwareD.0066400C
  00664183     F>push    dword ptr ds:[eax]
  00664185     8>mov     ecx, esi
  00664187     6>push    104
  0066418C     6>push    MalwareD.00664024
  00664191     E>call    MalwareD.0047BDD8
  00664196     8>lea     eax, dword ptr ss:[ebp-10]
  00664199     5>push    eax
  0066419A     B>mov     eax, MalwareD.00664010
  0066419F     F>push    dword ptr ds:[eax]
  006641A1     8>mov     ecx, esi
  006641A3     6>push    105
  006641A8     6>push    MalwareD.00664028
  006641AD     E>call    MalwareD.0047BDD8
  006641B2     8>lea     eax, dword ptr ss:[ebp-10]
  006641B5     5>push    eax
  006641B6     B>mov     eax, MalwareD.00664014
  006641BB     F>push    dword ptr ds:[eax]
  006641BD     8>mov     ecx, esi
  006641BF     6>push    106
  006641C4     6>push    MalwareD.0066402C
  006641C9     E>call    MalwareD.0047BDD8
  006641CE     6>popad
  006641CF     8>mov     edi, dword ptr ss:[ebp-10]
  006641D2     8>cmp     dword ptr ds:[edi-8], 0
  006641D6   - E>jmp     MalwareD.0047BF9A
  
  ////////////////////////// OK注册热键功能添加完成.
CTRL+SHIFT+ALT+1-6
对应着“暂停保护”的六个项目


  
--------------------------------------------------------------------------------
【经验总结】
  
  最后在OD中右键,保存的可执行文件->所有修改->保存文件
  经过测试所有功能完全正常:)~
  实际代码的修改我用的是 Skypatch插件(很方便,感谢作者~).  但奇怪的是用这个插件写好代码Patch后,OD的右键保存时,提示没有修改数据.
  真晕了,没办法,只好patch后,用010edit(感谢Playboysen~)对照着一点点改exe. 有知道什么原因的大大提示则个:)

  经过这次改造历程,PE区段的概念真的是明白了,在分析过程中,软件上下条理很清楚:)  应该与软件的架构有很大关系.学习了
  
  最后:感谢MD作者的作品,虽然不用数字卫士,但这个MD个人感觉还是很不错的,稳定性相当高,同时内置ARK工具很方便(做广告?哈哈).
  
  
打造后的MD:MalwareDefender.rar
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2010年11月30日 18:02:28