进程防结束之PS_CROSS_THREAD_FLAGS_SYSTEM

有人投到黑防去了,不过黑防不厚道,竟然没给完整的代码,自己整理一份备用吧,驱网、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 ) ! = 0 )

也就是说当线程的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. 805c89fa 55               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. 805c8a0a 7507             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 [ ebp + 8 ]
  12. 805c8a16 50               push     eax
  13. 805c8a17 e828fcffff       call    nt!PspTerminateThreadByPointer (805c8644 )
  14. 805c8a1c 5d               pop     ebp
  15. 805c8a1d c20400           ret     4
很明显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 = 0;
  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 = 0;
  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 + 1 );
  43.     PULONG pFlags = PULONG ( (PUCHAR )pEThread + * (PULONG ) (pOffset + 1 ) );
  44.     DbgPrint ( "pOffset:%08x, CrossFlagOffset:%08x\r\n", pOffset, * (PULONG ) (pOffset + 1 ) );
  45.     *pFlags |= PS_CROSS_THREAD_FLAGS_SYSTEM;   //set PS_CROSS_THREAD_FLAGS_SYSTEM bit
  46.     nRet = STATUS_SUCCESS;
  47.     uInf = 0;
  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, 0, &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 ), 0, 0, &nByteRet, 0 );

 


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

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


加粗 (Ctrl+B)斜体 (Ctrl+I)下划线 (Ctrl+U)字体颜色超链接 (Ctrl+L)取消超链接表情关于 xhEditor
 


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值