首页
社区
课程
招聘
[原创]给任务管理器增加显示程序完整路径功能
发表于: 2009-2-22 16:39 25303

[原创]给任务管理器增加显示程序完整路径功能

2009-2-22 16:39
25303
【文章标题】: 给任务管理器增加显示程序完整路径功能
【文章作者】: stalker
【软件名称】: taskmgr.exe
【下载地址】: 系统目录
【使用工具】: OllyDbg,LordPE,ResHacker
【操作平台】: Windows XP Sp2
--------------------------------------------------------------------------------
【详细过程】
  Windows自带的任务管理器无法显示程序所在的完整路径,我一直觉得这是一个缺陷,今天我们就自己来给它增加这一功能。
  获取一个进程完整路径的方法有很多,我们使用CreateToolhelp32Snapshot&Module32First的方法,示例代码如下
  
  invoke CreateToolhelp32Snapshot,TH32CS_SNAPMODULE,dwTargetProcessID
  mov MD32.dwSize,sizeof MD32           ;MD32为一个MODULEENTRY32结构体变量
  invoke Module32First,eax,offset MD32
  

  调用上面的代码之后MD32.szExePath中就是目标进程的完整路径了。
  下面正式开始对任务管理器的修改,大致可以分为3个步骤
  1.增加菜单
  2.定位程序响应菜单项点击的代码位置
  3.加入对我们新增菜单的响应代码
  
  首先使用资源编辑工具(这里我使用的是ResHacker)给程序增加一个菜单项"显示完整路径(&S)",如图1

  我们新增的菜单项与"结束进程(&E)"处于同一组中,我们就通过它来定位任务管理器对菜单项响应代码的位置,从图1我们看
  到它的ID为40028,转换为16进制就是9C5C(记下来)
  关于定位,首先我想到的是以前使用的“查找所有分支法”,无奈没有成功(看来这办法并不是屡试不爽=_=)
  
  于是另寻他法,通过行为来定位,OD载入任务管理器,对TerminateProcess这个函数下断,运行之,然后随便运行一个程序,
  再在被调试的任务管理器中右键结束它,此时OD断下了任务管理器对TerminateProcess函数的调用,如图2

  从0100C226,一直向上找到过程首
  
  0100C17D  /$  8BFF          mov     edi, edi
  0100C17F  |.  55            push    ebp
  0100C180  |.  8BEC          mov     ebp, esp
  0100C182  |.  83EC 20       sub     esp, 20
  ......省略中间若干代码
  0100C223  |.  6A 01         push    1                                ; /ExitCode = 1
  0100C225  |.  56            push    esi                              ; |hProcess
  0100C226  |.  FF15 C0100001 call    dword ptr [<&KERNEL32.TerminateP>; \TerminateProcess
  

  单击0100C17D这一行,可以在信息窗口看到如图3所示信息

  有三个地方调用了这个过程,我们要寻找究竟哪个地方对菜单项进行了判断处理,一个一个前往查看下,过程省略,最终找到
  下面的地方
  
  0100CF29   > \BA 5C9C0000   mov     edx, 9C5C       ;9C5C,你还记得吗?
  0100CF2E   >  3BCA          cmp     ecx, edx
  0100CF30   .^ 74 AD         je      short 0100CEDF
  0100CF32   .^ 7E BB         jle     short 0100CEEF
  0100CF34   .  81F9 629C0000 cmp     ecx, 9C62
  0100CF3A   .  7E 30         jle     short 0100CF6C
  0100CF3C   .  81F9 779C0000 cmp     ecx, 9C77
  0100CF42   .  74 18         je      short 0100CF5C
  0100CF44   .  81F9 A99C0000 cmp     ecx, 9CA9
  0100CF4A   .^ 75 A3         jnz     short 0100CEEF
  0100CF4C   .  85C0          test    eax, eax
  0100CF4E   .^ 74 9F         je      short 0100CEEF
  

  
  对菜单项id的处理判断找到了,我们直接从0100CF29这里跳走,加入我们自己的代码,然后再跳回来继续执行
  再写代码之前我们应当知道:
  1.一个MODULEENTRY32结构的大小为224H
  2.结构成员szExePath的相对于结构体起始地址的偏移为120H
  3.要成功获取进程的完整路径,我们要获得该进程的PID以及寻找一个内存块来存放一个MODULEENTRY32结构体
  
  关键是第3点,如何获取目标进程的PID,我们知道,通过TerminateProcess来结束一个进程,首先得使用OpenProcess函数
  来打开这个进程以获取进程句柄,而OpenProcess又需要进程的PID做为参数。我们回到开始任务管理器结束进程的地方看看
  
  0100C17D  /$  8BFF          mov     edi, edi
  0100C17F  |.  55            push    ebp
  0100C180  |.  8BEC          mov     ebp, esp
  0100C182  |.  83EC 20       sub     esp, 20
  ......
  0100C210  |.  FF75 08       push    dword ptr [ebp+8]                ; /ProcessId
  0100C213  |.  6A 00         push    0                                ; |Inheritable = FALSE
  0100C215  |.  6A 01         push    1                                ; |Access = TERMINATE
  0100C217  |.  FF15 B4100001 call    dword ptr [<&KERNEL32.OpenProces>; \OpenProcess
  0100C21D  |.  8BF0          mov     esi, eax
  0100C21F  |.  85F6          test    esi, esi
  0100C221  |.  74 28         je      short 0100C24B
  0100C223  |.  6A 01         push    1                                ; /ExitCode = 1
  0100C225  |.  56            push    esi                              ; |hProcess
  0100C226  |.  FF15 C0100001 call    dword ptr [<&KERNEL32.TerminateP>; \TerminateProcess
  

  
  可以看到OpenProcess的第三个参数为[ebp+8],即当前过程(0100C17D)的第一个参数,调用此过程的代码如下
  
  0100CEE3   .  6A 00         push    0
  0100CEE5   .  FF70 08       push    dword ptr [eax+8]   ;[eax+8]与上面的[ebp+8]相对应,里面就是目标进程pid
  0100CEE8   .  8BCE          mov     ecx, esi            ;调试过程中可以通过命令d eax+8来验证
  0100CEEA   .  E8 8EF2FFFF   call    0100C17D
  

  上面这段调用代码,与开始我们找到的判断菜单id进行处理的代码位于同一过程,因此我们的代码可以直接使用[eax+8]来
  获取目标进程的pid
  
  最后一个问题就是,从哪里找地方来存放我们的MODULEENTRY32结构体
  首先使用OD载入运行任务管理器(一定要运行),然后Alt+M找到其.data段的位置,如图4

  双击该地址前往,然后会弹出来一个dump窗口,里面显示的是内存数据,一直往下拖,直到出现大片空白为止
  然后随便找一个地址作为结构体的起始地址(但要确保其后大小不小于224H),我使用的是01016A00这个地址
  
  到现在,基本所有的问题都解决了,剩下的就是找地方写代码
  由于taskmgr.exe并没有导入CreateToolhelp32Snapshot以及Module32First这两个函数,写入代码之前首先用LordPE导入它们,
  除此之外,我还导入了MessageBoxA,因为taskmgr.exe只导入了MessageBoxW,而结构体MODULEENTRY32的szExePath成员并不是
  一个Unicode String。当然,你也可以先将它转换为Unicode String,然后再调用taskmgr.exe导入的MessageBoxW。不过我想
  这样也许会更麻烦,因此我采用了增加导入MessageBoxA的简单方法=_=
  
  写入代码如下
  
  01014F00   > \60            pushad
  01014F01   .  BA 989C0000   mov     edx, 9C98
  01014F06   .  3BCA          cmp     ecx, edx
  01014F08   .  75 37         jnz     short 01014F41
  01014F0A   .  FF70 08       push    dword ptr [eax+8]                ; /ProcessID
  01014F0D   .  6A 08         push    8                                ; |Flags = TH32CS_SNAPMODULE
  01014F0F   .  FF15 38100201 call    dword ptr [<&kernel32.CreateTool>; \CreateToolhelp32Snapshot
  01014F15   .  C705 006A0101>mov     dword ptr [1016A00], 224
  01014F1F   .  68 006A0101   push    01016A00                         ; /pModuleentry = taskmgr3.01016A00
  01014F24   .  50            push    eax                              ; |hSnapshot
  01014F25   .  FF15 3C100201 call    dword ptr [<&kernel32.Module32Fi>; \Module32First
  01014F2B   .  FF15 7C130001 call    dword ptr [<&USER32.GetForegroun>; [GetForegroundWindow
  01014F31   .  6A 00         push    0                                ; /Style = MB_OK|MB_APPLMODAL
  01014F33   .  6A 00         push    0                                ; |Title = NULL
  01014F35   .  68 206B0101   push    01016B20                         ; |Text = ""
  01014F3A   .  50            push    eax                              ; |hOwner
  01014F3B   .  FF15 5D100201 call    dword ptr [<&user32.MessageBoxA>>; \MessageBoxA
  01014F41   >  61            popad
  01014F42   .  BA 5C9C0000   mov     edx, 9C5C
  01014F47   .^ E9 E27FFFFF   jmp     0100CF2E
  

  
  修改
  
  0100CF29   > \BA 5C9C0000   mov     edx, 9C5C     
  0100CF2E   >  3BCA          cmp     ecx, edx
  

  为
  
  0100CF29   > \E9 D27F0000   jmp     01014F00
  0100CF2E   >  3BCA          cmp     ecx, edx
  

  
  然后保存所有修改,至此,大功告成
 附上胜利截图一张以及修改过的taskmgr.exe

  
--------------------------------------------------------------------------------
【经验总结】
  我的目的基本还算达到了,原来发现不认识的进程时,想找出它来看看,却发现任务管理器居然不支持显示完整路径。
  但不知道为什么,获取一些系统进程的路径的时候,没有成功,显示出来是乱码。

该问题已经解决,权限问题(我自己测试的时候使用了一段在其他程序中正常的bug提权代码,于是没有发现)再次感谢 安摧 同学,希望大家写程序的时候一定仔细


现在附件中是上传的新的taskmgr.exe

--------------------------------------------------------------------------------

                                                       2009年02月22日 下午16:34

[课程]FART 脱壳王!加量不加价!FART作者讲授!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (35)
雪    币: 1185
活跃值: (2041)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
太强了,要顶!
2009-2-22 19:55
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
嘿嘿,vista自带了这个功能。
2009-2-22 20:20
0
雪    币: 247
活跃值: (10)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
4
权限问题~~~
在打开一个用户名为SYSTEM的进程的时候,因为权限不够,CreateToolhelp32Snapshot返回了-1(INVALID_HANDLE_VALUE)。
01014F00 > \60 pushad
01014F01 . BA 989C0000 mov edx, 9C98
01014F06 . 3BCA cmp ecx, edx
01014F08 . 75 37 jnz short 01014F41
01014F0A . FF70 08 push dword ptr [eax+8] ; /ProcessID
01014F0D . 6A 08 push 8 ; |Flags = TH32CS_SNAPMODULE
01014F0F . FF15 38100201 call dword ptr [<&kernel32.CreateToolhelp32Snapshot>] ; \CreateToolhelp32Snapshot
//这个返回失败!

01014F15 . C705 006A0101>mov dword ptr [1016A00], 224
01014F1F . 68 006A0101 push 01016A00 ; /pModuleentry = mytaskmg.01016A00
01014F24 . 50 push eax ; |hSnapshot
01014F25 . FF15 3C100201 call dword ptr [<&kernel32.Module32First>] ; \Module32First
01014F2B . FF15 7C130001 call dword ptr [<&USER32.GetForegroundWindow>] ; [GetForegroundWindow
01014F31 . 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL
01014F33 . 6A 00 push 0 ; |Title = NULL
01014F35 . 68 206B0101 push 01016B20 ; |Text = "?",06,"?眝?",06,"?,B6,"",B2,"",92,"?翽?",06,"衚",B2,"",92,"?",06,"蠪",B2,"",92,"?"
01014F3A . 50 push eax ; |hOwner
01014F3B . FF15 5D100201 call dword ptr [<&user32.MessageBoxA>] ; \MessageBoxA
01014F41 > 61 popad
01014F42 . BA 5C9C0000 mov edx, 9C5C
01014F47 .^ E9 E27FFFFF jmp 0100CF2E



提升权限的代码:
BOOL EnableDebugPrivileges()
{
/**********************************************************************/
//提升进程自身权限
BOOL bRet;
HANDLE hToken;
bRet = ::OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken);
if(!bRet)
{
return FALSE;
}
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
::LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&tp.Privileges[0].Luid);
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
::AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(tp),NULL,NULL);
if(GetLastError() != ERROR_SUCCESS)
{
return FALSE;
}
return TRUE;
/**********************************************************************/
}
2009-2-22 21:15
0
雪    币: 399
活跃值: (38)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
5
恩,问题解决了,非常感谢 安催 同学
开始我也想到是权限问题,我用了前几天用来修改特定进程内存的程序中的提权代码,看来是我写得有点问题。
2009-2-22 21:46
0
雪    币: 431
活跃值: (442)
能力值: ( LV12,RANK:530 )
在线值:
发帖
回帖
粉丝
6
http://bbs.pediy.com/showthread.php?t=4003

得到路径后还可以干点儿别的事情。
2009-2-22 22:16
0
雪    币: 7309
活跃值: (3778)
能力值: (RANK:1130 )
在线值:
发帖
回帖
粉丝
7
没有人喜欢Process Explorer
2009-2-22 22:20
0
雪    币: 399
活跃值: (38)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
8

让Vegeta见笑了
2009-2-22 22:42
0
雪    币: 399
活跃值: (38)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
9
我喜欢用Norton Process Viewer
2009-2-22 22:42
0
雪    币: 1667
活跃值: (286)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
10
记得我以前有发过任务管理器2000的代码,估计LZ以后修改可以参考~!
2009-2-23 04:06
0
雪    币: 399
活跃值: (38)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
11
任务管理器2000,就是Windows 2000带的任务管理器?
自带这个功能呀,好久没见过2000系统了
2009-2-23 12:53
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
好文章, mark了
2009-2-23 16:22
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
在SP3下出错了。不能用。
2009-2-23 16:28
0
雪    币: 431
活跃值: (442)
能力值: ( LV12,RANK:530 )
在线值:
发帖
回帖
粉丝
14
太客气了,互相学习。
2009-2-23 20:42
0
雪    币: 370
活跃值: (15)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
15
I LIKE THIS DIY
2009-2-23 21:52
0
雪    币: 474
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
这个还是有学习价值的。
2009-2-23 22:44
0
雪    币: 370
活跃值: (52)
能力值: ( LV13,RANK:350 )
在线值:
发帖
回帖
粉丝
17
真是没想到啊,学习
2009-2-24 18:49
0
雪    币: 192
活跃值: (50)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
我是来看一下的 看完我就走
2009-2-24 23:30
0
雪    币: 411
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
试了一下,发现我的系统不是XP SP2,不能用。谢谢楼主。
2009-2-25 11:47
0
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
写的好,要亲自试下!
2009-2-25 21:05
0
雪    币: 10726
活跃值: (2730)
能力值: ( LV5,RANK:71 )
在线值:
发帖
回帖
粉丝
21
看雪如何发帖?
2009-2-26 23:03
0
雪    币: 492
活跃值: (41)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
22
01014F5A  /$  55            PUSH EBP
01014F5B  |.  8BEC          MOV EBP,ESP
01014F5D  |.  83C4 E0       ADD ESP,-20
01014F60  |.  B8 10000000   MOV EAX,10
01014F65  |.  B8 08000000   MOV EAX,8
01014F6A  |.  C745 E0 00000>MOV DWORD PTR SS:[EBP-20],0
01014F71  |.  FF15 14110001 CALL DWORD PTR DS:[<&KERNEL32.GetCurrentProcess>]           ; [GetCurrentProcess
01014F77  |.  8D5D FC       LEA EBX,DWORD PTR SS:[EBP-4]
01014F7A  |.  53            PUSH EBX                                                    ; /phToken
01014F7B  |.  6A 20         PUSH 20                                                     ; |DesiredAccess = TOKEN_ADJUST_PRIVILEGES
01014F7D  |.  50            PUSH EAX                                                    ; |hProcess
01014F7E  |.  FF15 20100001 CALL DWORD PTR DS:[<&ADVAPI32.OpenProcessToken>]            ; \OpenProcessToken
01014F84  |.  6A 00         PUSH 0
01014F86  |.  68 6C656765   PUSH 6567656C
01014F8B  |.  68 72697669   PUSH 69766972
01014F90  |.  68 62756750   PUSH 50677562
01014F95  |.  68 53654465   PUSH 65446553
01014F9A  |.  8BDC          MOV EBX,ESP
01014F9C  |.  8D45 F4       LEA EAX,DWORD PTR SS:[EBP-C]
01014F9F  |.  50            PUSH EAX
01014FA0  |.  53            PUSH EBX
01014FA1  |.  6A 00         PUSH 0
01014FA3  |.  A1 2C100001   MOV EAX,DWORD PTR DS:[<&ADVAPI32.LookupPrivilegeValueW>]
01014FA8  |.  05 25060000   ADD EAX,625
01014FAD  |.  FFD0          CALL EAX
01014FAF  |.  83C4 14       ADD ESP,14
01014FB2  |.  C745 E4 01000>MOV DWORD PTR SS:[EBP-1C],1
01014FB9  |.  FF75 F4       PUSH DWORD PTR SS:[EBP-C]
01014FBC  |.  8F45 E8       POP DWORD PTR SS:[EBP-18]
01014FBF  |.  FF75 F8       PUSH DWORD PTR SS:[EBP-8]
01014FC2  |.  8F45 EC       POP DWORD PTR SS:[EBP-14]
01014FC5  |.  C745 F0 02000>MOV DWORD PTR SS:[EBP-10],2
01014FCC  |.  6A 00         PUSH 0                                                      ; /pRetLen = NULL
01014FCE  |.  6A 00         PUSH 0                                                      ; |pPrevState = NULL
01014FD0  |.  6A 10         PUSH 10                                                     ; |PrevStateSize = 10 (16.)
01014FD2  |.  8D45 E4       LEA EAX,DWORD PTR SS:[EBP-1C]                               ; |
01014FD5  |.  50            PUSH EAX                                                    ; |pNewState
01014FD6  |.  6A 00         PUSH 0                                                      ; |DisableAllPrivileges = FALSE
01014FD8  |.  FF75 FC       PUSH DWORD PTR SS:[EBP-4]                                   ; |hToken
01014FDB  |.  FF15 18100001 CALL DWORD PTR DS:[<&ADVAPI32.AdjustTokenPrivileges>]       ; \AdjustTokenPrivileges
01014FE1  |.  FF15 84110001 CALL DWORD PTR DS:[<&KERNEL32.GetLastError>]                ; [GetLastError
01014FE7  |.  0BC0          OR EAX,EAX
01014FE9  |.  75 07         JNZ SHORT mytaskmg.01014FF2
01014FEB  |.  C745 E0 01000>MOV DWORD PTR SS:[EBP-20],1
01014FF2  |>  FF75 FC       PUSH DWORD PTR SS:[EBP-4]                                   ; /hObject
01014FF5  |.  FF15 78110001 CALL DWORD PTR DS:[<&KERNEL32.CloseHandle>]                 ; \CloseHandle
01014FFB  |.  8B45 E0       MOV EAX,DWORD PTR SS:[EBP-20]
01014FFE  |.  C9            LEAVE
01014FFF  \.  C3            RETN

我在XP SP3下运行错误;
这个提权代码是从你的程序中反汇编出来的,其中加红的这一句是干嘛的呀?
本来是把函数的地址传给EAX,为什么还要加上625?
这样一加就不是查询特权值的函数地址了啊!
不是很明白,请楼主提示下。
2009-2-27 12:41
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
。。厉害,支持下
2009-2-27 13:48
0
雪    币: 399
活跃值: (38)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
24
被你发现尴尬的地方拉 我的这个东西在sp2下是没问题的
我在做这个的时候,还不太会用LordPE来增加导入函数,当时导入了LookupPrivilegeValueA,但是找不到调用地址(后来查资料后知道了),所以当时使用了通过LookupPrivilegeValueW的地址加上LookupPrivilegeValueA相对于它的偏移来定位。你自己用LordPE打开程序找找它的ThunkRVA,直接call [imagebase+TnunkRVA]试试看。
2009-2-27 22:20
0
雪    币: 211
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
占位,关注中!
2009-5-4 11:26
0
游客
登录 | 注册 方可回帖
返回
//