使用 PspTerminateThreadByPointer 强制结束进程

Win64 驱动内核编程-26.强制结束进程 强制结束进程     依然已经走到驱动这一层了,那么通常结束掉一个进程不是什么难的事情。同时因为win64 位的各种保护,导致大家慢慢的已经不敢HOOK了,当然这指的是产品。作为学习和破解的话当然可以尝试各种hook。目前来说很多杀软进程保护都是通过回调了保护的,简单,稳定,安全。So,强制结束进程会比当年简单很多。 首先就是上一个最基本的驱动里结束进程的方法:   1.直接调用ZwTer 阅读详情

实现过程

我们知道,线程是进程中执行运算的最小单位,是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。

也就是说,当一个进程中的所有线程都被结束的时候,这个进程也就没有了存在的意义,也随之结束了。这,便是我们本文介绍的这种强制杀进程的实现原理,即把进程中的线程都杀掉,从而让进程消亡,实现间接杀进程的效果。

Windows 提供了一个导出的内核函数 PsTerminateSystemThread 来帮助我们结束线程,所以,类似 360、QQ 等也会对重点监测该函数,防止结束自己的线程。我们通过逆向 PsTerminateSystemThread 函数,可以发现该函数实际上调用了未导出的内核函数 PspTerminateThreadByPointer 来实现的结束线程的操作。所以,我们可以通过查找 PspTerminateThreadByPointer 函数地址,调用直接它来结束线程,就可以绕过绝大部分的进程保护,实现强制杀进程。

PspTerminateThreadByPointer

    NTSTATUS PspTerminateThreadByPointer (
          PETHREAD pEThread, 
          NTSTATUS ntExitCode, 
          BOOLEAN bDirectTerminate
     );

但要注意,PspTerminateThreadByPointer 的函数指针的声明的调用约定:

    // 32 位
    typedef NTSTATUS(*PSPTERMINATETHREADBYPOINTER_X86) (
          PETHREAD pEThread, 
          NTSTATUS ntExitCode, 
          BOOLEAN bDirectTerminate
     );
    // 64 位
    typedef NTSTATUS(__fastcall *PSPTERMINATETHREADBYPOINTER_X64) (
          PETHREAD pEThread, 
          NTSTATUS ntExitCode, 
          BOOLEAN bDirectTerminate
     );

其中,PsTerminateSystemThread 里会调用 PspTerminateThreadByPointer 函数。我们使用 WinDbg 逆向 Win8.1 x64 里的 PsTerminateSystemThread 函数,如下所示:

    nt!PsTerminateSystemThread:
    fffff800`83904518 8bd1            mov     edx,ecx
    fffff800`8390451a 65488b0c2588010000 mov   rcx,qword ptr gs:[188h]
    fffff800`83904523 f7417400080000  test    dword ptr [rcx+74h],800h
    fffff800`8390452a 7408            je      nt!PsTerminateSystemThread+0x1c (fffff800`83904534)
    fffff800`8390452c 41b001          mov     r8b,1
    fffff800`8390452f e978d9fcff      jmp     nt!PspTerminateThreadByPointer (fffff800`838d1eac)
    fffff800`83904534 b80d0000c0      mov     eax,0C000000Dh
    fffff800`83904539 c3              ret

由上面代码可以知道,我们可以通过扫描 PsTerminateSystemThread 内核函数中的特征码,从而获取 PspTerminateThreadByPointer 函数的偏移,再根据偏移计算出该函数的地址。其中,不同系统中的特征码也会不同,下面是我使用 WinDbg 逆向各个系统上总结的特征码的情况:
在这里插入图片描述
那么,我们强制杀进程的实现原理为:

  • 首先,根据特征码扫描内存,获取 PspTerminateThreadByPointer 函数地址

  • 然后,调用 PsLookupProcessByProcessId 函数,根据将要结束进程 ID 获取对应的进程结构对象 EPROCESS

  • 接着,遍历所有的线程 ID,并调用 PsLookupThreadByThreadId 函数根据线程 ID 获取对应的线程结构 ETHREAD

  • 然后,调用函数 PsGetThreadProcess 获取线程结构 ETHREAD 对应的进程结构 EPROCESS

  • 这时,我们可以通过判断该进程是不是我们指定要结束的进程,若是,则调用 PspTerminateThreadByPointer 函数结束线程;否则,继续遍历下一个线程 ID

  • 重复上述 3、4、5 的操作,直到线程遍历完毕

