首页
社区
课程
招聘
[求助]这次是PsTerminateSystemThread问题.....
发表于: 2009-9-11 15:26 17270

[求助]这次是PsTerminateSystemThread问题.....

2009-9-11 15:26
17270
呵呵,小菜一只,遇到的都是些菜问题
大牛们别笑话俺~~~

刚才问过了PsCreateSystemThread的问题,现在却是PsTerminateSystemThread

大致代码如下:
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
                     IN PUNICODE_STRING RegistryPath){

   NTSTATUS status = STATUS_SUCCESS;
    DriverObject->DriverUnload=OnUnload;
    SetHook();
    return status;
}

NTSTATUS SetHook()
{
    NTSTATUS ntStatus;
    g_bExit = FALSE;

    ntStatus = PsCreateSystemThread(&hThread, (ACCESS_MASK) THREAD_ALL_ACCESS, NULL, NULL, NULL, (PKSTART_ROUTINE)WatchKiAttachProcessThread, NULL);
    KdPrint(("创建线程结果:%X\n", ntStatus));
   return ntStatus;
}

VOID OnUnload(IN PDRIVER_OBJECT DriverObject){
    NTSTATUS ntStatus;
    PETHREAD peThread;
    g_bExit = TRUE;
    PsLookupThreadByThreadId(hThread, &peThread);
    ntStatus = KeWaitForSingleObject(peThread, Executive, KernelMode, TRUE, 0);
    KdPrint(("NTSTATUS:%X\n", ntStatus));
    ObDereferenceObject(peThread);
    UnHook();
}

void WatchKiAttachProcessThread(IN PVOID pContext)
{
    LARGE_INTEGER liInterval;
    liInterval.QuadPart = - 10 * 1000 * 1000;

    while(1)
    {
        if (g_bExit)
        {
            PsTerminateSystemThread(STATUS_SUCCESS);
        }
        KeDelayExecutionThread(KernelMode,TRUE,&liInterval);

        if(((PUCHAR)g_OirginalKiAttachProcesssAddress)[1] != g_JmpMyKiAttachProcesssBytes[1] &&
           ((PUCHAR)g_OirginalKiAttachProcesssAddress)[2] != g_JmpMyKiAttachProcesssBytes[2] &&
           ((PUCHAR)g_OirginalKiAttachProcesssAddress)[3] != g_JmpMyKiAttachProcesssBytes[3] &&
           ((PUCHAR)g_OirginalKiAttachProcesssAddress)[4] != g_JmpMyKiAttachProcesssBytes[4] )
        {
            DbgPrint("HOOK被修改");
            HookKiAttachProcesss();
        }
    }
}

当驱动卸载时,调用OnUnload过程,执行到    ntStatus = KeWaitForSingleObject(peThread, Executive, KernelMode, TRUE, 0)之后,程序会进入线程函数WatchKiAttachProcessThread中执行PsTerminateSystemThread(STATUS_SUCCESS),而执行过此指令后,驱动卸载结束,,后面的UnHook之类的全都走不到了,这是为什么?有什么办法能让驱动正常卸载 ?

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (21)
雪    币: 77
活跃值: (17)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
2
另外还经常在运行到ntStatus = KeWaitForSingleObject(peThread, Executive, KernelMode, TRUE, 0);时发生蓝屏
STOP:0X0000000A
2009-9-11 16:04
0
雪    币: 290
活跃值: (20)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
PsLookupThreadByThreadId(hThread, &peThread);
我该怎么说你呢
2009-9-11 16:32
0
雪    币: 77
活跃值: (17)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
啊?这函数不应该是这么用吗?
我看可以得到正确的对象地址啊!而且是可以正常等待线程结束.....

呵呵,要是用的不对的话,该怎么说就怎么说,不用吝啬啊,,
2009-9-11 17:29
0
雪    币: 290
活跃值: (20)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
5
PsLookupThreadByThreadId的第一个参数tid不是句柄虽然类型是HANDLE但是你察看下ddk的用法兄弟
2009-9-11 17:32
0
雪    币: 77
活跃值: (17)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
6
另外这个问题解决了
用了个笨办法

VOID SetHook()
{
    NTSTATUS ntStatus;

    g_bExit = FALSE;
    KeInitializeEvent(&Kevent, SynchronizationEvent, FALSE);
    ntStatus = PsCreateSystemThread(&hThread, (ACCESS_MASK)THREAD_ALL_ACCESS, NULL, NULL, NULL, (PKSTART_ROUTINE)WatchKiAttachProcessThread, NULL);
    ZwClose(hThread);
}

void WatchKiAttachProcessThread(IN PVOID pContext)
{
    NTSTATUS ntStatus;
    LARGE_INTEGER liInterval;
    liInterval.QuadPart = - 10 * 1000 * 1000;
    while(1)
    {
        if (g_bExit)
        {
            ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
            KeSetEvent(&Kevent, 0, FALSE); // 设置线程结束事件
            PsTerminateSystemThread(STATUS_SUCCESS);
        }
        KeDelayExecutionThread(KernelMode,TRUE,&liInterval);

        if(((PUCHAR)g_OirginalKiAttachProcesssAddress)[1] != g_JmpMyKiAttachProcesssBytes[1] &&
           ((PUCHAR)g_OirginalKiAttachProcesssAddress)[2] != g_JmpMyKiAttachProcesssBytes[2] &&
           ((PUCHAR)g_OirginalKiAttachProcesssAddress)[3] != g_JmpMyKiAttachProcesssBytes[3] &&
           ((PUCHAR)g_OirginalKiAttachProcesssAddress)[4] != g_JmpMyKiAttachProcesssBytes[4] )
        {
            KdPrint(("HOOK被修改"));
            ExecuteWithNullDpcLockMustSucceed(HookKiAttachProcesss);
        }
        KdPrint(("WatchKiAttachProcessThread Run()!\n"));
    }
}

