首页
社区
课程
招聘
[讨论]pid=1的进程保护方案分析,我很菜,没能分析完
发表于: 2008-7-29 02:04 20943

[讨论]pid=1的进程保护方案分析,我很菜,没能分析完

2008-7-29 02:04
20943

记得前一段时间看到的,不知是哪个杀木马软件的自我保护,说是当开启强力保护之后,就会把自己的pid修改为1,这样就结束不掉了.
我是驱动菜鸟,刚刚学起,知道了几个结构而已,就自己写了个简单驱动,修改指定进程的EPROCESS中的pid 值为1,效果如图(示例中修改了notepad.exe的pid):

这样修改之后,再测试一部分进程工具,结果如下:
taskmgr    无法结束
IceSword                  直接BSOD
SnipeSword  ;  可以正确识别PID,结束就BSOD
RKU     普通方式无法结束,Force Kill 导致BSOD
gmer.exe                  无法结束
Atool.exe                   可结束,但退出此程序就BSOD

就算不是被别的进程结果,而是自行退出,也会马上BSOD.我想这是因为所有线程退出的流程都是一样的,不管线程是自杀还是他杀,最终都是执行了PspExitThread,而问题应该就在这个函数.

BSOD截图如下:


用Windbg分析用IceSword结束时BSOD产生的Minidump,结果如下:
kd> !analyze -v
*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

CID_HANDLE_DELETION (17)
Arguments:
Arg1: 00000000
Arg2: 00000000
Arg3: 00000000
Arg4: 00000000

Debugging Details:
------------------

CUSTOMER_CRASH_COUNT:  2

DEFAULT_BUCKET_ID:  CODE_CORRUPTION

BUGCHECK_STR:  0x17

PROCESS_NAME:  svchost.exe

LAST_CONTROL_TRANSFER:  from 805fad7b to 80534523

STACK_TEXT:  
ba51fc74 805fad7b 00000017 fe829788 fe829798 nt!KeBugCheck+0x14
ba51fca4 80564af7 fe8297b0 fe829798 00000000 nt!PspProcessDelete+0x15d
ba51fcc0 804e46d5 fe8297b0 00000000 00001404 nt!ObpRemoveObjectRoutine+0xdf
ba51fce4 80567cb3 81783da0 e23b4970 81775678 nt!ObfDereferenceObject+0x5f
ba51fcfc 80567d1c e23b4970 fe8297b0 00001404 nt!ObpCloseHandleTableEntry+0x155
ba51fd44 80567d66 00001404 00000001 00000000 nt!ObpCloseHandle+0x87
ba51fd58 804df7ec 00001404 007afdbc 7c92eb94 nt!NtClose+0x1d
ba51fd58 7c92eb94 00001404 007afdbc 7c92eb94 nt!KiFastCallEntry+0xf8
WARNING: Frame IP not in any known module. Following frames may be wrong.
007afdbc 00000000 00000000 00000000 00000000 0x7c92eb94

STACK_COMMAND:  kb

CHKIMG_EXTENSION: !chkimg -lo 50 -d !nt
    80534533-80534537  5 bytes - nt!KeBugCheckEx
  [ 8b ff 55 8b ec:e9 14 db f6 37 ]
5 errors : !nt (80534533-80534537)

MODULE_NAME: IsDrv122

IMAGE_NAME:  IsDrv122.sys

DEBUG_FLR_IMAGE_TIMESTAMP:  46d28e35

FOLLOWUP_NAME:  MachineOwner

MEMORY_CORRUPTOR:  PATCH_IsDrv122

FAILURE_BUCKET_ID:  MEMORY_CORRUPTION_PATCH_IsDrv122

BUCKET_ID:  MEMORY_CORRUPTION_PATCH_IsDrv122

Followup: MachineOwner
---------

========================================================
从栈调用看,是PspProcessDelete出现错误,引发KeBugCheck.
既然我改的是pid,那么我就在WRK中找PspProcessDelete中和pid有关的操作,然后就看到这些代码,前后无关部分省略.

........
if (Process->UniqueProcessId) {
        if (!(ExDestroyHandle (PspCidTable, Process->UniqueProcessId, NULL))) {
            KeBugCheck (CID_HANDLE_DELETION);
        }
    }

......

看来好像是这里的ExDestoryHandle出了问题.
该函数的描述是:
NTKERNELAPI
BOOLEAN
ExDestroyHandle (
    __inout PHANDLE_TABLE HandleTable,
    __in HANDLE Handle,
    __inout_opt PHANDLE_TABLE_ENTRY HandleTableEntry
    )