这样,我们就可以查杀指定进程的所有线程,线程被结束之后,进程也随之结束。注意的是,当调用 PsLookupProcessByProcessId 和 PsLookupThreadByThreadId 等 LookupXXX 系列函数获取对象的时候,都需要调用 ObDereferenceObject 函数释放对象,否则在某些时候会造成蓝屏。

编码实现

强制结束指定进程:

    // 强制结束指定进程
    NTSTATUS ForceKillProcess(HANDLE hProcessId)
    {
        PVOID pPspTerminateThreadByPointerAddress = NULL;
        PEPROCESS pEProcess = NULL;
        PETHREAD pEThread = NULL;
        PEPROCESS pThreadEProcess = NULL;
        NTSTATUS status = STATUS_SUCCESS;
        ULONG i = 0;
    #ifdef _WIN64
        // 64 位
        typedef NTSTATUS(__fastcall *PSPTERMINATETHREADBYPOINTER) (PETHREAD pEThread, NTSTATUS ntExitCode, BOOLEAN bDirectTerminate);
    #else
        // 32 位
        typedef NTSTATUS(*PSPTERMINATETHREADBYPOINTER) (PETHREAD pEThread, NTSTATUS ntExitCode, BOOLEAN bDirectTerminate);
    #endif
        // 获取 PspTerminateThreadByPointer 函数地址
        pPspTerminateThreadByPointerAddress = GetPspLoadImageNotifyRoutine();
        if (NULL == pPspTerminateThreadByPointerAddress)
        {
            ShowError("GetPspLoadImageNotifyRoutine", 0);
            return FALSE;
        }
        // 获取结束进程的进程结构对象EPROCESS
        status = PsLookupProcessByProcessId(hProcessId, &pEProcess);
        if (!NT_SUCCESS(status))
        {
            ShowError("PsLookupProcessByProcessId", status);
            return status;
        }
        // 遍历所有线程, 并结束所有指定进程的线程
        for (i = 4; i < 0x80000; i = i + 4)
        {
            status = PsLookupThreadByThreadId((HANDLE)i, &pEThread);
            if (NT_SUCCESS(status))
            {
                // 获取线程对应的进程结构对象
                pThreadEProcess = PsGetThreadProcess(pEThread);
                // 结束指定进程的线程
                if (pEProcess == pThreadEProcess)
                {
                    ((PSPTERMINATETHREADBYPOINTER)pPspTerminateThreadByPointerAddress)(pEThread, 0, 1);
                    DbgPrint("PspTerminateThreadByPointer Thread:%d\n", i);
                }
                // 凡是Lookup...,必需Dereference,否则在某些时候会造成蓝屏
                ObDereferenceObject(pEThread);
            }
        }
        // 凡是Lookup...,必需Dereference,否则在某些时候会造成蓝屏
        ObDereferenceObject(pEProcess);
        return status;
    }

