windows下的反调试探究——原理

原理

我们在前面介绍了一些反调试的手段,基本上都是通过对内核的某个标志进行修改来达到反调试的效果,但是这里有一个问题就是,如果分析人员对我们的样本的API进行了hook,那么我们的反调试手段都将作废,也就是说我们还是要深入底层去探究调试器与被调试器直接究竟是如何建立连接的,只有了解了原理,我们才能更加得心应手的进行对抗

在windows里面,每个程序的低2G是独立使用的,高2G(内核)区域是共用的。那么我们假设一个场景,我们的3环调试器要想和被调试程序之间建立通信肯定就需要涉及到进程间的通信以及数据的交换,如果这个过程放在3环完成,不停的进程通信会很繁琐,所以windows选择将这个过程放在0环进行。调试器与被调试程序之间只能通过CreateProcessDebugActiveProcess这两个API建立起连接,这里我们探究DebugActiveProcess是如何建立起两者之间的连接的

与调试器建立连接

首先看一下DebugActiveProcess

调用ntdll.dllDbgUiConnectToDbg

再调用ZwCreateDebugObject

通过调用号进入0环

进入0环创建DEBUG_OBJECT结构体

然后到ntoskrnl里面看一下NtCreateDebugObject

然后调用了ObInsertObject创建DebugObject结构返回句柄

再回到ntdll.dll,当前线程回0环创建了一个DebugObject结构,返回句柄到3环存放在了TEB的0xF24偏移处

也就是说,遍历TEB的0xF24偏移的地方,如果有值则一定是调试器

与被调试程序建立连接

还是回到kernel32.dllDebugActiveProcess,获取句柄之后调用了DbgUiDebugActiveProcess

调用ntdll.dllDbgUiDebugActiveProcess

跟到ntdll.dll里面的DbgUiDebugActiveProcess,传入两个参数,分别为调试器的句柄和被调试进程的句柄

通过调用号进0环

来到0环的NtDebugActiveProcess, 第一个参数为被调试对象的句柄,第二个参数为调试器的句柄

执行ObReferenceObjectByHandle,把被调试进程的句柄放到第五个参数里面,这里eax本来存储的是调试器的EPROCESS,执行完之后eax存储的就是被调试进程的EPROCESS

这里判断调试器打开的进程是否是自己,如果是自己则直接退出

也不能调试系统初始化的进程

然后获取调试对象的地址,之前是句柄,但是句柄在0环里面是无效的,这里就要找真正的地址

获取到调试对象的地址之后还是存到ebp+Process的地方,这里之前是被调试对象的地址,现在存储的是调试对象的地址

将调试进程和被调试的PEPROCESS传入_DbgkpSetProcessDebugObject,将调试对象和被调试进程关联起来

跟进函数,发现有判断DebugPort是否为0的操作,ebx为0,edi为被调试进程的EPROCESS,那么edi+0bc就是调试端口

然后再把调试对象的句柄放到被调试对象的DebugPort里面

调试事件

调试事件是在调试过程中导致系统通知调试器的事件,调试事件包括创建进程、创建线程、加载动态链接库 (DLL) 、卸载 DLL、发送输出字符串和生成异常。我们知道调试器和被调试程序的通信主要依赖于0环的_DEBUG_OBJECT结构,然后被调试程序在进行操作时(如:创建进程线程、加载dll)等,就会将一个调试事件写入到_DEBUG_OBJECT结构里面,调试器获得句柄即可进行调试

这里就会使用调试事件采集函数来对调试事件进行写入,调试器在被调试进程进行特定操作的必经之路中调试事件采集函数,必经之路分为5条,其中以Dbgk开头的函数为调试事件采集函数,所有调试事件采集函数最终都会调用DbgkpSendApiMessage将封装好的调试事件结构体写入到链表当中。DbgkSendApiMessage有两个参数,第一个参数为调试事件类型,第二个参数为是否挂起其它线程,有时需要,比如0xCC,有时不需要,比如模块加载。

例如创建进程、线程必经之路:

退出线程、进程必经之路:

我们跟一下PspExitThread,首先在PspExitThread里面判断Debugport是否为0,如果为0则不处于调试状态就不会跳转,如果不为0则为调试状态则跳转到loc_52E3AC

然后这里有个判断,如果当前线程是最后一个线程则跳转到DbgkExitProcess退出进程,如果不是最后一个线程则跳转到DbgkExitThread退出当前线程

这里我们跟DbgkExitProcess,这里调用了DbgkpSendApiMessage,这个函数的作用就是将被调试程序发送过来的调试事件挂入_DEBUG_OBJECT

这里继续跟进去,如果不挂起进程则用DbgkpQueueMessage收集调试事件的有关信息

跟进DbgkpQueueMessage可以看到最终通过DebugPort得到被调试程序的_DEBUG_OBJECT的地址

这里继续往下走,通过链表操作添加调试事件信息

总结

首先调试器进程先创建一个_DEBUG_OBJECT结构放到TEB0xF24处,存储的是_DEBUG_OBJECT结构的句柄,然后在被调试程序EPROCESSDebugPort的地方存储_DEBUG_OBJECT结构的地址,然后通过调用DbgkpSendApiMessage进行调试事件的采集,把句柄放到_DEBUG_OBJECT结构,供调试器使用

那么了解了调试器和被调试器之间如何建立连接,我们就可以通过以下几种方式来进行反调试

1.不断将EPROCESSDebugPort清零,使调试器不能够和被调试程序建立连接

2.遍历每个线程TEB0xF24,如果存在值就证明有调试器

3.要想建立连接必须要在0环创建_DEBUG_OBJECT结构,使用NtCreateDebugObject,直接hook NtCreateDebugObject达到监控的效果

