反调原理

该检测方式使用 IsDebuggerPresent 或者 CheckRemoteDebuggerPresent 函数,这两个函数都是 kernel32.dll 中实现的

对于 IsDebuggerPresent 函数,如果返回值为 TRUE,那么表示当前进程在调试器上下文中运行

CheckRemoteDebuggerPresent 的底层是通过 NtQueryInformationProcess 函数来实现的,函数接受一个 BOOL 的指针参作为返回值

函数调用成功的时候返回非零值,这时候检查出参 pbDebuggerPresent 指针的值,如果值为 TRUE,那么表示当前进程正在被调试中

使用这两个函数需要引用 windows.h 头文件,函数的原型分别如下

BOOL IsDebuggerPresent();BOOL CheckRemoteDebuggerPresent(HANDLE hProcess, PBOOL pbDebuggerPresent);

IsDebuggerPresent 实际上是查询当前进程的 PEB(Process Environment Block)中的 BeingDebugged 字段

PEB 结构是进程环境块,是 Windows 内核中一个核心的内部数据结构,包含了进程的大量信息,在 Windows SDK 的 winternl.h 提供了部分定义

PEB 的结构如下,IsDebuggerPresent 使用了第二个字段 BeingDebugged,当被调试的时候该字段值被置为 1

typedef struct _PEB {BYTE Reserved1[2];BYTE BeingDebugged;BYTE Reserved2[1];PVOID Reserved3[2];PPEB_LDR_DATA Ldr;PRTL_USER_PROCESS_PARAMETERS ProcessParameters;PVOID Reserved4[3];PVOID AtlThunkSListPtr;PVOID Reserved5;ULONG Reserved6;PVOID Reserved7;ULONG Reserved8;ULONG AtlThunkSListPtr32;PVOID Reserved9[45];BYTE Reserved10[96];PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;BYTE Reserved11[128];PVOID Reserved12[1];ULONG SessionId;
} PEB, *PPEB;

实现代码

完整的反调试的实现代码如下

#include <iostream>
#include <thread>
#include <string>
#include <vector>
#include <windows.h>
#include <TlHelp32.h>
#include <winternl.h>bool CheckProcessIsDebuging()
{//return IsDebuggerPresent();BOOL isDebugging = FALSE;HANDLE hHandle = GetCurrentProcess();CheckRemoteDebuggerPresent(hHandle, &isDebugging);return isDebugging;
}void ThreadProc()
{while (true){if (CheckProcessIsDebuging()){std::cout << "Debugging..." << std::endl;}else{std::cout << "Running..." << std::endl;}std::this_thread::sleep_for(std::chrono::milliseconds(1000));}
}int main()
{std::thread thrd(ThreadProc);thrd.join();return 0;
}

逆向处理

对于 IsDebuggerPresent 的绕过

x64dbg 附加载入 anti04.exe 后,在符号窗口中选中主模块,然后右侧查看到模块,显示它的一个导入函数 IsDebuggerPresent

20250704150632

选定 kernel32.IsDebuggerPresent 然后右键 “在内存窗口中转到”,内存窗口中显示了 IAT 表的该函数的导入项

内存的值即是 kernel32.IsDebuggerPresent 函数的实际地址,选择该内存地址,右键 “搜索引用”

然后在引用页面中双击引用记录跳转到 IsDebuggerPresent 函数的调用处,然后在该 call 处进行下断点

20250704163412

这里的绕过方式有两种,一个是在 call 之后 test 前修改 eax 的值为 0,但是这个只对当前的一次 call 调用生效

另一个是直接修改 peb 中的 BeingDebugged 字段值,需要先定位到 peb 的内存地址,然后再进行修改

关于 peb 地址是固定的 gs:[60],其中 gs 是 TEB 的段寄存器,gs:[0x60] 是 TEB + 0x60 偏移处的值,是当前线程所属进程的 PEB 的地址

在左下角的命令框中输入 gs:[60] 后回车,然后下方显示出 peb 的内存地址,点击该地址在内存窗口中进行跳转

然后在该地址中,修改第三个字节为 0(未修改前为 1 表示在调试中),之后的运行就会显示程序未处于调试中了

20250704163813

在 x64dbg 中,可以通过 ScyllaHide 插件进行绕过,安装插件后,默认就已经勾选了对 BeingDebugged 的绕过

这里主要是学习反调试的基本原理,在此不会对插件的使用进行过多的说明

20250704165219

对于 CheckRemoteDebuggerPresent 的绕过

在 cpu 主窗口中 ctrl + G 输入 CheckRemoteDebuggerPresent 进行搜索,得到下面的地址

20250704172952