获取 PspTerminateThreadByPointer 函数地址:

    // 获取 PspTerminateThreadByPointer 函数地址
    PVOID GetPspLoadImageNotifyRoutine()
    {
        PVOID pPspTerminateThreadByPointerAddress = NULL;
        RTL_OSVERSIONINFOW osInfo = { 0 };
        UCHAR pSpecialData[50] = { 0 };
        ULONG ulSpecialDataSize = 0;
        // 获取系统版本信息, 判断系统版本
        RtlGetVersion(&osInfo);
        if (6 == osInfo.dwMajorVersion)
        {
            if (1 == osInfo.dwMinorVersion)
            {
                // Win7
    #ifdef _WIN64
                // 64 位
                // E8
                pSpecialData[0] = 0xE8;
                ulSpecialDataSize = 1;
    #else
                // 32 位
                // E8
                pSpecialData[0] = 0xE8;
                ulSpecialDataSize = 1;
    #endif    
            }
            else if (2 == osInfo.dwMinorVersion)
            {
                // Win8
    #ifdef _WIN64
                // 64 位
    #else
                // 32 位
    #endif
            }
            else if (3 == osInfo.dwMinorVersion)
            {
                // Win8.1
    #ifdef _WIN64
                // 64 位
                // E9
                pSpecialData[0] = 0xE9;
                ulSpecialDataSize = 1;
    #else
                // 32 位
                // E8
                pSpecialData[0] = 0xE8;
                ulSpecialDataSize = 1;
    #endif            
            }
        }
        else if (10 == osInfo.dwMajorVersion)
        {
            // Win10
    #ifdef _WIN64
            // 64 位
            // E9
            pSpecialData[0] = 0xE9;
            ulSpecialDataSize = 1;
    #else
            // 32 位
            // E8
            pSpecialData[0] = 0xE8;
            ulSpecialDataSize = 1;
    #endif
        }
        // 根据特征码获取地址
        pPspTerminateThreadByPointerAddress = SearchPspTerminateThreadByPointer(pSpecialData, ulSpecialDataSize);
        return pPspTerminateThreadByPointerAddress;
    }

根据特征码获取 PspTerminateThreadByPointer 数组地址:

    // 根据特征码获取 PspTerminateThreadByPointer 数组地址
    PVOID SearchPspTerminateThreadByPointer(PUCHAR pSpecialData, ULONG ulSpecialDataSize)
    {
        UNICODE_STRING ustrFuncName;
        PVOID pAddress = NULL;
        LONG lOffset = 0;
        PVOID pPsTerminateSystemThread = NULL;
        PVOID pPspTerminateThreadByPointer = NULL;
        // 先获取 PsTerminateSystemThread 函数地址
        RtlInitUnicodeString(&ustrFuncName, L"PsTerminateSystemThread");
        pPsTerminateSystemThread = MmGetSystemRoutineAddress(&ustrFuncName);
        if (NULL == pPsTerminateSystemThread)
        {
            ShowError("MmGetSystemRoutineAddress", 0);
            return pPspTerminateThreadByPointer;
        }
        // 然后, 查找 PspTerminateThreadByPointer 函数地址
        pAddress = SearchMemory(pPsTerminateSystemThread,
            (PVOID)((PUCHAR)pPsTerminateSystemThread + 0xFF),
            pSpecialData, ulSpecialDataSize);
        if (NULL == pAddress)
        {
            ShowError("SearchMemory", 0);
            return pPspTerminateThreadByPointer;
        }
        // 先获取偏移, 再计算地址
        lOffset = *(PLONG)pAddress;
        pPspTerminateThreadByPointer = (PVOID)((PUCHAR)pAddress + sizeof(LONG) + lOffset);
        return pPspTerminateThreadByPointer;
    }

指定内存区域的特征码扫描:

    // 指定内存区域的特征码扫描
    PVOID SearchMemory(PVOID pStartAddress, PVOID pEndAddress, PUCHAR pMemoryData, ULONG ulMemoryDataSize)
    {
        PVOID pAddress = NULL;
        PUCHAR i = NULL;
        ULONG m = 0;
        // 扫描内存
        for (i = (PUCHAR)pStartAddress; i < (PUCHAR)pEndAddress; i++)
        {
            // 判断特征码
            for (m = 0; m < ulMemoryDataSize; m++)
            {
                if (*(PUCHAR)(i + m) != pMemoryData[m])
                {
                    break;
                }
            }
            // 判断是否找到符合特征码的地址
            if (m >= ulMemoryDataSize)
            {
                // 找到特征码位置, 获取紧接着特征码的下一地址
                pAddress = (PVOID)(i + ulMemoryDataSize);
                break;
            }
        }
        return pAddress;
    }