VOID OnUnload(IN PDRIVER_OBJECT DriverObject){
    NTSTATUS ntStatus;
    g_bExit = TRUE;
    ntStatus = KeWaitForSingleObject(&Kevent, Executive, KernelMode, TRUE, 0);
    KdPrint(("NTSTATUS:%X\n", ntStatus));
    UnHook();
}
2009-9-11 17:38
0
雪    币: 77
活跃值: (17)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
7
用上面的方法解决后
目前可以正常卸载驱动,线程运行也正常

就是不知道有没有其它隐患存在

兄弟给指点一下
2009-9-11 17:39
0
雪    币: 77
活跃值: (17)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
8
呃,刚看了一下DDK
确实如此,,可是为嘛有时候可以正常运行过去呢,,奇怪了

另外使用PsGetCurrentThreadId取得的应该不是我要结束的那个线程ID吧?
用哪个函数可以根据线程句柄取得线程ID呢?
2009-9-11 17:44
0
雪    币: 290
活跃值: (20)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
9
何必那样麻烦???
你不会用KeWaitForxxx用ZwWaitForxxx啊?把PsLookupThreadByThreadId去掉就行了
何必再加个事件??
你的用法可以但是多费手脚根本不需要去做的事情干嘛非要去做
2009-9-11 17:46
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
10
句柄ObRefrenceObjectByHandle得到对象ETHREAD,然后取Cid->UniqueThread就可以了,或者ZwQueryInformationThread
2009-9-11 17:49
0
雪    币: 251
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
隐患很大
KeSetEvent以后就看哪个线程跑得快了
2009-9-11 17:52
0
雪    币: 77
活跃值: (17)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
12
开始用的就是KeWaitForSignleObject来等待线程的结束
但是蓝屏,另一个帖子里有兄弟解答说该函数的第一个参数应该是Thread对象,而不是句柄

然后使用PsLookupThreadByThreadId来获取对象了,结果能通过,但一运行到线程中的结束指令后,整个卸载过程就完结了,OnUnload中等待线程结束后需要运行的代码全程没有得到运行,驱动没有正常在系统中卸载
然后这又知道了
PsLookupThreadByThreadId的第一个参数不是句柄,而应该是ID,,所以想知道怎么样根据句柄获得ID的..
2009-9-11 17:56
0
雪    币: 77
活跃值: (17)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
13
谢谢兄弟,我回头好好研究一下这两个函数
2009-9-11 17:56
0
雪    币: 77
活跃值: (17)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
14
意思是 KeSetEvent 后,因为已经满足主线程中的等待事件要求,所以有可能先运行主线程是吗?

不过这时Watch线程中后面只有一个自杀指令,应该不会有问题了吧?我自己猜的,,,不知道对不对
2009-9-11 17:59
0
雪    币: 77
活跃值: (17)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
15
如果我上面猜的不对
那是否可以通过在线程结束时,提升IRQL到DISPATCH级来达到同步的目的呢?
2009-9-11 18:00
0
雪    币: 251
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
既然已经有handle了为什么还要找CID?
2009-9-11 18:02
0
雪    币: 290
活跃值: (20)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
17
ObRefrenceObjectByHandle直接传句柄就可以获取内核对象(你的是Thread)再传给KeWaitForxxx就行了,你的方法没错的KeWaitxxx的时候已经挂住了代码执行不下去了,只有当执行到KeSetEvent时才执行

只是你这种方法有点多余直接用Zw/KeWaitForxxx就行了
2009-9-11 18:02
0
雪    币: 290
活跃值: (20)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
18
至于句柄获取id可以有几次种方法,可以使用ZwQueryInformationThread,也可以从Thread到ThreadId(当然知道Thread就没必要了,就好像知道了hThread就不需要知道Id也可以知道Thread了)
你如果要纪录ID在PsCreateSystemThread的时候参数就有返回
2009-9-11 18:05
0
雪    币: 77
活跃值: (17)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
19
找ID是想通过ID来找对象...
楼上已经有几位兄弟告诉我可以通过ObRefrenceObjectByHandle来获得对象了,,
之前不清楚,,太菜了,让兄弟见笑,呵呵
2009-9-11 18:05
0
雪    币: 77
活跃值: (17)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
20
嗯,这下明白了
就是在用KeWaitxxxx之前,先通过ObRefrenceObjectByHandle来获取对象,然后再调用KeWait方法来等待是吧..
之前出错应该是传进去的参数类型不正确,所以导致的执行起来出现各种不明所以的问题!!!
2009-9-11 18:06
0
雪    币: 77
活跃值: (17)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
21
啊,这一说发现我还真是笨啊

NTSTATUS
  PsCreateSystemThread(
    OUT PHANDLE  ThreadHandle,
    IN ULONG  DesiredAccess,
    IN POBJECT_ATTRIBUTES  ObjectAttributes  OPTIONAL,
    IN HANDLE  ProcessHandle  OPTIONAL,
    OUT PCLIENT_ID  ClientId  OPTIONAL,
    IN PKSTART_ROUTINE  StartRoutine,
    IN PVOID  StartContext
    );

这里的PCLIENT_ID应该就是线程ID了吧!!!真晕,这太菜了也
2009-9-11 18:09
0
雪    币: 12
活跃值: (701)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
学习下
2022-7-7 17:45
0
游客
登录 | 注册 方可回帖
返回
//