• 标 题:《增加taskmgr.exe调用FileInfo的功能》
  • 作 者:Vegeta
  • 时 间:004-08-17,10:21
  • 链 接:http://bbs.pediy.com

前不久写了个小程序:“ProcessList and FI”,他能查看系统的所有进程,并且有效地和FI结合在了一起。当面对一些可疑的进程时就可以快速得调用FI进行更深一步地分析了,可这个小程序仅仅支持WIN9X,到了NT系统中就不能使用了。再写个NT下的进程管理器不如直接改造现有的taskmgr.exe,因为我个人感觉taskmgr.exe还不错!

一:本文所涉及的程序。

    目标程序:taskmgr.exe(Win2000SP4所带的Windows TaskManager(ver5.0.2195.6620))。
    调用FI的程序:CallFI.exe(在taskmgr.exe中获取指定进程的路径并依此调用FileInfo程序)。
    所需工具:SoftICE、W32dasm、Exescope、LordPE,UltraEdit。


二:分析taskmgr.exe。

    打开taskmgr.exe后选择[进程]标签,右键单击任意一个进程后你会发现弹出了一个菜单,我们可以在里面添加一个菜单项用来调用CallFI.exe程序。
    
    在添加菜单项之前先对其菜单消息处理代码进行定位。定位后就可以修改消息处理代码,处理我们新添加的菜单项事件了。可以用TrackPopupMenuEx()和SendMessageW()作为断点进行定位。先下TrackPopupMenuEx()断点,右键单击进程后就会中断,中断后要按F11,然后选[结束进程],这时又会出现中断,此时再下SendMessageW()断点,中断后再往下走几步就会找到关键位置了。当然,你也可以直接下SendMessageW()作为断点,但不如前一种方法方便。
    
    下面是其菜单消息处理代码的部分内容:

:010085F6 BA5B9C0000              mov edx, 00009C5B      ————9C5B(ID=40027,[调试]菜单)
:010085FB 3BCA                    cmp ecxedx
:010085FD 7F50                    jg 0100864F            ————所选ID>40027 -> JUMP
:010085FF 7438                    je 01008639            ————跳到[调试]事件处理代码
:01008601 81E9F0030000            sub ecx, 000003F0
:01008607 7410                    je 01008619
:01008609 49                      dec ecx
:0100860A 49                      dec ecx
:0100860B 0F8492000000            je 010086A3
:01008611 49                      dec ecx
:01008612 7425                    je 01008639
:01008614 E99A000000              jmp 010086B3           ————退出判断
.
:01008639 85C0                    test eaxeax
:01008648 E8B2FDFFFF              call 010083FF    ————[调试]事件处理代码
.
:0100864F BA5C9C0000              mov edx, 00009C5C  ————[结束进程ID]
:01008654 3BCA                    cmp ecxedx
:01008656 744B                    je 010086A3        ————[结束进程]事件处理代码
.
:0100866A 81F9A99C0000            cmp ecx, 00009CA9 ————[结束进程树ID]
:01008670 7541                    jne 010086B3
:0100867B E852070000              call 01008DD2    ————[结束进程树]事件处理代码
:01008680 EB31                    jmp 010086B3           ————退出判断


    可以看到这段代码首先和[调试]菜单的ID进行比较,只要ID比40027大,代码就会跳到另外的一个地方再进行判断,直到不满足任何条件退出至:010086B3。这里好象没什么好讲的,只要在退出之前跳到我们的代码就可以了……可究竟选择修改哪里呢?跳到010086B3处的代码有很多,例如:01008614,他是在ID小于40027并且不等于40027的情况下跳出去的,此时寄存器ECX的值已经不再是所选菜单的ID值了。我们要添加的代码首先要判断ECX是否为我们所选菜单的ID值,难道再MOV一次?不好!(其实不判断ID也能正常执行,就是代码不严谨,我在后面的修改中就没有CMP,偷懒……这里还是讲清楚为好。)往下看吧,01008670,他跳到010086B3前ECX的值还是所选菜单的ID值!就选他了!我们新建菜单的ID值比40027大就可以确保程序能执行到那里。我选的是:40066。

    