选中该行记录 entry 跳转到 CheckRemoteDebuggerPresent 函数的汇编代码位置

20250704173702

下面这两行的 ds:[rdi] 就是函数的第二个参数 pbDebuggerPresent,ebx = 0 或 1(是否检测到调试器)

setne bl 会根据前面 cmp 判断是否写入 bl = 1,因此将这句汇编进行覆盖即可,覆盖为清空 ebx

00007FF89ECC7B60     | 0F95C3                   | setne bl                                        |
00007FF89ECC7B63     | 891F                     | mov dword ptr ds:[rdi],ebx                      |

覆盖后的代码显示如下,这时候就可以实现了对 CheckRemoteDebuggerPresent 的绕过

20250704174058

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

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

相关文章

翻译《The Old New Thing》- Windows 媒体目录中 onestop.mid 文件的故事

Whats the story of the onestop.mid file in the Media directory? - The Old New Thinghttps://devblogs.microsoft.com/oldnewthing/20130212-00/?p5263 如果你查看你的C:\Windows\Media文件夹&#xff0c;会发现一个名为onestop的MIDI文件。这个奇怪的小MIDI文件背后有什…

【方案】前端UI布局的绝技,响应式布局,多端适配

大家好&#xff0c;欢迎来到停止重构的频道。本期讨论网页UI布局。网页UI布局是前端开发中占比较多的部分&#xff0c;做完网页布局也就差不多完成了一半的工作。本期视频&#xff0c;我们不再讨论基础的UI布局。我们希望满足响应式布局&#xff0c;一份代码适配PC/平板/手机等…

【郑大二年级信安小学期】Day4上午:Bool盲注时间盲注堆叠查询post注入HTTP头部注入ua字段

目录 0 录制文件 1 SQL注入-布尔盲注 1.1 布尔盲注优缺点 1.2 先看一下第八关嗯页面特征 1.3 步骤 1.4 常用函数 1.5 判断是否字符型 1.6 判断闭合 1.7 查询库名 1.8 查询数据表 1.9 获取字段名 1.10 获取数据 1.11 布尔盲注缺陷 2 时间盲注 2.1 基础知识 2.2 判…

如何设计一个“真正可复用”的前端组件?

&#x1f9f1; 如何设计一个“真正可复用”的前端组件&#xff1f;&#x1f527; 一个按钮可以写10次&#xff0c;也可以封装一次复用全场&#xff1b;组件是前端的积木&#xff0c;而设计模式才是组装它们的说明书。你真的在写“可复用”组件吗&#xff1f;&#x1f9e0; 什么…

AlpineLinux安装RabbitMQ及其管理界面

AlpineLinux安装RabbitMQ及其管理界面 本文以 alpine linux 的 3.21版本为例,演示对于 RabbitMQ 在Linux 下的安装,其他发行版本大同小异。主要是包管理软件的命令区别,以及在线仓库提供的 RabbitMQ 版本差异而已。 (一)安装 Erlang 因为 RabbitMQ 是用 Erlang 语言编写…

3S技术+ArcGIS/ENVI全流程实战:水文、气象、灾害、生态、环境及卫生等领域应用

系统梳理3S技术的核心理论与实战应用&#xff0c;涵盖ArcGIS与ENVI软件操作、空间数据管理、地图投影转换、遥感影像解译、DEM地形分析、空间插值建模等关键技能&#xff0c;并结合农业、气象、生态、灾害等跨学科案例&#xff0c;提供从数据获取到高级可视化的完整解决方案。无…

弹窗中el+table,二次打开弹窗,选择列会携带第一次选择的数据

1第一次打开弹窗选择的数据&#xff0c;正确&#xff0c;然后关闭弹窗再次打开弹窗&#xff0c;重新选择&#xff0c;第二次的数据&#xff0c;错误在打开弹窗/关闭弹窗等位置全部做了置空处理&#xff0c;以下是代码&#xff1a;最后的原因是&#xff1a;el-dailog 自带缓存&a…

RocketMQ在Spring Boot中的详细使用指南

📋 目录 🚀 RocketMQ简介 什么是RocketMQ? 核心概念 🏗️ 基础架构组件 📝 重要概念解释 🔧 环境搭建 1. RocketMQ服务端安装 Docker方式(推荐初学者) 手动安装方式 2. 验证安装 🏗️ Spring Boot集成配置 1. 添加依赖 2. 配置文件 application.y…

基于Java+Springboot的医院档案管理系统

源码编号&#xff1a;S597源码名称&#xff1a;基于Springboot的医院档案管理系统用户类型&#xff1a;多角色&#xff0c;用户、医护人员、管理员数据库表数量&#xff1a;11 张表主要技术&#xff1a;Java、Vue、ElementUl 、SpringBoot、Maven运行环境&#xff1a;Windows/M…

