有人投到黑防去了,不过黑防不厚道,竟然没给完整的代码,自己整理一份备用吧,驱网、DebugMan、邪八的那群人直接飘过吧。
这种方法的关键在于给线程的ETHREAD.CrossThreadFlags设置PS_CROSS_THREAD_FLAGS_SYSTEM值,这样其它进程就无法结束它了,包括IceSword、RkU。至于原理,那就先看看wrk里结束进程的那几个内核函数源码,NtTerminateProcess、PsTerminateProcess、PspTerminateProcess最终都是调用PspTerminateThreadByPointer来将每个线程杀死,而在PspTerminateThreadByPointer里,如果线程是被其它进程强x结束的,就会有个这样的判断:

  1. if (IS_SYSTEM_THREAD
    (Thread))
    {
  2.     return STATUS_ACCESS_DENIED;
  3. }

Thread类型是PETHREAD,IS_SYSTEM_THREAD是个宏,如下:

  1. #define IS_SYSTEM_THREAD(Thread)  (((Thread)->CrossThreadFlags&PS_CROSS_THREAD_FLAGS_SYSTEM)
    )

也就是说当线程的ETHREAD.CrossThreadFlags包含PS_CROSS_THREAD_FLAGS_SYSTEM位时,就直接返回拒绝访问,这样线程就不会被结束了。具体参考代码请看wrk 1.2里的文件base\ntos\ps\psdelete.c。
好,现在只要给我们的进程里的每个线程都设置PS_CROSS_THREAD_FLAGS_SYSTEM,进程就不会被结束掉了。但是ETHREAD的结构没有文档化,所以还得自己找到CrossThreadFlags成员在ETHREAD结构里的偏移。可以通过在已导出的相关函数中找一些特征来定位CrossThreadFlags,黑防中是在PsIsSystemThread里找,但是这个函数在Windows 2000里没有,所以我们换个,换成PsTerminateSystemThread,先看下PsTerminateSystemThread的源码:

  1. NTSTATUS
  2. PsTerminateSystemThread(
  3.     __in NTSTATUS ExitStatus
  4.     )
  5. {
  6.     PETHREAD Thread = PsGetCurrentThread();
  7.  
  8.     if (!IS_SYSTEM_THREAD
    (Thread))
    {
  9.         return STATUS_INVALID_PARAMETER;
  10.     }
  11.  
  12.     return PspTerminateThreadByPointer
    (Thread, ExitStatus, TRUE);
  13. }

这里也用到了IS_SYSTEM_THREAD,那么也一定会有定位CrossThreadFlags的代码,如下:

  1. kd> u PsTerminateSystemThread
  2. nt!PsTerminateSystemThread:
  3. 805c89f8 8bff            mov    
    edi,edi
  4.              push    ebp
  5. 805c89fb 8bec            mov    
    ebp,esp
  6. 805c89fd 64a124010000    mov    
    eax,dword
    ptr
    fs:[00000124h]
  7. 805c8a03 f6804802000010  test    byte
    ptr
    [eax+248h],10h
  8.            jne     nt!PsTerminateSystemThread+0x1b
    (805c8a13)
  9. 805c8a0c b80d0000c0      mov    
    eax,0C000000Dh
  10. 805c8a11 eb09            jmp     nt!PsTerminateSystemThread+0x24
    (805c8a1c)
  11. 805c8a13 ff7508          push    dword
    ptr
    []
  12.              push    eax
  13. 805c8a17 e828fcffff      call    nt!PspTerminateThreadByPointer
    (805c8644)
  14. 805c8a1c 5d              pop    
    ebp
  15. 805c8a1d c20400          ret    

很明显test    byte ptr [eax+248h],10h中的248h就是CrossThreadFlags在ETHREAD里的偏移了,test    byte ptr [eax+xxxxxxxx],10h的16进制是f680xxxxxxxx10,现在只要先获得PsTerminateSystemThread的地址,然后向后搜索0x80f6,搜索到后再后面的4个字节就是CrossThreadFlags在ETHREAD里的偏移了。