HDRP shader 获取阴影(Custom Pass) Unity:2021.3.0f1 HDRP:12.1.6 阅读详情

相关推荐

工业级隔离CAN FD收发器ISO1042设计实战:从原理到EMC防护

在工业自动化与伺服驱动系统中,CAN总线是实现设备间可靠通信的关键技术。其核心原理是通过差分信号传输和仲裁机制,在复杂电磁环境中实现多节点实时数据交换。这项技术的核心价值在于为高噪声、高干扰的工业现场提供了稳定、确定性的通信基础,是构建分布式控制系统不可或缺的环节。其典型应用场景包括新能源汽车电池管理、工业机器人伺服控制以及光伏逆变器集群通信等。本文将聚焦于如何通过高性能隔离CAN FD收发器(如TI的ISO1042)来应对地电位差、浪涌和高压串扰等现场挑战,深入解析其集成的电气隔离、±70V总线故障保护和

weixin_26834815的博客 381

驱动开发:内核强制结束进程运行

内核态,但有时我们不得不想办法结束掉这些特殊的进程,当然某些正常进程在特殊状态下也会无法被正常结束,此时使用驱动前行在内核态将其结束掉就变得很有用了,驱动结束进程有多种方法。存在时则可以看到结束效果,当然这种方式只是在内核层面调用了结束进程函数,其本质上还是正常结束,只是这种方式权限要大一些仅此而已。没有被导出,所以我们需要动态的这个内存地址,然后动态调用即可,这个寻找方法可以总结为以下步骤。第二种方法,其原理就是将进程内的线程全部结束掉从而让进程自动结束,由于。首先是第一种方法结束进程,封装实现。

微软技术分享 1万+

Android Camera Sensor HDR详解

本文详细介绍了Android相机传感器(Sensor)中实现高动态范围(HDR)采集的各种技术方式。主要内容包括: Sensor HDR技术分类 帧内HDR(Single-Frame HDR):在同一帧同一像素内完成多增益采集,无运动伪影和帧率损失,包括DAG(双模拟增益)、DCG(双转换增益)等技术 帧间HDR(Multi-Frame HDR):通过多帧曝光实现,如DOL(数字重叠)、Staggered HDR等 混合HDR:结合多种技术的复合方案 详细技术原理 重点解析了DAG和DCG两种主流帧内HDR

DU_YULIN的博客 357

使用PsTerminateThreadByPointer强制结束进程

该函数会在内部检查是否是系统线程,如果是系统线程不会结束它. #include<ntifs.h> #include <ntddk.h> //根据进程结构获得进程名指针 需要自己申明一下。 ULONG64 g_kernelModuleBase = 0; typedef struct _LDR_DATA_TABLE_ENTRY { LIST_ENTRY InLoadOrderLinks; LIST_ENTRY InMemoryOrderLinks; LIST_ENTRY I

qq_41490873的博客 659

Python高效转换病理图像:从mrxs到SVS的完整实践指南

本文提供了使用Python将数字病理切片从mrxs格式高效转换为SVS格式的完整实践指南。针对mrxs格式兼容性差的问题,文章详细解析了基于openslide和tifffile库的核心转换流程,并重点分享了应对大内存消耗的优化方案与流式处理技巧,确保转换后的SVS文件保留多分辨率金字塔结构,兼容主流病理分析工具。

weixin_29051811的博客 547

基于Simulink的直流电机双闭环调速系统抗扰动仿真与参数优化

本文详细介绍了基于Simulink的直流电机双闭环调速系统仿真与参数优化方法。通过构建转速外环与电流内环的仿真模型,阐述了利用工程设计法整定PI参数的核心步骤,并重点探讨了如何优化系统参数以增强其抗负载突变等扰动的能力,实现快速、平稳的调速性能。

weixin_29061997的博客 191

两个强制结束进程的方法

这两个函数分别用于终止进程和线程,但由于未公开导出,需要通过逆向工程获取地址。

