![](https://img-blog.csdnimg.cn/20201014180756780.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
Windows内核
文章平均质量分 50
walker-n
这个作者很懒,什么都没留下…
展开
-
(x86)硬件断点的原理与测试
硬件中断的原理与测试。原创 2023-04-30 18:59:50 · 309 阅读 · 0 评论 -
APC初始化 —— 逆向分析 KeInitializeApc
简介操作系统想要实现对正在执行的线程的管理,就要通过 APC 机制实现,即向目标线程的 APC 队列中插入 _KAPC ,以实现对该线程的管理(如挂起、终止)。而向线程插入 APC 就需要先初始化 APC ,在 Windows中使用 KeInitializeApc 函数实现对APC 的初始化。以 PspTerminateThreadByPointer 函数为例,部分重要汇编指令如下:逆向分析KeInitializeApc...原创 2021-03-19 17:02:37 · 772 阅读 · 0 评论 -
句柄表 ——遍历句柄表实现反调试
简介我们知道,当我们尝试在进程中创建、打开内核对象时,该内核对象的地址会作为句柄项存储在进程的句柄表中。因此,我们可以通过遍历全局句柄表获取操作系统中的全部进程(如 OllyDbg 就实现了进程隐藏,在任务管理器中是无法看到该进程的),然后再遍历每个进程的私有句柄表,检测其私有句柄表中是否存储着被保护进程的内核对象地址 _EPROCESS,就可以得知被保护进程是否被其他进程附加,以达到反调试的目的。当然通过不断将被保护进程的 _EPROCESS.DebugPort 清零,就可以强制实现进程无法被附加调原创 2021-03-17 15:49:17 · 747 阅读 · 1 评论 -
全局句柄表 —— 抹除进程PID
简介进程 PID 是进程的唯一标识,那么如果我们尝试抹除进程的 PID 会发生什么情况呢?本次的测试代码以及关于全局句柄表,可参考全局句柄表 —— 遍历全局句柄表Code驱动程序的关键代码如下:// 该句柄是进程句柄if (!RtlCompareUnicodeString(&pWkPOBJECT_TYPE->Name, &unicode_Process, TRUE)){ DbgPrint("句柄类型: Process, 句柄号: %u.\n", uHand原创 2021-03-16 21:56:01 · 712 阅读 · 0 评论 -
全局句柄表 —— 遍历全局句柄表
简介进程句柄表是私有的,每个进程都有自己的进程句柄表。除此之外,系统还有一个全局句柄表,全局变量 PspCidTable 指向该表。全局句柄表存储的是操作系统中所有创建的进程、线程的句柄(不会出现重复)。每个进程和线程都有一个唯一的编号:PID 和 CID , 这两个值其实就是全局句柄表中的索引。也就是说,即使我们实现了对进程、线程的断链,但是只要操作系统中创建了进程、线程,全局句柄表中就会记录其对应的句柄(PID/CID),仍然可以通过全局句柄实现对线程、进程的遍历。EnumPspCidTab原创 2021-03-16 20:58:31 · 1443 阅读 · 4 评论 -
时钟中断 (线程切换)—— 逆向分析 KeUpdateRunTime/KiDispatchInterrupt
简介系统时钟可以实现的线程的切换。Windows 系列操作系统的时钟间隔:10 - 20 毫秒,采用 0x30 中断号。在系统时钟下,线程的执行流程:当一个新的线程开始执行时,初始化程序会在 _KTHREAD.Quantum 赋初始值,该值的大小由 _KPROCESS.ThreadQuantum 决定。线程在执行过程中,系统就会调用 KeUpdateRunTime 来记录时间片的使用情况。KiDispatchInterrupt 完成对线程的调度(1)当该线程的时间片耗尽并让出处理原创 2021-03-14 23:13:55 · 669 阅读 · 0 评论 -
线程切换 ——逆向分析 KiSwapThread
简介在 Windows 内核中,线程的切换是通过 API 函数 KiSwapThread 实现获取将要执行的线程 _KTHREAD 结构体指针,再调用 KiSwapContex/SwapContex 函数实现线程上下文的切换,以实现线程的切换。KiSwapThread/KiSwapContex/SwapContex 直接的调用关系如下:KiSwapThread内核函数 KiSwapThread 的汇编代码分析如下:.text:004050BF ; =============== S U B原创 2021-03-14 16:16:52 · 524 阅读 · 0 评论 -
线程切换 —— 逆向分析 KiSwapContex/SwapContex
简介在 Windows 内核中,线程的切换是通过底层内核 API 函数 KiSwapContex/SwapContex 实现的。KiSwapContexKiSwapContex 的逆向分析如下:.text:00404828 ; =============== S U B R O U T I N E =======================================.text:00404828.text:00404828.text:00404828 ; __fastcall KiS原创 2021-03-14 11:09:11 · 315 阅读 · 5 评论 -
_ETHREAD断链 —— 实现线程隐藏
简介线程所属的父进程 _EPROCESS 结构体中的 ThreadListHead 成员是当前进程中所有线程的双向链表头,该成员有两个,分别在 0x50 和 0x190 处。我们可以通过该线程链表头进行线程遍历,也可以通过直接遍历 _ETHREAD 结构体中的 ThreadListEntry 成员实现遍历进程中的所有线程,ThreadListEntry 分别位于 0x1b0 和 0x22c 处。我们可以通过 _ETHREAD 的 ThreadListEntry 断链实现线程隐藏。需要注意的是,Threa原创 2021-03-08 12:42:39 · 2278 阅读 · 0 评论 -
清空 _EPROCESS 结构体中的 DebugPort ,实现进程无法被附加调试
简介在内核 _EPROCESS 中有一个 DebugPort 成员,该成员中存储的是一个内核调试对象地址。当调试器附加进程调试时,操作系统会在内核中创建一个调试对象,并将调试对象的地址写入对应被调试进程的 _EPROCESS 结构体中的 DebugPort 成员中,用于实现调试器与被调试进程之间建立联系。而清空该地址时,调试器将会与被调试进程之间失去关联,即无法继续调试该进程。如果调试器重复多次发起调试请求,操作系统将会重复将调试对象的地址写入被调试进程。如果只将 DebugPort 清空一次,依然会原创 2021-03-07 11:43:26 · 657 阅读 · 0 评论 -
_EPROCESS断链 —— 实现进程内核隐藏
我们可以利用 _EPROCESS 结构体中的 ActiveProcessLinks 双向链表遍历进系统中的进程,并将特定进程从该双向链表中移除,以达到隐藏特定进程的目的。_EPROCESS_EPROCESS 结构体是内核用于管理和维护进程的结构体,每个进程都会有一个属于自己的结构体。同一个程序创建了多个进程,其就会有对应个数的 _EPROCESS 。_EPROCESS 的结构如下:kd> dt _EPROCESSnt!_EPROCESS +0x000 Pcb原创 2021-03-06 19:35:07 · 2276 阅读 · 5 评论 -
SSDT Hook (HookZwTerminateProcess)—— 实现任务管理器无法关闭进程
本节的目的是通过驱动程序修改 ntoskrnl.exe 程序的 SSDT 表中的函数地址表,以实现 SSDT Hook 。本次的测试函数为 R3 API 函数 ZwTerminateProcess ,通过 Hook 该函数,以实现任务管理器无法强制关闭进程,只有通过进程的关闭方法才可以正常结束进程。Hook 该函数的关键是判断 ZwTerminateProcess 函数中的进程句柄 hProcess 。当进程是通过自身的关闭方法关闭的话,该句柄的值应为 0xffffffff 或 0x00 ,而通过其他进原创 2021-03-06 15:03:59 · 566 阅读 · 0 评论 -
R0-R3 现场保护(_KTrap_Frame/_KPCR/_ETHREAD)—— 分析内核函数KiSystemService
简介在进程由用户态进入内核态的过程中,发生了 ESP/SS/EIP/CS 的切换。因此,在进程权限切换的工程中,必然要进行寄存器的现场保护。这里,要使用到3个内核结构体:_KTrap_Frame/_KPCR/_ETHREAD。_KTrap_Frame每个线程在内核中都有一个 _KTrap_Frame 结构体,用于操作系统对线程的管理,该结构体时操作系统进行维护的。_KTrap_Frame 的结构如下:kd> dt _KTrap_Frame nt!_KTRAP_FRAME //调原创 2021-03-05 14:22:03 · 1102 阅读 · 0 评论 -
R3-R0 系统调用(快速调用与中断门)
简介我们知道,通过驱动程序可以实现从用户态进入内核态。而操作系统的 API 函数可以实现进入内核态,那么这是如何实现的呢?操作系统定义了一个用户程序和内核程序都可以访问的一个结构 _KUSER_SHARED_DATA ,而用户态下的该结构和内核态下的该结构都指向同一个物理内存。操作系统通过初始化该结构体,以实现 API 函数直接 call 该结构体下的 SystemCall 中的函数地址( KiFastSystemCall 或 KiIntSystemCall 函数),以实现从用户态进入内核态。_KU原创 2021-03-03 14:42:05 · 1020 阅读 · 0 评论