4.被调试进程必须通过DbgkpSendApiMessage将调试事件放入_DEBUG_OBJECT结构供调试器使用,那么这里就可以直接hook 对应的调试事件,如创建进程就hook DbgkCreateThread,也可以直接hook DbgkpSendApiMessage达到监控所有调试事件的效果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/511784.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【蓝牙协议栈】【BR/EDR】【AVDTP】音视频分布传输协议

1. AVDTP概念 AVDTP即 AUDIO/VIDEO DISTRIBUTION TRANSPORT PROTOCOL(音视频分配传输协议),主要负责 A/V stream的协商、建立及传输程序,还指定了设备之前传输A/V stream的消息格式. AVDTP的传输机制和消息格式是以 RTP为基础的。RTP由 RTP Data Transfer Protocol (RTP)和…

网络进程:广播、组播、流式域、报式域(套接字)

1.广播 1.1广播发送端模型(类似UDP客户端) 程序代码&#xff1a; #include<myhead.h> int main(int argc, const char *argv[]) {//创建套接字int sfdsocket(AF_INET,SOCK_DGRAM,0);if(sfd-1){perror("socket error");return -1;}//将套接字设置成允许广播i…

Ubuntu 18.04(x86_64)安装配置 CUDA 11.6 + cuDNN v8.9.7 + TensorRT8.4.1.5(亲测可用)

1. 检查是否安装显卡驱动 lspci | grep -i nvidianvidia-smi 如果显示特定的界面&#xff0c;这表明显卡驱动已经被安装。若未安装驱动&#xff0c;则需通过手动方式进行安装。 首先&#xff0c;需要添加软件源&#xff1a; 执行以下命令以添加PPA源&#xff1a; sudo add-…

测试环境搭建整套大数据系统-问题篇(一:实时遇到的问题)

1. java.io.IOException: Failed to deserialize JSON ‘{“age”:867,“sex”:“fba8c074f9”,“t_insert_time”:“2024-03-04 14:12:24.821”}’ 解决方式 修改数据类型。将TIMESTAMP_LTZ改为TIMESTAMP。 2. java. lang,classNotFoundException: org,apache.flink,streami…

Docker镜像导出/导入

Docker镜像导出/导入 一、前言 在实际操作中&#xff0c;为了便于docker镜像环境和服务配置的迁移&#xff0c;我们有时需要将已在测试环境主机上完成一系列配置的docker镜像或运行中的容器镜像导出&#xff0c;并传输到生产或其他目标环境主机上运行。为此&#xff0c;本文主…

使用 gulp-cleanwxss 清除小程序无用样式代码

小程序在迭代中&#xff0c;因没有及时清理无用样式&#xff0c;造成包体积越来越大。而通过人工判断清除工作量大&#xff0c;因而使用 gulp-cleanwxss 实现脚本清除。 一、Demo 演示 二、实现步骤 1、全局安装 gulp 命令行工具 yarn global add gulp-cli2、局部安装依赖 gu…

尚硅谷Java数据结构--线索化二叉树

出现空指针异常&#xff08;先记录一下&#xff09; &#xff08;希望大佬能够指出是哪里出了问题&#xff09; package DataStructure;/*** Created with IntelliJ IDEA.* Description:* User: 86178* Date: 2024-03-05* Time: 10:39*/ public class ThreadedBinaryTreeDemo …

蓝桥杯-单片机组基础7-存储器映射扩展与PWM脉冲调制(附小蜜蜂课程代码)

蓝桥杯单片机组备赛指南请查看这篇文章&#xff1a;戳此跳转蓝桥杯备赛指南文章 本文章针对蓝桥杯-单片机组比赛开发板所写&#xff0c;代码可直接在比赛开发板上使用。 型号&#xff1a;国信天长4T开发板&#xff08;绿板&#xff09;&#xff0c;芯片&#xff1a;IAP15F2K6…

备战蓝桥杯---图论应用1

目录 1.增加虚点建图&#xff1a; 2.抽象图的迪杰斯特拉&#xff1a; 3.用bitset优化弗洛伊德&#xff1a; 4.有向图的Prim/kruskal&#xff1a; 1.增加虚点建图&#xff1a; 我们当然可以每一层与上一层的点再连上一条边&#xff0c;但这样子边太多了超内存&#xff0c;我们…

【格与代数系统】偏序关系、偏序集与全序集

关系&#xff1a;X,Y是两个非空集合, 记若则称R是X到Y的一个二元关系&#xff0c;简称关系。 若,记。 当时&#xff0c;称是上的一个关系。 目录 偏序关系 偏序集 可比性 全序集 最值与上下界 上下确界 偏序关系 设是上的一个关系&#xff0c;若满足&#xff1a; (1)自…

springboot+bootstrap+jsp校园二手书交易平台mlg86

考虑到实际生活中在校园二手书交易系统方面的需要以及对该系统认真的分析,将系统权限按管理员和学生这两类涉及用户划分。 (a) 管理员&#xff1b;管理员使用本系统涉到的功能主要有个人中心、学生管理、图书类型管理、二手图书管理、通知公告管理、管理员管理、用户留言、系统…

微信小程序开发学习笔记《19》uni-app框架-配置小程序分包与轮播图跳转

微信小程序开发学习笔记《19》uni-app框架-配置小程序分包与轮播图跳转 博主正在学习微信小程序开发&#xff0c;希望记录自己学习过程同时与广大网友共同学习讨论。建议仔细阅读uni-app对应官方文档 一、配置小程序分包 分包可以减少小程序首次启动时的加载时间 为此&#…