/*
Routine Description:

    This function removes a handle from a handle table.
*/
//即从一个句柄表中移除指定句柄.
EXHANDLE LocalHandle;
    PETHREAD CurrentThread;
    PVOID Object;

    PAGED_CODE();

    LocalHandle.GenericHandleOverlay = Handle;

    CurrentThread = PsGetCurrentThread ();

    //
    //  If the caller did not supply the optional handle table entry then
    //  locate the entry via the supplied handle, make sure it is real, and
    //  then lock the entry.
    //

    KeEnterCriticalRegionThread (&CurrentThread->Tcb);

    if (HandleTableEntry == NULL) {

        HandleTableEntry = ExpLookupHandleTableEntry( HandleTable,
                                                      LocalHandle );

        if (!ExpIsValidObjectEntry(HandleTableEntry)) {

            KeLeaveCriticalRegionThread (&CurrentThread->Tcb);
            return FALSE;
        }

        if (!ExpLockHandleTableEntry( HandleTable, HandleTableEntry )) {

            KeLeaveCriticalRegionThread (&CurrentThread->Tcb);
            return FALSE;
        }
    } else {
        EXASSERT ((HandleTableEntry->Value&EXHANDLE_TABLE_ENTRY_LOCK_BIT) == 0);
    }

    //
    // If we are debugging handle operations then save away the details
    //

    if (HandleTable->DebugInfo != NULL) {
        ExpUpdateDebugInfo(HandleTable, CurrentThread, Handle, HANDLE_TRACE_DB_CLOSE);
    }

    //
    //  At this point we have a locked handle table entry.  Now mark it free
    //  which does the implicit unlock.  The system will not allocate it
    //  again until we add it to the free list which we will do right after
    //  we take out the lock
    //

    Object = InterlockedExchangePointer (&HandleTableEntry->Object, NULL);

    EXASSERT (Object != NULL);
    EXASSERT ((((ULONG_PTR)Object)&EXHANDLE_TABLE_ENTRY_LOCK_BIT) == 0);

    //
    // Unblock any waiters waiting for this table entry.
    //
    ExUnblockPushLock (&HandleTable->HandleContentionEvent, NULL);

    ExpFreeHandleTableEntry( HandleTable,
                             LocalHandle,
                             HandleTableEntry );

    KeLeaveCriticalRegionThread (&CurrentThread->Tcb);

    return TRUE;
}

接下来就到句柄表相关操作的分析了.由于能力有限,我只大概知道句柄表是3层表,后面的一些操作我就看不明白了,所以把问题发出来,恳请大牛牛们继续分析~~~我等小菜好学习一下~


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (31)
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
2
自己顶一个,期待大牛出现~
2008-7-29 11:35
0
雪    币: 709
活跃值: (2420)
能力值: ( LV12,RANK:1010 )
在线值:
发帖
回帖
粉丝
3
1. 你改了pspcidtable没?
2. 还是仅仅修改了EPROCESS中的PID?

问题要描述清楚。
若是1, IS在杀进程时,取到的ETHREAD不合法,于是BSOD.
若是2, 应该不会有问题,至少我这里没问题.
2008-7-29 12:03
0
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
4
炉子的软件很多pid =1的~~
2008-7-29 12:24
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
5
回答:1.没有改PspCidTable,事实上我还不太了解这个表
2.正确,我只改了EPROCESS中的PID,应该是这个引起了ExDestroyHandle的错误吧.

你测试没有问题吗?
我在虚拟机干净系统中测试也是会BSOD,前面的那个图就来自虚拟机.
大米应该对句柄表很熟了吧,你能不能从ExDestroyHandle那里继续分析?
2008-7-29 14:12
0
雪    币: 375
活跃值: (12)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
6

嗯~老V答对了,当然还有更加猥琐的方法。。。
2008-7-29 15:12
0
雪    币: 6075
活跃值: (2236)
能力值: (RANK:1060 )
在线值:
发帖
回帖
粉丝
7
这些都是小儿科,我有最猥琐的方法,我就是不说。
2008-7-29 15:14
0
雪    币: 709
活跃值: (2420)
能力值: ( LV12,RANK:1010 )
在线值:
发帖
回帖
粉丝
8
这些都是幼儿科,我有超猥琐的方法,我就是不说。
2008-7-29 16:23
0
雪    币: 1946
活跃值: (248)
能力值: (RANK:330 )
在线值:
发帖
回帖
粉丝
9
我是来膜拜楼上三位猥琐王的
2008-7-29 16:24
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
10
我也膜拜一下几位大牛牛,就帮我解释下这个你们眼中的小儿科问题吧?
2008-7-29 16:49
0
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
我也有猥琐方法,不过只是一般猥琐,嘎嘎
PS:听说Bughoho是mm(曾经是mm?)疑惑ing~
2008-7-29 16:58
0
雪    币: 7309
活跃值: (3788)
能力值: (RANK:1130 )
在线值:
发帖
回帖
粉丝
12
我是来膜拜组长的
2008-7-29 17:12
0
雪    币: 740
活跃值: (952)
能力值: ( LV9,RANK:160 )
在线值:
发帖
回帖
粉丝
13
膜拜13#以上的人
2008-7-29 17:40
0
雪    币: 609
活跃值: (237)
能力值: ( LV12,RANK:441 )
在线值:
发帖
回帖
粉丝
14
膜拜14#以上的人
2008-7-29 18:35
0
雪    币: 846
活跃值: (221)
能力值: (RANK:570 )
在线值:
发帖
回帖
粉丝
15
膜拜5#以上的人
2008-7-29 19:26
0
雪    币: 846
活跃值: (221)
能力值: (RANK:570 )
在线值:
发帖
回帖
粉丝
16
似乎因为某种原因,使WINDOWS在使用PID的时候需要右移2位(貌似所有PID值都是4的倍数),修改PID为1,会被认为是Idle?

