这种方法的关键在于给线程的ETHREAD.CrossThreadFlags设置PS_CROSS_THREAD_FLAGS_SYSTEM值,这样其它进程就无法结束它了,包括IceSword、RkU。至于原理,那就先看看wrk里结束进程的那几个内核函数源码,NtTerminateProcess、PsTerminateProcess、PspTerminateProcess最终都是调用PspTerminateThreadByPointer来将每个线程杀死,而在PspTerminateThreadByPointer里,如果线程是被其它进程强x结束的,就会有个这样的判断:
也就是说当线程的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的源码:
很明显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;
-
}