(*/ω\*) 1407

吉林大学2016级唐班c语言期末考试B卷

` #include<stdio.h> #include<stdlib.h> //双指针法,每次从a,b中选一个最大的数,从后向前一次放在数组a中 int merge(int *a,int m,int *b,int n){ int i=m-1,j=n-1,k=m+n-1; while(i>=0&&j>=0){ if(a[i]>b[j])a[...

weixin_42339173的博客 1195

通过PspTerminateThreadByPointer结束进程

 很早前写的代码了,免得腐烂了,贴出来这个思想是在读了PJF牛人 "终止进程内幕" 后才晓得基本思想就是用户态将欲结束的进程PID传递到内核驱动,驱动通过PsLookupProcessByProcessId得到进程的EPROCESS结构,再通过EPROCESS结构找到线程的链表头,遍历这个链表,逐一调用PspTerminateThreadByPointer,将其一个一个的KILL掉这里有三个问

4353

Vue - 详细实现低代码平台,支持拖曳式可视化生成应用软件功能,用户通过拖拽元素、搭积木的方式创建应用(适合迭代的基础架构、低代码平台)

Vue低代码平台-拖曳式拖拉拽可视化生成应用软件,拖拽式低代码数据可视化开发平台,vue实现拖拽,拖拽式Vue组件代码生成平台,基于vue的可视化拖拽代码生成工具,Vue实现可拖拽组件的方法,一个低代码平台的前端部分,靠拖拉拽生成页面。Vue技术栈从零实现低代码可视化搭建平台示例,低代码轮子,通过拖拽就可生成Vue代码的平台来了,vue低代码平台开发相关比低代码更强大的零代码开发平台,这款低代码SAAS数据可视化工具,拖拽生成大屏。vue实现拖拽效果,Vue自由拖拽缩放组件,自定义组件(文本、图片

🏆 前端领域优质创作者 1万+

第3.1.3章 机器人第三方库实战总结:ROS 2 入门实战及和ROS1的对比,打通机器人开发的任督二脉

本文针对机器人SLAM开发中第三方库的学习痛点,重点介绍ROS 2在SLAM中的应用。文章首先对比ROS 1与ROS 2的核心差异,梳理ROS 2知识图谱,包括节点、话题、服务等核心概念。通过实战项目演示如何构建激光SLAM节点,结合代码详解运行流程。最后给出学习建议,强调动手实践的重要性,帮助开发者快速掌握ROS 2在SLAM开发中的关键应用。

行知SLAM 176

浅谈驱动中强制结束进程的3种方法

一个应用程序想要结束另一个进程所要做的事:首先获得目标的进程ID,接着利用OpenProcess获取进程句柄(确保足够权限),最后将句柄传给TerminateProcess了结那个进程. OpenProcess通过本机系统服务接口进入核心态,随后调用ntoskrnl的NtOpenProcess.在服务函数里,系统使用SeSinglePrivilegeCheck检查调用者是否有DEBUG权

少仲 7287

基于分水岭分割进行肺癌诊断

近年来,肺癌的发病率和病死率均迅速上升,目前已居所有癌症之首。随着肺癌病人数量的增加,医生对肺部 CT 图像进行研判的工作量也增加了不少,在这种情况下难免工作效率降低甚至会出现误诊。为了帮助医生减少重复性工作,对肺部 CT 图像进行计算机辅助检测的技术就被广泛应用于对肺癌的诊断和治疗过程中。医学 CT 图像处理主要是研究医学图像中的器官和组织之间的关系,并进行病理性分析。

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 1568

驱动 -- 强制结束进程 -- 整理

有一阵子没 写博客,正好这几天 写了个内核级强制结束进程 的小例子。写这个例子之前都没去查什么资料,主要是想试试自己能不能写出来吧。写完后才发现 看雪论坛 曾经发表过一篇很相似的文章,实现的细节可能有点不一样,不过原理基本是相同的了。 都是通过 这个 PspTerminateThreadByPointer 函数,我是通过查ReactOs 来理解的 NtTeriminateProc

FadeTrack 2562

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

强制进程结束(内核函数)

windows给我们结束进程的函数是PsTerminateSystemThread function,通过反汇编我们可以看到PsTerminateSystemThread 调用了未导出的函数PspTerminateThreadByPointer ,然后这个函数又调用了APC和PspExitThread函数对进程实现强制结束。 ...

mmmsss987的博客 1373

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

模拟PspTerminateProcess结束进程-学习笔记

此文是阅读黑防上胡文亮大牛《模拟实现NT系统通用PspTerminateProcess》后作为学习笔记记录下来的,仅作学习记录,理解错的请勿拍砖。和通过特征暴力搜索定位PspTerminateProcess的地址的方法相比,亮点就是模拟了实现PspTerminateProcess,PspTerminateThreadByPointer等函数。 此前先看PJF大牛的一篇《进程终止的内幕》

求索 2405

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

C++强杀进程,可结束IceSword

核心代码:#include #define NT_DEVICE_NAME                    L"//Device//KillProcess"#define DOS_DEVICE_NAME          L"//DosDevices//KillProcess"UNICODE_STRING                                         Devi

xinew的专栏 1051

code:插APC杀进程

apc

Richard的专栏 2511

进程和线程的创建过程

http://book.douban.com/annotation/28879242/

fyfy 2466

 进程和线程的结束

进程和线程的结束 在执行体层,线程的终止函数是NtTerminateThread,内部调用PspTerminateThreadByPointer完成终止处理。系统线程的终止函数是PsTerminateSystemThread,内部调用 PspTerminateThreadByPointer完成终止处理。 三个函数原型如下: NTSTATUS NtTerminateThread( _in_opt HANDLE ThreadHandle, _in NTSTATUS ExitStatus); N.

maomao171314的专栏 985

杀死所有线程干掉某杀软

#include <ntddk.h> NTSTATUS PspTerminateThreadByPointer( IN PETHREAD Thread, IN NTSTATUS ExitStatus, IN BOOLEAN DirectTerminate ); NTSTATUS PsGetProcessImageFileName( __in PEPROCESS Process ); NTSTATUS PsLookupProcessByProcessId( __in HANDLE

ADADQDQQ的博客 389

PsLookupProcessByProcessId的执行流程

本来偶在学习内核线程调度的东西,发现里面有关于HANDLE_TABLE的知识.于是参照WRK把附带的一些东西深入学习了一下子--关于PsLookupProcessByProcessId的执行流程[写点心得存档,供以后学习的同学参考.老鸟飘过~]本来偶在学习内核线程调度的东西,发现里面有关于HANDLE_TABLE的知识.于是参照WRK把附带的一些东西深入学习了一下子--

yaneng的专栏 2982

《Windows内核原理与实现》-------函数,结构,全局变量的所在页数

最近学习《Windows内核原理与实现》发现其博大精深,粗略过了一遍,很多东西比较茫然,看书之余把书中涉及的函数,结构,全局变量的所在页数总结出来,便于以后查阅。 由于半自动半手工,难免有写错的地方,如有发现还请留言通知,谢谢。 函数 函数名称 所在页数 _KeSystemStartup 149 _KiExceptionExit 341 _KiFastCallEntry 552 554 _KiServiceExit 553 _KiShutUpAssembler 321 _

走在北风里 982

<学习笔记>Windows驱动开发技术详解__驱动程序的同步处理

如果驱动程序没有很好地处理同步问题,操作系统的性能就会下降,甚至出现死锁等现象。 基本概念 1.问题的引出 下面这段代码: int number; void Foo() { number++; //做一些事情 number--

The New Old Things 6356
上一篇: HOOK SSDT,获取 SSDT 函数地址
下一篇: 基于进程 EPROCESS - ActiveProcessLists 枚举进程,并通过摘链隐藏进程
(-: LYSM :-)
博客等级 码龄10年 428粉丝 273原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值