修改为2或者3也是一样的?还有5,6,7

也可能是某个PID段默认是不允许关的
2008-7-29 19:31
0
雪    币: 563
活跃值: (95)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
哈哈蓝屏了
2008-7-29 20:29
0
雪    币: 375
活跃值: (12)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
18

嗯~pid基本都是4的倍数,再没修改的情况下都是。原始pid+1、+2、+3都能打开该pid的进程。这或许和PspCidTable有关。sudami应该可以回答这个问题,期待dami~

2008-7-29 20:56
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
19
顶楼上的,我也在等大米呢,可大米来了却不说~
2008-7-29 21:10
0
雪    币: 709
活跃值: (2420)
能力值: ( LV12,RANK:1010 )
在线值:
发帖
回帖
粉丝
20
你把代码发上来啊。
也不知道你是怎么写的。。。
2008-7-29 21:34
0
雪    币: 846
活跃值: (221)
能力值: (RANK:570 )
在线值:
发帖
回帖
粉丝
21
貌似XP开始?  PspCidTable换了个省内存的格式? 分了3级

二级和三级,PID要先对齐,然后再根据PID查PspCidTable

在查PspCidTable之前还有检查PID值是否过大导致超级PspCidTable范围的,超过了就直接返回失败了.....这个就是你们说的更猥琐的方法?

其实PID怎么改,只要不是自己的,就可以让别人杀不了自己吧... 怎么不直接换成0....
2008-7-29 22:29
0
雪    币: 375
活跃值: (12)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
22


XP/2K3是动态扩展的。

句柄表是这样。

要猥琐的可以去别的地方做手脚。。

有了WRK。。。。像我这种菜鸟有福了。
2008-7-29 23:01
0
雪    币: 846
活跃值: (221)
能力值: (RANK:570 )
在线值:
发帖
回帖
粉丝
23
你这么说,把LZ搞得很不专业....不要说出来麻...
2008-7-29 23:10
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
24
代码比较简单基本没啥内容,就是通过PsActiveProcessLinks遍历EPROCESS链,找到记事本的EPROCESS,然后修改其UniqueProcessId一项的值为1.

刚学驱动,这个代码基本没啥价值,所以没贴,抱歉~

================================================================
//关键函数
VOID ShowEPROCESS(void)
{
        DWORD EProcess,FirstEProcess;
        LIST_ENTRY*     ActiveProcessLinks;
        DWORD pid,dwCount=0;
        PUCHAR pImage;
        PPROCESS_INFO ProcessInfo={0};
        EProcess=FirstEProcess=(DWORD)PsGetCurrentProcess();
        __try {   
        while ( EProcess!= 0)   
        {   
            dwCount++;   
                        pid= *( (DWORD*)( EProcess + EPROCESS_PID_OFFSET ) );   
            pImage= (PUCHAR)( EProcess + EPROCESS_IMAGENAME_OFFSET ) ;   
                        if (!_stricmp("notepad.exe",pImage))
                        {
                                DbgPrint("Found notepad.exe,now change the PID\n");
                                *( (DWORD*)( EProcess + EPROCESS_PID_OFFSET ) )=1;

                        }
            DbgPrint ( "[Pid=%8d] EProcess=0x%08X %s\n", pid, EProcess, pImage) ;   
                       
            ActiveProcessLinks = (LIST_ENTRY*) ( EProcess + EPROCESS_FLINK_OFFSET ) ;   
            EProcess = (DWORD)ActiveProcessLinks->Flink - EPROCESS_FLINK_OFFSET ;   
                       
            if ( EProcess == FirstEProcess )   
                break ;   
        }   
        DbgPrint ( "ProcessCount = %d\n", dwCount ) ;   
    }
        __except ( 1 ) {   
        DbgPrint ( "EnumProcessList exception !" ) ;   
    }

}
======================================================

代码用到了EPROCESS结构在XP SP2下的一些偏移,不是此版本系统请不要随便加载附件中的驱动,否则可能BSOD.
驱动,运行记事本后,用任意驱动加载工具加载此驱动即可. ShowEPROC.rar
上传的附件:
2008-7-30 03:02
0
雪    币: 709
活跃值: (2420)
能力值: ( LV12,RANK:1010 )
在线值:
发帖
回帖
粉丝
25
单单改个PID,我这里没出过问题;看你代码也没什么问题啊
改THREAD 的TID指向的PID到是会导致IS结束就BSOD.

现在在实习,没环境没工具.晚上回家再帮你调试下,看能否解决...
2008-7-30 09:35
0
游客
登录 | 注册 方可回帖
返回
//