得到了偏移,下面就是写代码了,驱动部分:

  1. #include <ntifs.h>
  2. #include <ntddk.h>
  3.  
  4. #define PS_CROSS_THREAD_FLAGS_SYSTEM 0x00000010UL  //form wrk 1.2 base\ntos\inc\ps.h
  5. #define IOCTL_THREAD_PROTECT CTL_CODE(FILE_DEVICE_UNKNOWN,
    0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
  6.  
  7. VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
  8. {
  9.   UNICODE_STRING usSymLink;
  10.   RtlInitUnicodeString(&usSymLink, L"\\??\\ThreadProtect");
  11.   IoDeleteSymbolicLink(&usSymLink);
  12.   IoDeleteDevice(pDriverObject->DeviceObject);
  13. }
  14.  
  15. NTSTATUS DispatchCreateClose(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
  16. {
  17.   pIrp->IoStatus.Status
    = STATUS_SUCCESS;
  18.   pIrp->IoStatus.Information
    ;
  19.   IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  20.  
  21.   return STATUS_SUCCESS;
  22. }
  23.  
  24. NTSTATUS DispatchControl(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
  25. {
  26.   NTSTATUS nRet = STATUS_UNSUCCESSFUL;
  27.   ULONG_PTR uInf ;
  28.   PIO_STACK_LOCATION pIoStack = IoGetCurrentIrpStackLocation(pIrp);
  29.   PVOID pSysBuff = pIrp->AssociatedIrp.SystemBuffer;
  30.  
  31.   switch (pIoStack->Parameters.DeviceIoControl.IoControlCode)
  32.   {
  33.   case IOCTL_THREAD_PROTECT:
  34.     PETHREAD pEThread;
  35.     PsLookupThreadByThreadId(HANDLE(*(PULONG)pSysBuff),
    &pEThread);
  36.     UNICODE_STRING usName;
  37.     RtlInitUnicodeString(&usName, L"PsTerminateSystemThread");
  38.     PUSHORT pOffset =
    (PUSHORT)MmGetSystemRoutineAddress(&usName);
  39.  
  40.     //search "test byte ptr [eax+xxxxxxxx],10h",hex:f680xxxxxxxx10
  41.     while (*pOffset
    !=
    0x80f6)
  42.       pOffset = PUSHORT((PUCHAR)pOffset
    );
  43.     PULONG pFlags = PULONG((PUCHAR)pEThread
    + *(PULONG)(pOffset
    ));
  44.     DbgPrint("pOffset:%08x, CrossFlagOffset:%08x\r\n", pOffset,
    *(PULONG)(pOffset
    ));
  45.     *pFlags |= PS_CROSS_THREAD_FLAGS_SYSTEM;  //set PS_CROSS_THREAD_FLAGS_SYSTEM bit
  46.     nRet = STATUS_SUCCESS;
  47.     uInf ;
  48.     break;
  49.   }
  50.  
  51.   pIrp->IoStatus.Status
    = nRet;
  52.   pIrp->IoStatus.Information
    = uInf;
  53.   IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  54.   return nRet;
  55. }
  56.  
  57. extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath)
  58. {
  59.   pDriverObject->DriverUnload
    = DriverUnload;
  60.   pDriverObject->MajorFunction[IRP_MJ_CREATE]
    = DispatchCreateClose;
  61.   pDriverObject->MajorFunction[IRP_MJ_CLOSE]
    = DispatchCreateClose;
  62.   pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]
    = DispatchControl;
  63.  
  64.   UNICODE_STRING usDeviceName;
  65.   RtlInitUnicodeString(&usDeviceName, L"\\Device\\ThreadProtect");
  66.  
  67.   NTSTATUS nRet;
  68.   PDEVICE_OBJECT pDeviceObject;
  69.   nRet = IoCreateDevice(pDriverObject,
    , &usDeviceName, FILE_DEVICE_UNKNOWN,
  70.     FILE_DEVICE_SECURE_OPEN, FALSE,
    &pDeviceObject);
  71.   if (!NT_SUCCESS(nRet))
  72.     return nRet;
  73.  
  74.   UNICODE_STRING usSymLink;
  75.   RtlInitUnicodeString(&usSymLink, L"\\??\\ThreadProtect");
  76.   nRet = IoCreateSymbolicLink(&usSymLink,
    &usDeviceName);
  77.   if (!NT_SUCCESS(nRet))
  78.   {
  79.     IoDeleteDevice(pDeviceObject);
  80.     return nRet;
  81.   }
  82.   return STATUS_SUCCESS;
  83. }

这段代码要解释的都在上面了。EXE部分的代码就不用帖了,只要将每个线程的ID通过DeviceIoControl传入驱动即可:

  1. #define IOCTL_THREAD_PROTECT CTL_CODE(FILE_DEVICE_UNKNOWN,
    0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
  2.  
  3. DeviceIoControl(hDevice, IOCTL_THREAD_PROTECT,
    &nThreadId, sizeof(nThreadId),
    , ,
    &nByteRet, );

点击这里下载文件: ThreadProtect.rar
运行后果自行负责,运行不了自行想办法到注册表里删除先前的ThreadProtect键值。

最后,怎么结束用这种方法保护的进程?方法大大的有,插入APC,然后PspExitThread就不会经过PspTerminateThreadByPointer了。

jpg 改 rar

