- 博客(96)
- 资源 (1)
- 收藏
- 关注
原创 wow stsm 宏
蓝装拾取确认宏/script T,F=T or 0,F or CreateFrame("frame")if X then X=nil else X=function()local t=GetTime()if t-T>1 then StaticPopup1Button1:Click()T=t end end end F:SetScript ("OnUpdate",X)分解宏/cast 分解/use 迅影护腕/use 不可宽恕者的面具/use 吟游诗人热裤/use 野性之心手套
2022-02-23 11:37:58
6400
转载 [转](75)内核APC执行过程,分析 KiDeliverApc 函数
一、内核APC执行过程通过分析 SwapContext ,KiSwapContexgt , KiSwapThread ,我们得出一个结论:切换线程后会执行内核APC,调用的函数是 KiDeliverApc 。内核APC和用户APC都要由 KiDeliverApc 函数调用,KiDeliverApc 函数首先处理内核APC,然后根据 PreviousMode 参数,用户APC队列是否有数据来判断是否需要处理用户APC。内核APC的执行比较简单(相对用户APC而言),它是直接...
2021-04-14 09:12:58
510
转载 [转](74)分析 APC 插入过程 —— KeInsertQueueApc , KiInsertQueueApc
一、KeInsertQueueApc(调用 KiInsertQueueApc)BOOLEANKeInsertQueueApc ( IN PRKAPC Apc, IN PVOID SystemArgument1, IN PVOID SystemArgument2, IN KPRIORITY Increment )/*++Routine Description: This function inserts an APC object ...
2021-04-14 09:12:15
861
转载 [转](73)分析 KeInitializeApc ,了解 KAPC 的初始化
一、回顾第71篇博客我们分析了 PspTerminateThreadByPointer 函数,其中调用了 KeInitializeApc 函数初始化 KAPC 结果。这次课我们来分析 KeInitializeApc 函数,了解 APC 如何初始化。PspTerminateThreadByPointer(psdelete.c) 调用 KeInitializeApcKeInitializeApc (ExitApc, PsGetKernelT...
2021-04-14 09:06:54
622
转载 [转](72)进程挂靠(attach)使用备用APC队列 SavedApcState 保存父进程 APC 队列,分析 NtReadVirtualMemory
一、回顾上次课我们学习了 _KAPC_STATE , _KAPC 结构,分析了 TerminateThread 函数最终如何通过插入 APC 的方式来通知目标线程终止。这次课我们来学习备用APC队列 SavedApcState ,这个结构在进程挂靠attach时会使用到。课后作业是分析 NtReadVirtualMemory 函数,通过分析,我们可以了解什么是 attach ,以及 attach 时如何使用 SavedApcState 。二、SavedApcSt...
2021-04-14 09:01:15
440
转载 [转](71)APC队列,KAPC结构,分析 TerminateThread ,QueueUserApc
一、线程是如何结束的首先,线程是自己结束的,线程不能被其他线程杀死,考虑一种极端情况,线程屏蔽了时钟中断,不发生异常,那么它就能一直执行下去。TerminateThread 函数结束其他线程的方式是向线程APC队列添加一个APC结构,线程执行到某个时刻,会检查自己的APC队列,判断要做什么工作,包括结束自己。其他线程插入APC和本线程执行APC是异步的过程,所以APC的全称是 APC(asynchronous procedure call)异步过程调用。二、AP...
2021-04-14 08:58:23
516
转载 (转)一致代码段和非一致代码段 CPL RPL DPL
之所以出现这个定义是因为系统要安全:内核要和用户程序分开..内核一定要安全.不能被用户程序干涉.但是有时候用户程序也需要读取内核的某些数据,怎么办呢?操作系统就引入了访问特权等级(0-3)的机制.这些特权等级,通过三个符号来体现CPL/DPL/RPL.其中CPL是存寄存器如CS中,RPL是代码中根据不同段跳转而确定,以动态刷新CS里的CPL.DPL是在GDT/LDT描述符表中,静态的。1.在x86中的数据和代码是按段来存放的:[section],GTL/LDT里的每个..
2021-03-18 21:48:40
247
转载 [转](70)内核重载 xp sp3 x86 单核
一、项目说明这次项目是这样设计的,首先 inline hook NtTerminateProcess 函数,使其他进程不能关闭受保护的进程,这里选择记事本。然后编写一个普通的程序,调用 TerminateProcess 函数关闭记事本,如无意外是关不掉的。然后编写驱动,重载内核,HOOK KiFastCallEntry 函数,让我们的程序系统调用走新内核,这样就可以关掉记事本了。二、知识回顾KiFastCallEntry我们已经逆向分析...
2020-11-25 08:54:26
247
转载 [转](69)番外 —— 编写一个简易的反调试引擎
一、开发背景这个项目是我用来检验所学知识的,它只适用于32位xp sp3 单核版本。简单起见,我就不对引擎本身做保护了,假设引擎是神圣不可侵犯的。二、功能介绍应用层TLS回调 常用的反调试API函数 CRC代码校验 检测调试器进程(CreateToolhelp32Snapshot) 注入检测(vadroot)内核层进程隐藏(ActiveProcessLinks 断链) 内核 HOOK 检测(内核重载,实时检测是否被HO...
2020-11-25 08:53:44
177
转载 [转](38)注入ShellCode
编写这篇博客的目的:中级上项目 MessageBox 监视器需要编写 shellcode,三期没有讲,于是补充学习了这部分知识。一、ShellCode的定义和应用场景Shellcode是不依赖环境,放到任何地方都可以执行的机器码。shellcode的应用场景很多,本文不研究shellcode的具体应用,而只是研究编写一个shellcode需要掌握哪些知识。二、ShellCode编写原则1、不能有全局变量因为我们编写shellcode时,使用的全局变...
2020-11-24 09:02:29
1286
转载 [转](68)自旋锁 , cmpxchg8b 指令
一、临界区和自旋锁的对比上次课我们学习了临界区,并自己实现了一个。临界区是通过线程切换的方式来等待的,自旋锁则使用循环代替了线程切换,在多核环境下,使用自旋锁可以提高效率。用一个例子来解释临界区和自旋锁的区别。只有一个厕所,有一个人进去了。临界区就是外面的人过来看一眼发现没位子,就回家睡觉了,睡醒了再回来看看有没有位子,重复这样的步骤;自旋锁就是外面人一看没位置,他就在原地打转,一有位子马上就进去了。自旋锁的执行流程真的是在“旋转”,我觉得这个名字起得...
2020-11-24 09:02:14
488
转载 [转](67)多核同步,lock 总线锁 ,自己实现临界区
一、多核同步问题单条汇编指令可能被多个CPU同时执行,此时就可能会引发安全问题。考虑下面的指令:INC DWORD PTR DS:[0x12345678] 如果两个CPU同时执行该指令,[0x12345678] 的初始值是0,那么两个CPU执行后,本应该 [0x12345678] 是2,结果却有可能是1。为了解决这个问题,可以使用 LOCK 对某个内存地址“加锁”,将指令修改成如下:LOCK INC DWORD PTR DS:[0x12...
2020-11-23 11:41:06
697
转载 [转](66)全局句柄表,遍历全局句柄表
一、回顾前面的课程我们学习了进程的句柄表,全局句柄表和进程句柄表非常像,只有一些小区别。这节课的课后作业我先给出来:编写程序,通过全局句柄表PsdCidTable,遍历所有进程(包括隐藏进程)。打印全局句柄表中内核对象的所有类型一、需要解决的问题:1、如何通过找到全局句柄表?2、如何判断是否是进程?二、有用的系统函数:MmGetSystemRoutineAddress这个函数用来得到导出函数的地址,优点是:1、不会被IAT Hook影响(从内...
2020-11-23 11:39:53
414
转载 [转](65)如何根据句柄从二级、三级结构句柄表中找到内核对象
一、回顾上一篇博客介绍了如何遍历一级句柄表。一级句柄表非常简单,就是一个4KB页,最多存储512个句柄表项。如果句柄数量在 512 - 1024*512 之间,句柄表就是二级结构;如果句柄数量大于 1024 * 512,就是三级结构。这篇博客作为上一篇的补充,介绍如何从二级、三级结构句柄表中找到内核对象。二、ExpLookupHandleTableEntry 函数实际上这个需求就是 ExpLookupHandleTableEntry 函数做的事情:P...
2020-11-23 11:39:18
349
转载 [转](64)句柄表,遍历所有进程的句柄表实现反调试
一、内核对象,句柄这次课讨论的内核对象是指创建时需要指定 LPSECURITY_ATTRIBUTES 参数的对象,例如 Mutex, Thread。调用 CreateThread 等函数会返回一个 HANDLE 类型值,这种就叫句柄,它对应一个内核对象;调用 CloseHandle 函数对某个内核对象计数减一,当内核对象计数为0,这个对象就被销毁了。内核对象在内核存储,直接把地址给3环用很不安全,所以微软设计了句柄(HANDLE)给3环使用,句柄是一个整数,它的...
2020-11-23 11:38:31
847
转载 [转](63)0环与3环通信非常规方式 —— 0环InlineHook
一、回顾在第37篇博客里,我们学习了0环-3环通信的常规方式,是通过设备的方式进行数据交互的。今天,我们来学习一种非常规方式,即通过HOOK API 的形式完成数据交互。(37)0环与3环通信,PspTerminateProcess 关闭进程工具二、原理随便找一个内核函数,参数至少要有4个,多一点也无所谓。用 Inline hook 改变它的执行流程,如果参数是合法的,就调用原来的函数,如果参数符合某种规则,就认为这是3环请求和驱动通信的。举个例子,我...
2020-11-23 11:38:22
389
转载 [转](62)时钟中断切换线程,时间片管理, KiDispatchInterrupt
一、回顾前面的课程,我们分析了API主动切换线程的流程,分析了 KiSwapContext 和 SwapContext 函数,这两个是切换线程的函数。分析了 KiSwapThread 函数,功能是找到新的就绪线程。分析了 KiFindReadyThread 函数,了解了操作系统如何根据线程优先级来调度线程。除了主动切换以外,时钟中断和异常也会导致线程切换。这次课我们来学习另一种导致线程切换的情景 —— 时钟中断。二、时钟中断Windows系统每隔10-...
2020-11-23 11:38:08
832
转载 [转](61)分析 KiFindReadyThread 函数 —— 线程优先级
一、前言通过之前的学习,我们知道了线程切换有两种触发情况,一种是API主动调用切换,另一种是时钟中断切换,时钟中断方式我们还没学。当线程切换发生时,要调用 KiFindReadyThread 函数从调度链表里找到下一个就绪线程。这次课我们就来分析 KiFindReadyThread 函数是如何根据线程优先级找到就绪线程的。这个函数用了二分查找和大量位运算,代码非常长,就算拿着源码看,都要花些功夫。二、预备知识逆向之前,介绍一下必不可少的预备知识。...
2020-11-23 11:37:35
466
转载 [转](60)逆向分析 KiSwapThread
一、回顾上一篇博客,我带着以下的问题逆向分析了 KiSwapContext 和 SwapContext 这两个函数:SwapContext 有几个参数,分别是什么? SwapContext 在哪里实现了线程切换 线程切换的时候,会切换CR3吗?切换CR3的条件是什么? 中断门提权时,CPU会从TSS得到ESP0和SS0,TSS中存储的一定是当前线程的ESP0和SS0吗?如何做到的? FS:[0]在3环指向TEB,但是线程有很多,FS:[0]指向的是哪个线程的TEB,如何做到...
2020-11-23 11:36:42
367
转载 [转](59)逆向分析 KiSwapContext 和 SwapContext
一、前言在前面的课程中,我们研究了模拟线程切换的代码,学习了 _KPCR,ETHREAD,EPROCESS 等内核结构体,这些都是为了学习Windows线程切换做的准备。线程切换是操作系统的核心内容,几乎所有的内核API都会调用切换线程的函数。这次课我们就来逆向 KiSwapContext 和 SwapContext 这两个函数,看看Windows是怎么切换线程的。我们要带着问题开始逆向:SwapContext 有几个参数,分别是什么? SwapContext...
2020-11-23 11:36:30
939
转载 [转]结构体对齐,#pragma pack
一、结构体对齐首先通过一个例子说明结构体对齐,可以看到,下面这个结构体占32字节(32位)typedef struct { double d; short s; int i; char c; short ss; char cc; int ii;} A;这个是8字节默认对齐。二、#pragma pack可以使用 #pragma pack(push, 4) 将对齐数改成4,那么结构体大小就会变成28字节。#prag...
2020-11-23 11:36:17
353
1
转载 [转](58)模拟线程切换——添加挂起、恢复线程功能
一、回顾我们在上一篇博客分析了模拟线程切换的源码。《模拟线程切换》我们着重分析了 Scheduling 和 SwitchContext 这两个函数,对线程切换的过程有了新的认识:线程切换本质是通过切换堆栈达到切换寄存器的目的 线程切换既有线程主动切换,也有时钟中断切换这次课,我们将给程序添加线程挂起和恢复的代码。二、原理我的做法是在线程调度函数 Scheduling 里判断线程是否处于挂起状态,如果是,那么跳过该线程,否则才有资格做...
2020-11-20 08:49:54
179
转载 [转](57)模拟线程切换
一、回顾在之前的课程中,我们学习了 EPROCESS, ETHREAD, KPCR 等重要的内核结构体,学习了存储等待线程的等待链表和调度线程的调度链表,这些知识都是为了后面学习线程切换打的基础。这次课,我们将学习老师提供的模拟Windows线程切换的源码,这份代码可以在3环模拟线程调度,有助于我们理解真正的Windows线程调度源码。二、运行结果这份代码是我照着视频抄的(见文末),在后续的学习中,我们要往里面加东西,所以建议不要做过多的修改。...
2020-11-20 08:49:42
181
转载 [转](56)等待链表,调度链表
一、回顾进程结构体EPROCESS(0x50和0x190)是2个链表,里面圈着当前进程所有的线程。对进程断链,程序可以正常运行,原因是CPU执行与调度是基于线程的,进程断链只是影响一些遍历系统进程的API,并不会影响程序执行。对线程断链也是一样的,断链后在Windbg或者OD中无法看到被断掉的线程,但并不影响其执行(仍然在跑)。二、线程的三种状态:等待,运行,就绪线程可以分为3种状态:1、wait(等待,挂起,阻塞随便怎么翻译)...
2020-11-20 08:49:29
201
转载 [转](55)_KPCR, _NT_TIB, _KPRCB
一、回顾上次课我们学习了 ETHREAD 的部分属性,其中有一个 ThreadListEntry 属性,存储了线程链表,我们可以把它断链处理,然后任务管理器,OD,windbg就会认为进程里没有线程了,但实际上程序还在正常运行,这说明了操作系统线程调度并不通过 ThreadListEntry 链表。这次课我们首先学习KPCR(Processor Control Region)结构,然后学习调度链表和等待链表,了解操作系统通过调度链表调度线程的过程。但是我打算将KPCR单独写一篇博客...
2020-11-20 08:49:07
430
转载 [转](54)线程结构体 ETHREAD,线程断链
一、回顾上次课我们学习了进程,我们知道了进程是空间概念,最主要的功能是提供CR3,而线程才是CPU调度的最小单位;更早的时候做SSDT HOOK FindWindow 时我们还了解到了,当3环程序向驱动发起通信时,驱动所属进程就是3环的程序;学习了EPROCESS里的部分成员,其中 ActiveProcessLinks 是进程链表,我们可以通过对其断链实现进程隐藏,DebugPort 是调试端口,抹除它的值可以使三环调试器调试崩溃。本次课我们来学习线程结构体 E...
2020-11-20 08:48:55
833
转载 [转](53)进程结构体EPROCESS,擦除 DebugPort 实现反调试,ActiveProcessLinks 断链实现进程隐藏
一、进程的作用进程最重要的作用是提供了CR3,10-10-12分页下CR3指向页目录表,2-9-9-12分页下CR3指向页目录指针表。每个进程有一个或多个线程。本质上,没有进程切换,只有线程切换。我们过去说进程切换是切换了CR3的值,实际上是切换线程时切换了CR3,只不过同一进程内的线程切换不会改变CR3。我们说进程是空间概念,进程为它的线程提供了CR3,那么它的线程访问同一个线性地址时,就能访问到同一个物理页。attach 和 .process 本质就是切换C...
2020-11-20 08:48:41
672
转载 [转](52)系统调用阶段测试——基于 SSDT HOOK 的 FindWindowA 监视器
一、项目说明SSDT HOOK 内核函数我们已经会了,请看这两篇博客:SSDT HOOK 实现进程保护补充内容:SSDT HOOK 模板此次考试和 hook NtOpenProcess 或 NtTerminateProcess 有所区别,FindWindowA 是 GDI 函数,这意味着系统调用走的是第二张系统服务表:win32k.sys 系统服务表可能会缺页,要在驱动里访问它,做法是创建一个已经调用过GDI函数的进程(不一定是窗口程序),然...
2020-11-20 08:48:28
358
1
转载 [转](50)补充内容:SSDT HOOK 模板
代码下面的驱动代码ssdt hook了NtOpenProcess函数,可以监视打开进程的操作。#include <ntddk.h>#include <ntstatus.h>/************************************************************************//* 类型声明 ...
2020-11-20 08:48:14
108
转载 [转](49)逆向分析 KiSystemService / KiFastCallEntry 调用内核函数部分
一、回顾前两篇博客,我逆向分析了 KiSystemService 和 KiFastCallEntry 填充_KTRAP_FRAME 结构体的代码,二者大同小异,主要的区别是 sysenter 只改了eip,cs,ss,虽然esp也改了,但是windows不使用,而是从TSS里取esp0;另外sysenter并没有像中断门那样压栈,所以3环的 ss, esp, eflags, cs,eip都要在函数里依次保存到 _KTRAP_FRAME 。这次课后作业是逆向 KiSystemServ...
2020-11-20 08:47:56
382
转载 [转](51)SSDT HOOK 实现进程保护
一、回顾在前面的课程里,我们逆向分析了 KiSystemService / KiFastCallEntry 的部分代码,我们发现这两个函数找系统服务表 SystemServiceTable 的方法是通过 _KTHREAD + 0xE0 来找。今天我们来学习另一种方法,即通过 SSDT 表找系统服务表。二、SSDTSSDT是内核模块的导出变量,可通过 dd KeServiceDescriptorTable 查看:kd> dd KeSer...
2020-11-20 08:47:18
210
转载 [转](48)逆向分析 KiFastCallEntry 函数填充
一、回顾上一篇博客我逆向了 KiSystemService 函数填充 _KTRAP_FRAME 部分。逆向分析 KiSystemService 函数填充 _KTRAP_FRAME 部分里面涉及了6个结构体,分别是 _KTRAP_FRAME,_ETHREAD,_KTHREAD,_KPCR,_NT_TIB 和 _KPRCB。这些结构体待会逆向 _KiFastCallEntry 时也要用到,我在本文就不贴出来了,有需要可以去上篇博客查看或者在windbg里 dt 查看。...
2020-11-19 08:45:45
193
转载 [转](47)逆向分析 KiSystemService 函数填充
一、回顾之前的课程,我们学习了API系统调用在3环部分做的事情,有两种方式进0环,分别是中断门和快速调用,分别调用两个不同的函数 KiSystemService 和 KiFastCallEntry。本文我们来逆向分析 KiSystemService 函数填充 _KTRAP_FRAME 部分的反汇编代码。分析之前,思考四个问题: 进0环后,原来的寄存器存在哪里? 如何根据系统调用号(eax中存储)找到要执行的内核函数? 调用时参数是存储到3环的堆栈,如...
2020-11-19 08:45:31
649
转载 [转](46)分析 INT 0x2E 和 sysenter
一、回顾上次课我们学习了3环进0环的两种方式,分别是中断门和快速调用,如果CPU支持快速调用,那么_KUSER_SHARED_DATA 结构体的 SystemCall 属性指向的函数是 KiFastSystemCall;如果不支持,那么SystemCall 指向的函数是KiIntSystemCall。执行 KiFastSystemCall,则使用快速调用的方式进0环;执行 KiIntSystemCall,则使用中断门的方式进0环。共同点是都要给0环提供新的CS,SS,E...
2020-11-19 08:45:19
539
转载 [转](45)中断门和快速调用进0环详解,重写 WriteProcessMemory
一、本文大纲系统调用的两种方式:中断门和快速调用 _KUSER_SHARED_DATA 结构 使用 cpuid 指令判断当前CPU是否支持快速调用 3环进0环需要更改的4个寄存器 以 ReadProcessMemory 为例说明系统调用全过程 重写 ReadProcessMemory 和 WriteProcessMemory int 0x2e 和 sysenter 都做了什么工作?二、中断门和快速调用以我的理解,系统调用,即从调用操作系统提供的3环API开始,到...
2020-11-19 08:45:06
468
转载 [转]共享内存+Shellcode实现跨进程调用3环函数
提供shellcode的程序// 共享内存调用Shellcode_Shellcode提供者.cpp : 定义控制台应用程序的入口点。// 生成shellcode须关闭运行时安全检查选项// C/C++ -> 代码生成// 基本运行时检查:默认值// 缓冲区安全检查:否#include "stdafx.h"#include <Windows.h>// 弹出对话框的shellcodeunsigned char ShellCodebuff[] = { 0x...
2020-11-19 08:44:54
302
转载 [转](44)MessageBoxA 监视器(过写拷贝,不使用 shellcode 注入)
一、研发背景这是中级上保护模式和驱动开发章节的综合练习。程序可以监视系统API调用,和三期的那个函数调用监视器不同,三期的只能HOOK本进程的API,而这个项目可以监视所有进程。项目源码:https://github.com/Kwansy98/MsgBoxAWatcher/tree/main编译环境是 VS2010 + WDK7600,运行环境是32位XP。每个人做这个作业时都有不同的写法,本文仅供参考,有什么疑问或建议,欢迎留言或私信,也可以加q群 10460...
2020-11-19 08:44:37
524
转载 [转](42)驱动中使用全局变量
一、现象我在编写驱动中发现,使用全局变量或static变量,它们的地址是会变的。全局变量每次调用驱动函数都会重新初始化。我试图在 IRP_MJ_DEVICE_CONTROL 处理函数中定义一个 static 变量,然后发现每次执行函数时,static变量的值都是0.于是我打印了变量的地址,发现确实每次调用都会变。本文只是介绍了这种现象,背后的原因我不清楚,如果以后弄明白其中原因,我会在此补充。二、替代方法调用 IoCrea...
2020-11-19 08:44:25
460
转载 [转](41)缺页异常简介
一、什么情况下会引起缺页异常很简单,PTE的P=0时,就会引发缺页异常。缺页异常有4种情形,见下图:不常使用的线性地址可能是没有挂物理页的,当我们访问这个地址,由于PTE P=0,会触发缺页异常,程序跳转到异常处理函数执行,处理函数判断PTE无效的原因,做相应的处理。二、测试缺页异常下面编写一个简单的程序,来演示缺页异常。// MessageBoxA_PDE_PTE.cpp : 定义控制台应用程序的入口点。//#includ...
2020-11-19 08:44:12
506
转载 [转](40)写拷贝
一、什么是写拷贝写拷贝是VAD树里的属性。当访问一个线性地址,页表项 PTE = 0 时,就会触发缺页异常,跳转到异常处理函数,处理函数会检查VAD树,看看这个线性地址到底是没挂物理页,还是写拷贝,或者是别的什么情况。举个例子,在Windows XP系统里,MessageBoxA 这个函数位于 ntdll.dll,假如我想HOOK它,比如把它头两个字节的 MOV EDI,EDI 改成JMP,此时由于 PTE = 0,就会触发缺页异常。然后异常处理函数遍历 VAD 树,就会发现 Me...
2020-11-19 08:43:57
259
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人