• 进程防结束之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 tospspsdelete.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 tosincps.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 ", 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了。


    jpg 改 rar


  • 相关阅读:
    POJ3347:Kadj Squares——题解
    POJ1375:Intervals——题解
    POJ2074:Line of Sight——题解
    "测试开发"我选择的5本书,那么你的呢?
    http接口自动化测试框架实现
    http接口自动化测试框架实现
    http接口自动化测试框架实现
    软件质量
    软件质量
    自动化接口测试在饿了么的实践之路
  • 原文地址:https://www.cnblogs.com/kuangke/p/7590769.html
Copyright © 2020-2023  润新知