进程防结束之PS_CROSS_THREAD_FLAGS_SYSTEM的更多相关文章

  1. HOOK API(四)—— 进程防终止

    HOOK API(四) —— 进程防终止 0x00        前言 这算是一个实战吧,做的一个应用需要实现进程的防终止保护,查了相关资料后决定用HOOK API的方式实现.起初学习HOOK API ...

  2. win10周年更新后程序各种卡死,进程无法结束怎么破?

    最近THINKPAD T460P更新了WIN10周年版后程序各种卡死,运行一段时间,各种程序就开始崩溃,进程无法结束,最终只能强制关机. 这个BUG微软已经确认了,安装了SSD+HDD双硬盘的WIN1 ...

  3. Windows下查看进程及结束进程命令[转]

    Windows下查看进程及结束进程命令 1)查看占用8080端口的进程号 >netstat –aon | findstr “8080” 结果:TCP    0.0.0.0:8080        ...

  4. Windows下查看8080进程及结束进程命令

    Windows下查看进程及结束进程命令 1)查看占用8080端口的进程号 >netstat –aon | findstr “8080” 结果:TCP    0.0.0.0:8080        ...

  5. Delphi监视进程并结束进程

    监视进程并结束进程在很多地方都用到这里借前人的经验写了个小例子: 以QQ的进程qq.exe为例 关键代码如下: function CheckTask(ExeFileName: string): Boo ...

  6. C#程序中:如何启用进程、结束进程、查找进程

    在启动某个程序之前,如果需要先检查改程序是否已经运行,可以查找进程里有没有这个进程,再根据查找进程后的结果进行相应的判断操作. 产找进程的范围是任务管理器中的进程列表.如果进程被隐藏了,结果……(我没 ...

  7. windows下查看进程及结束进程命令

    windows下查看进程及结束进程命令 1)查看占用8080端口的进程号 >netstat –aon | findstr “8080” 结果:TCP    0.0.0.0:8080        ...

  8. 性能优化-service进程防杀

    service作为后台服务,其重要性不言而喻,但很多时候service会被杀死,从而失去了我们原本想要其发挥的作用,在这种情况下我们该如何确保我们的service不被杀死就是本节需要讨论的内容了 se ...

  9. C程序的执行和当前进程的结束

    内核使程序执行的唯一方法,就是调用exec函数,这个函数又会启动一个C程序启动例程,这个启动例程是C程序的启动地址.负责调用main函数,并接受mainn函数的返回值. 使得进程结束的唯一方式是隐式的 ...

随机推荐

  1. Install Homebrew

    /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/instal ...

  2. hadoop 参数

    看<Hadoop:权威指南>的时候收集了书上写的一些需要优化的参数,记录了一下子,给大家分享一下吧. 1.mapred.task.timeout 任务超时时间,默认是10分钟 2.mapr ...

  3. Akka 编程: 什么是Actor

    上一篇我们简介了Actor系统.说明了Actor之间存在着层次关系,它也是构成Actor应用的最主要的单位. 本篇介绍Actor本身的一些基本概念.一个Actor包括了State(状态),Behavi ...

  4. 轻松学习之Linux教程二 一览纵山小:Linux操作系统具体解释

    本系列文章由@uid=hpw" style="padding:0px; margin:0px; color:rgb(255,0,0); text-decoration:none&q ...

  5. [从jQuery看JavaScript]-匿名函数与闭包

    jQuery片段: (function(){ //这里忽略jQuery所有实现 })(); 半年前初次接触jQuery的时候,我也像其他人一样很兴奋地想看看源码是什么样的.然而,在看到源码的第一眼,我 ...

  6. bcm56150_i2c驱动分析

    本文主要关注bsp中,关于smbus(系统管理总线,是i2c的子集)的配置过程,了解如如何配置i2c寄存器.所有发送的数据都会写在FIFO中,使能之后就发送出去.接收数据就从接收寄存器中读取.读取和发 ...

  7. wamp5多站点配置教程

    wamp5多站点配置教程 第一要做的是安装第二个apache服务一.找到Apache2的htppd.conf文件.例如:我的wamp是安装在G盘的,我的就是G:\wamp\Apache2\conf目录 ...

  8. error: expected declaration specifiers or '...' before 'xxxx'(xxxx是函数形参)

    今天汗颜了一大阵 早上,在编译我的源代码的时候竟然不通过编译,上个星期六也出现了这种情况,当时不知道怎么弄的后来又通过编译了,可能是原来的.o文件没有make clean 还保存在那里,以至于蒙过去了 ...

  9. (转)RGB接口和i80接口的区别

     在嵌入式的主流 LCD屏中主要支持两大类的硬件接口,一种是常见的RGB接口,另外一种是MCU接口.后面因为最早是针对单片机的领域在使用,因此得名.后在中低端手机大量使用,其主要特点是价格便宜的. M ...

  10. linux -- Linux下的五个查找命令:grep、find、locate、whereis、which

    1.grep grep(General Regular Expression Parser,通用规则表达式分析程序)是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来. 它的使 ...