Pandas 学习教程

目录 定义 基本操作 一维数组操作 二维数组操作 数据选择过滤 数据处理 数据清洗 数据转换 数据分析 排序 分组聚合 数据透视表 高级操作 合并数据 时间序列处理 自定义函数调用 数据可视化集成 数据导出和导入 大数据分块处理 定义 全称&#xff1a; panel da…

QueryWrapper 类的作用与示例详解

通俗易懂的解释想象一下你去图书馆找书&#xff1a;QueryWrapper 就像是一个智能的图书管理员你告诉管理员你的需求&#xff1a;"我要找计算机类、2020年后出版的、作者是张三的书"管理员会根据你的要求组合查询条件&#xff0c;然后去书库帮你找书在编程中&#xff…

【PyTorch】PyTorch中torch.nn模块的循环层

PyTorch深度学习总结 第九章 PyTorch中torch.nn模块的循环层 文章目录PyTorch深度学习总结前言一、循环层1. 简单循环层&#xff08;RNN&#xff09;2. 长短期记忆网络&#xff08;LSTM&#xff09;3. 门控循环单元&#xff08;GRU&#xff09;4. 双向循环层二、循环层参数1. …

Ubuntu 24.04 LTS 服务器配置:安装 JDK、Nginx、Redis。

Ubuntu 24.04 LTS 服务器配置&#xff1a;安装 JDK、Nginx、Redis。新建用来放置软件安装包的目录 mkdir /home/software 配置目录所有者为 ubuntu 用户&#xff1a; chown ubuntu /home/software将软件安装包上传到 /home/software配置 JDK-8 新建 jdk 安装目录 mkdir /usr/ja…

工作中用到过哪些设计模式?是怎么实现的?

1. 单例模式&#xff08;结合 Spring Component&#xff09;场景&#xff1a;配置中心、全局状态管理 Spring 实现&#xff1a;java// 自动注册为Spring Bean&#xff08;默认单例&#xff09; Component public class AppConfig {Value("${server.port}")private in…

Leetcode 3609. Minimum Moves to Reach Target in Grid

Leetcode 3609. Minimum Moves to Reach Target in Grid 1. 解题思路2. 代码实现 题目链接&#xff1a;3609. Minimum Moves to Reach Target in Grid 1. 解题思路 这一题我一开始走岔了&#xff0c;走了一个正向遍历走法的思路&#xff0c;无论怎么剪枝都一直超时。后来看了…

工作流引擎:IDEA没有actiBPMN插件怎么办?

文章目录一、问题描述二、替代方案一、问题描述 我们在学习activiti7工作流引擎的时候&#xff0c;需要设计流程图。 一般推荐的就是使用IDEA插件actiBPMN进行开发。 但是&#xff0c;这个插件在IDEA2019后的版本都不在支持。 也就是搜不到 那么&#xff0c;怎么办了&#x…

Android音视频探索之旅 | CMake基础语法 创建支持Ffmpeg的Android项目

一.CMake语法 CMake语法非常多&#xff0c;我们知道如何导入静态库和动态库以及最基础的使用&#xff0c;目前是够用的。其它方面则根据实际项目同步学习。 1.1.基础语法-常用 cmake_minimum_required&#xff1a;指定cmake最小版本include_directories&#xff1a;引入&#x…

React Native 初始化项目和模拟器运行

中文官方文档&#xff1a;https://reactnative.cn/docs/environment-setup 英文官方文档&#xff1a;https://reactnative.dev/docs/getting-started-without-a-framework#step-1-creating-a-new-application 创建新项目 1、初始化 # 如果你之前全局安装过旧的react-native-cli…

20250706-5-Docker 快速入门(上)-创建容器常用选项_笔记

一、创建容器常用选项&#xfeff;&#xfeff;1. 创建容器常用选项&#xfeff;1&#xff09;常用选项创建容器常用选项&#xfeff;交互式选项&#xff1a;-i&#xff1a;保持标准输入打开&#xff0c;允许交互式操作-t&#xff1a;分配伪终端&#xff0c;使容器像传统终端一…

插值与拟合(3):B样条曲线

在路径规划问题中&#xff0c;通常会用到B样条来平滑路径&#xff0c;本文实现并封装了三次准均匀开放B样条曲线&#xff0c;供大学学习使用。作者提供了三套代码方案。可以用于不同平台&#xff1a;方案1&#xff1a;MATLAB&#xff1b;方案2&#xff1a;标准C&#xff1b;方案…