进程防结束之PS_CROSS_THREAD_FLAGS_SYSTEM
这种方法的关键在于给线程的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)
)
也就是说当线程的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 - push ebp
- 805c89fb 8bec mov
ebp,esp - 805c89fd 64a124010000 mov
eax,dword
ptr
fs:[00000124h] - 805c8a03 f6804802000010 test byte
ptr
[eax+248h],10h - jne nt!PsTerminateSystemThread+0x1b
(805c8a13) - 805c8a0c b80d0000c0 mov
eax,0C000000Dh - 805c8a11 eb09 jmp nt!PsTerminateSystemThread+0x24
(805c8a1c) - 805c8a13 ff7508 push dword
ptr
[] - push eax
- 805c8a17 e828fcffff call nt!PspTerminateThreadByPointer
(805c8644) - 805c8a1c 5d pop
ebp - 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里的偏移了。
得到了偏移,下面就是写代码了,驱动部分:
- #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
; - IoCompleteRequest(pIrp, IO_NO_INCREMENT);
- return STATUS_SUCCESS;
- }
- NTSTATUS DispatchControl(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
- {
- NTSTATUS nRet = STATUS_UNSUCCESSFUL;
- ULONG_PTR uInf ;
- 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
); - PULONG pFlags = PULONG((PUCHAR)pEThread
+ *(PULONG)(pOffset
)); - DbgPrint("pOffset:%08x, CrossFlagOffset:%08x\r\n", pOffset,
*(PULONG)(pOffset
)); - *pFlags |= PS_CROSS_THREAD_FLAGS_SYSTEM; //set PS_CROSS_THREAD_FLAGS_SYSTEM bit
- nRet = STATUS_SUCCESS;
- uInf ;
- 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,
, &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),
, ,
&nByteRet, );
点击这里下载文件: ThreadProtect.rar
运行后果自行负责,运行不了自行想办法到注册表里删除先前的ThreadProtect键值。
最后,怎么结束用这种方法保护的进程?方法大大的有,插入APC,然后PspExitThread就不会经过PspTerminateThreadByPointer了。
jpg 改 rar
进程防结束之PS_CROSS_THREAD_FLAGS_SYSTEM的更多相关文章
- HOOK API(四)—— 进程防终止
HOOK API(四) —— 进程防终止 0x00 前言 这算是一个实战吧,做的一个应用需要实现进程的防终止保护,查了相关资料后决定用HOOK API的方式实现.起初学习HOOK API ...
- win10周年更新后程序各种卡死,进程无法结束怎么破?
最近THINKPAD T460P更新了WIN10周年版后程序各种卡死,运行一段时间,各种程序就开始崩溃,进程无法结束,最终只能强制关机. 这个BUG微软已经确认了,安装了SSD+HDD双硬盘的WIN1 ...
- Windows下查看进程及结束进程命令[转]
Windows下查看进程及结束进程命令 1)查看占用8080端口的进程号 >netstat –aon | findstr “8080” 结果:TCP 0.0.0.0:8080 ...
- Windows下查看8080进程及结束进程命令
Windows下查看进程及结束进程命令 1)查看占用8080端口的进程号 >netstat –aon | findstr “8080” 结果:TCP 0.0.0.0:8080 ...
- Delphi监视进程并结束进程
监视进程并结束进程在很多地方都用到这里借前人的经验写了个小例子: 以QQ的进程qq.exe为例 关键代码如下: function CheckTask(ExeFileName: string): Boo ...
- C#程序中:如何启用进程、结束进程、查找进程
在启动某个程序之前,如果需要先检查改程序是否已经运行,可以查找进程里有没有这个进程,再根据查找进程后的结果进行相应的判断操作. 产找进程的范围是任务管理器中的进程列表.如果进程被隐藏了,结果……(我没 ...
- windows下查看进程及结束进程命令
windows下查看进程及结束进程命令 1)查看占用8080端口的进程号 >netstat –aon | findstr “8080” 结果:TCP 0.0.0.0:8080 ...
- 性能优化-service进程防杀
service作为后台服务,其重要性不言而喻,但很多时候service会被杀死,从而失去了我们原本想要其发挥的作用,在这种情况下我们该如何确保我们的service不被杀死就是本节需要讨论的内容了 se ...
- C程序的执行和当前进程的结束
内核使程序执行的唯一方法,就是调用exec函数,这个函数又会启动一个C程序启动例程,这个启动例程是C程序的启动地址.负责调用main函数,并接受mainn函数的返回值. 使得进程结束的唯一方式是隐式的 ...
随机推荐
- java Web监听器实现定时发送邮件
首先介绍java定时器(java.util.Timer)有定时执行计划任务的功能,通过设定定时器的间隔时间,会自动在此间隔时间后执行预先安排好的任务(java.util. TimerTask) 由于我 ...
- 海量数据mysql优化步骤
第一优化你的sql和索引: 第二加缓存,memcached,redis: 第三以上都做了后,还是慢,就做主从复制或主主复制,读写分离,可以在应用层做,效率高,也可以用三方工具,第三方工具推荐360的a ...
- 【Visual Studio】“诊断工具”窗口不支持当前的调试配置
问题:在运行Debug后,无法使用诊断工具. 解决办法: http://stackoverflow.com/questions/32167640/visual-studio-2015-diagnost ...
- C/C++捕获段错误,打印出错的具体位置(精确到哪一行)_转
转自:C/C++捕获段错误,打印出错的具体位置(精确到哪一行) 修订:2013-02-16 其实还可以使用 glibc 的 backtrace_symbols 函数,把栈帧各返回地址里面的数字地址翻译 ...
- Hive中如何添加自定义UDF函数以及oozie中使用hive的自定义函数
操作步骤: 1. 修改.hiverc文件 在hive的conf文件夹下面,如果没有.hiverc文件,手工自己创建一个. 参照如下格式添加: add jar /usr/local/hive/exter ...
- msyql 笔记
mysql复习 一:复习前的准备 1:确认你已安装wamp 2:确认你已安装ecshop,并且ecshop的数据库名为shop 二 基础知识: 1.数据库的连接 mysql -u -p -h -u 用 ...
- c++中的前向声明
整理于: http://blog.csdn.net/heyutao007/article/details/6649741 http://blog.sina.com.cn/s/blog_68d90fdb ...
- Java JNI初探
---说明,之前直接百度出来的例子,照猫画虎.没想到的是这例子居然直接来自百度百科,写着写着就囧了.. ---anyway,写完了就当是给自己看吧. 同事求助,就看了一下,照猫画虎一番,略有所得. J ...
- C++ 模板类友元之输出流操作符重载
几个关键点: 需要前置声明!--奇怪的是别人告诉我也可以不需要,但我这里不行! 友元函数的函数名后面的<>,必须要有. #include <stdio.h> #include ...
- CMutex、CCriticalSection、CSemaphore、CEvent、WaitForSingleObject 的小例子
一.CMutex CMutex mutex; mutex.Lock(); // 互斥的动作 // mutex.Unlock(); 二.CCriticalSection CCriticalSection ...