进程防结束之PS_CROSS_THREAD_FLAGS_SYSTEM
2017-09-25 10:38
411 查看
有人投到黑防去了,不过黑防不厚道,竟然没给完整的代码,自己整理一份备用吧,驱网、DebugMan、邪八的那群人直接飘过吧。
这种方法的关键在于给线程的ETHREAD.CrossThreadFlags设置PS_CROSS_THREAD_FLAGS_SYSTEM值,这样其它进程就无法结束它了,包括IceSword、RkU。至于原理,那就先看看wrk里结束进程的那几个内核函数源码,NtTerminateProcess、PsTerminateProcess、PspTerminateProcess最终都是调用PspTerminateThreadByPointer来将每个线程杀死,而在PspTerminateThreadByPointer里,如果线程是被其它进程强x结束的,就会有个这样的判断:
if (IS_SYSTEM_THREAD
(Thread))
{
return STATUS_ACCESS_DENIED;
}
Thread类型是PETHREAD,IS_SYSTEM_THREAD是个宏,如下:
#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的源码:
NTSTATUS
PsTerminateSystemThread(
__in NTSTATUS ExitStatus
)
{
PETHREAD Thread = PsGetCurrentThread();
if (!IS_SYSTEM_THREAD
(Thread))
{
return STATUS_INVALID_PARAMETER;
}
return PspTerminateThreadByPointer
(Thread, ExitStatus, TRUE);
}
这里也用到了IS_SYSTEM_THREAD,那么也一定会有定位CrossThreadFlags的代码,如下:
kd> u PsTerminateSystemThread
nt!PsTerminateSystemThread:
805c89f8 8bff mov
edi,edi
805c89fa
55 push ebp
805c89fb 8bec mov
ebp,esp
805c89fd 64a124010000 mov
eax,dword
ptr
fs:[00000124h]
805c8a03 f6804802000010 test byte
ptr
[eax+248h],10h
805c8a0a
7507 jne nt!PsTerminateSystemThread+0x1b
(805c8a13)
805c8a0c b80d0000c0 mov
eax,0C000000Dh
805c8a11 eb09 jmp nt!PsTerminateSystemThread+0x24
(805c8a1c)
805c8a13 ff7508 push dword
ptr
[ebp+8]
805c8a16
50 push eax
805c8a17 e828fcffff call nt!PspTerminateThreadByPointer
(805c8644)
805c8a1c 5d pop
ebp
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里的偏移了。
得到了偏移,下面就是写代码了,驱动部分:
#include <ntifs.h>
#include <ntddk.h>
#define PS_CROSS_THREAD_FLAGS_SYSTEM 0x00000010UL //form wrk 1.2 base\ntos\inc\ps.h
#define IOCTL_THREAD_PROTECT CTL_CODE(FILE_DEVICE_UNKNOWN,
0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
UNICODE_STRING usSymLink;
RtlInitUnicodeString(&usSymLink, L"\\??\\ThreadProtect");
IoDeleteSymbolicLink(&usSymLink);
IoDeleteDevice(pDriverObject->DeviceObject);
}
NTSTATUS DispatchCreateClose(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
pIrp->IoStatus.Status
= STATUS_SUCCESS;
pIrp->IoStatus.Information
= 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS DispatchControl(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
NTSTATUS nRet = STATUS_UNSUCCESSFUL;
ULONG_PTR uInf = 0;
PIO_STACK_LOCATION pIoStack = IoGetCurrentIrpStackLocation(pIrp);
PVOID pSysBuff = pIrp->AssociatedIrp.SystemBuffer;
switch (pIoStack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_THREAD_PROTECT:
PETHREAD pEThread;
PsLookupThreadByThreadId(HANDLE(*(PULONG)pSysBuff),
&pEThread);
UNICODE_STRING usName;
RtlInitUnicodeString(&usName, L"PsTerminateSystemThread");
PUSHORT pOffset =
(PUSHORT)MmGetSystemRoutineAddress(&usName);
//search "test byte ptr [eax+xxxxxxxx],10h",hex:f680xxxxxxxx10
while (*pOffset
!=
0x80f6)
pOffset = PUSHORT((PUCHAR)pOffset
+ 1);
PULONG pFlags = PULONG((PUCHAR)pEThread
+ *(PULONG)(pOffset
+ 1));
DbgPrint("pOffset:%08x, CrossFlagOffset:%08x\r\n", pOffset,
*(PULONG)(pOffset
+ 1));
*pFlags |= PS_CROSS_THREAD_FLAGS_SYSTEM; //set PS_CROSS_THREAD_FLAGS_SYSTEM bit
nRet = STATUS_SUCCESS;
uInf = 0;
break;
}
pIrp->IoStatus.Status
= nRet;
pIrp->IoStatus.Information
= uInf;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return nRet;
}
extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath)
{
pDriverObject->DriverUnload
= DriverUnload;
pDriverObject->MajorFunction[IRP_MJ_CREATE]
= DispatchCreateClose;
pDriverObject->MajorFunction[IRP_MJ_CLOSE]
= DispatchCreateClose;
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]
= DispatchControl;
UNICODE_STRING usDeviceName;
RtlInitUnicodeString(&usDeviceName, L"\\Device\\ThreadProtect");
NTSTATUS nRet;
PDEVICE_OBJECT pDeviceObject;
nRet = IoCreateDevice(pDriverObject,
0, &usDeviceName, FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN, FALSE,
&pDeviceObject);
if (!NT_SUCCESS(nRet))
return nRet;
UNICODE_STRING usSymLink;
RtlInitUnicodeString(&usSymLink, L"\\??\\ThreadProtect");
nRet = IoCreateSymbolicLink(&usSymLink,
&usDeviceName);
if (!NT_SUCCESS(nRet))
{
IoDeleteDevice(pDeviceObject);
return nRet;
}
return STATUS_SUCCESS;
}
这段代码要解释的都在上面了。EXE部分的代码就不用帖了,只要将每个线程的ID通过DeviceIoControl传入驱动即可:
#define IOCTL_THREAD_PROTECT CTL_CODE(FILE_DEVICE_UNKNOWN,
0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
DeviceIoControl(hDevice, IOCTL_THREAD_PROTECT,
&nThreadId, sizeof(nThreadId),
0, 0,
&nByteRet, 0);
点击这里下载文件: ThreadProtect.rar
运行后果自行负责,运行不了自行想办法到注册表里删除先前的ThreadProtect键值。
最后,怎么结束用这种方法保护的进程?方法大大的有,插入APC,然后PspExitThread就不会经过PspTerminateThreadByPointer了。
jpg 改 rar
这种方法的关键在于给线程的ETHREAD.CrossThreadFlags设置PS_CROSS_THREAD_FLAGS_SYSTEM值,这样其它进程就无法结束它了,包括IceSword、RkU。至于原理,那就先看看wrk里结束进程的那几个内核函数源码,NtTerminateProcess、PsTerminateProcess、PspTerminateProcess最终都是调用PspTerminateThreadByPointer来将每个线程杀死,而在PspTerminateThreadByPointer里,如果线程是被其它进程强x结束的,就会有个这样的判断:
if (IS_SYSTEM_THREAD
(Thread))
{
return STATUS_ACCESS_DENIED;
}
Thread类型是PETHREAD,IS_SYSTEM_THREAD是个宏,如下:
#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的源码:
NTSTATUS
PsTerminateSystemThread(
__in NTSTATUS ExitStatus
)
{
PETHREAD Thread = PsGetCurrentThread();
if (!IS_SYSTEM_THREAD
(Thread))
{
return STATUS_INVALID_PARAMETER;
}
return PspTerminateThreadByPointer
(Thread, ExitStatus, TRUE);
}
这里也用到了IS_SYSTEM_THREAD,那么也一定会有定位CrossThreadFlags的代码,如下:
kd> u PsTerminateSystemThread
nt!PsTerminateSystemThread:
805c89f8 8bff mov
edi,edi
805c89fa
55 push ebp
805c89fb 8bec mov
ebp,esp
805c89fd 64a124010000 mov
eax,dword
ptr
fs:[00000124h]
805c8a03 f6804802000010 test byte
ptr
[eax+248h],10h
805c8a0a
7507 jne nt!PsTerminateSystemThread+0x1b
(805c8a13)
805c8a0c b80d0000c0 mov
eax,0C000000Dh
805c8a11 eb09 jmp nt!PsTerminateSystemThread+0x24
(805c8a1c)
805c8a13 ff7508 push dword
ptr
[ebp+8]
805c8a16
50 push eax
805c8a17 e828fcffff call nt!PspTerminateThreadByPointer
(805c8644)
805c8a1c 5d pop
ebp
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里的偏移了。
得到了偏移,下面就是写代码了,驱动部分:
#include <ntifs.h>
#include <ntddk.h>
#define PS_CROSS_THREAD_FLAGS_SYSTEM 0x00000010UL //form wrk 1.2 base\ntos\inc\ps.h
#define IOCTL_THREAD_PROTECT CTL_CODE(FILE_DEVICE_UNKNOWN,
0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
UNICODE_STRING usSymLink;
RtlInitUnicodeString(&usSymLink, L"\\??\\ThreadProtect");
IoDeleteSymbolicLink(&usSymLink);
IoDeleteDevice(pDriverObject->DeviceObject);
}
NTSTATUS DispatchCreateClose(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
pIrp->IoStatus.Status
= STATUS_SUCCESS;
pIrp->IoStatus.Information
= 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS DispatchControl(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
NTSTATUS nRet = STATUS_UNSUCCESSFUL;
ULONG_PTR uInf = 0;
PIO_STACK_LOCATION pIoStack = IoGetCurrentIrpStackLocation(pIrp);
PVOID pSysBuff = pIrp->AssociatedIrp.SystemBuffer;
switch (pIoStack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_THREAD_PROTECT:
PETHREAD pEThread;
PsLookupThreadByThreadId(HANDLE(*(PULONG)pSysBuff),
&pEThread);
UNICODE_STRING usName;
RtlInitUnicodeString(&usName, L"PsTerminateSystemThread");
PUSHORT pOffset =
(PUSHORT)MmGetSystemRoutineAddress(&usName);
//search "test byte ptr [eax+xxxxxxxx],10h",hex:f680xxxxxxxx10
while (*pOffset
!=
0x80f6)
pOffset = PUSHORT((PUCHAR)pOffset
+ 1);
PULONG pFlags = PULONG((PUCHAR)pEThread
+ *(PULONG)(pOffset
+ 1));
DbgPrint("pOffset:%08x, CrossFlagOffset:%08x\r\n", pOffset,
*(PULONG)(pOffset
+ 1));
*pFlags |= PS_CROSS_THREAD_FLAGS_SYSTEM; //set PS_CROSS_THREAD_FLAGS_SYSTEM bit
nRet = STATUS_SUCCESS;
uInf = 0;
break;
}
pIrp->IoStatus.Status
= nRet;
pIrp->IoStatus.Information
= uInf;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return nRet;
}
extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath)
{
pDriverObject->DriverUnload
= DriverUnload;
pDriverObject->MajorFunction[IRP_MJ_CREATE]
= DispatchCreateClose;
pDriverObject->MajorFunction[IRP_MJ_CLOSE]
= DispatchCreateClose;
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]
= DispatchControl;
UNICODE_STRING usDeviceName;
RtlInitUnicodeString(&usDeviceName, L"\\Device\\ThreadProtect");
NTSTATUS nRet;
PDEVICE_OBJECT pDeviceObject;
nRet = IoCreateDevice(pDriverObject,
0, &usDeviceName, FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN, FALSE,
&pDeviceObject);
if (!NT_SUCCESS(nRet))
return nRet;
UNICODE_STRING usSymLink;
RtlInitUnicodeString(&usSymLink, L"\\??\\ThreadProtect");
nRet = IoCreateSymbolicLink(&usSymLink,
&usDeviceName);
if (!NT_SUCCESS(nRet))
{
IoDeleteDevice(pDeviceObject);
return nRet;
}
return STATUS_SUCCESS;
}
这段代码要解释的都在上面了。EXE部分的代码就不用帖了,只要将每个线程的ID通过DeviceIoControl传入驱动即可:
#define IOCTL_THREAD_PROTECT CTL_CODE(FILE_DEVICE_UNKNOWN,
0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
DeviceIoControl(hDevice, IOCTL_THREAD_PROTECT,
&nThreadId, sizeof(nThreadId),
0, 0,
&nByteRet, 0);
点击这里下载文件: ThreadProtect.rar
运行后果自行负责,运行不了自行想办法到注册表里删除先前的ThreadProtect键值。
最后,怎么结束用这种方法保护的进程?方法大大的有,插入APC,然后PspExitThread就不会经过PspTerminateThreadByPointer了。
jpg 改 rar
相关文章推荐
- 进程防结束之PS_CROSS_THREAD_FLAGS_SYSTEM
- CreateThread,AfxBeginThread,PsCreateSystemThread
- 驱动开发之 创建线程函数PsCreateSystemThread
- LzmTW.uSystem.uThreading+CrossThread
- system函数不用等待子进程结束
- System.Windows.Forms.Form.CheckForIllegalCrossThreadCalls = false;
- PsCreateSystemThread创建系统线程
- 驱动开发之 创建线程函数PsCreateSystemThread
- C# 关闭进程的时候总是捕捉到System.Threading.ThreadAbortException: 正在中止线程
- 通过PspTerminateThreadByPointer结束进程
- 21.driverbase-多线程PsCreateSystemThread
- PsCreateSystemThread函数说明
- thread7 进程结束时机
- C# 关闭进程的时候总是捕捉到System.Threading.ThreadAbortException: 正在中止线程
- 使用ps和kill查找并结束Linux进程
- PsCreateSystemThread
- 【转发】Cross-thread operation not valid: Control 'progressBar1' accessed from a thread other than the thread it was created on
- 【ps】查看进程
- Linux下使用ps命令来查看Oracle相关的进程
- Ubuntu 15.04 中结束进程的命令