三:修改taskmgr.exe。

    1,添加菜单项:
    用Exescope插入菜单项时提示没有足够的空间,只好修改原来的分隔线了,将ID改为:40066,名称也只能两个字符了,我写的是:“FI”。

    2,增加输入函数:
    新建菜单项[FI]的功能是运行CallFI.exe,这就要利用ShellExecute()或类似功能的函数。原taskmgr.exe中并没有类似函数的调用,所以我们必须增加一个ShellExecute()。简单介绍一下步骤:
    用LordPE中的[PE Editor]打开taskmgr.exe(记下ImageBase=01000000)。选[Directories],在Import Table处选[...],右键单击任意DLL,选[add import],分别填上:SHELL32.dll,ShellExecuteA,然后分别点:[+]和[OK]。在[Import Table]中选中刚刚添加进去的SHELL32.dll,并将右下脚的[View always FirstThunk]选中,记下ShellExecuteA的ThunkRVA值:0001801C。

    3,寻找空白空间并添加数据和代码:
    空白空间我选的是offset:560。现在再来看看ShellExecute():

    HINSTANCE ShellExecute(

    HWND hwnd,  // handle to parent window
    LPCTSTR lpOperation,  // pointer to string that specifies operation to perform
    LPCTSTR lpFile,  // pointer to filename or folder name string
    LPCTSTR lpParameters,  // pointer to string that specifies executable-file parameters 
    LPCTSTR lpDirectory,  // pointer to string that specifies default directory
    INT nShowCmd   // whether file is shown when opened
    );

    如果要运行CallFI.exe,在C中可以这样写:
    ShellExecute(NULL,"open","F:\\tools\\cracktools\\Fi250\\FI_REG.EXE",NULL, NULL, SW_SHOWNORMAL);

    ShellExecute()共有6个参数,在这里只有两个参数需要存放在空白空间里,即:
    lpOperation="open",
    lpFile="F:\tools\cracktools\Fi250\CallFI.exe"。//CallFI.exe在计算机中的位置。

    用UltraEdit打开taskmgr.exe,将上面44字节写入offset:560,并记下他们的地址:
    lpOperation=560
    lpFile=568

    这样我们就具备了运行CallFI.exe的条件:

    PUSHAAD        60
    PUSH 01        6A01        ->SW_SHOWNORMAL
    PUSH 00        6A00
    PUSH 00        6A00
    PUSH 01000568  6868050001  ->"F:\tools\cracktools\Fi250\FI_REG.EXE"
    PUSH 01000560  6860050001  ->"open"
    PUSH 00        6A00
    CALL 0001801C  FF151C800101->0101801C(ThunkRVA+ImageBase=0001801C+01000000)
    POPAD          61
    JMP 010086B3   E904810000  退出判断

    用UltraEdit打开taskmgr.exe,将上面31字节写入offset:590。

    当ID值不满足所有条件时,让程序执行我们的代码,将
    :01008670 jne 010086B3
    改为:
    :01008670 jne 01000590

    用UltraEdit搜索754185C0743D替换为0F851A7FFFFF即可。

    现在你就可以试试与FileInfo联手后的进程管理器了,是不是感觉比以前强大了很多呢?


四:相关提示。

    文中提到的CallFI.exe可从我的个人主页下载,CallFI.exe须与FileInfo程序在同一目录,详见其Readme文件。

    我的个人主页:
    http://timw.yeah.net
    http://timw.126.com

五:灌水。

    和其他的PEDIY文章相比本文实属拙文,写出来当个总结吧。水平有限,还请大家多多指教。

    再过几个小时,2004雅典奥运会就正式拉开帷幕了,祝所有的运动员都取得好成绩!

    谢谢大家!


23:09 2004-08-13