08.异常处理与异常Hook(软件断点Hook,硬件断点Hook)

文章目录

  • 异常处理
  • 异常Hook:
    • VEH软件断点HOOK
    • VEH硬件断点HOOK

异常处理

1.结构化异常SEH

#include <iostream>

int main()
{
    goto Exit;
    __try {
        //受保护节
        int a = 0;
        int b = 0;
        int c = a / b;
        std::cout << "触发异常" << std::endl;
    }
    /*
    EXCEPTION_CONTINUE_EXECUTION (-1) 异常已消除。 从出现异常的点继续执行。
    EXCEPTION_CONTINUE_SEARCH (0) 无法识别异常。 继续向上搜索堆栈查找处理程序,首先是所在的 try-except 语句,然后是具有下一个最高优先级的处理程序。
    EXCEPTION_EXECUTE_HANDLER (1) 异常可识别
    */
    //__except (1){
    //    std::cout << "SEH 异常" << std::endl;
    //}
    __finally {
        //终止处理程序,如果程序异常退出,将会执行
        std::cout << "异常退出" << std::endl;
    }
    std::cout << "程序即将退出" << std::endl;
Exit:
    std::cout << "正常退出" << std::endl;
}

2.向量化异常VEH:

_EXCEPTION_POINTERS:包含一个异常记录,其中包含异常的计算机独立描述,以及一个上下文记录。

typedef struct _EXCEPTION_POINTERS {
  PEXCEPTION_RECORD ExceptionRecord;
  PCONTEXT          ContextRecord;
} EXCEPTION_POINTERS, *PEXCEPTION_POINTERS;

ExceptionRecord:

其中,ExceptionRecord指向了有关异常说明的PEXCEPTION_RECORD结构体指针:

typedef struct _EXCEPTION_RECORD {
  DWORD                    ExceptionCode;
  DWORD                    ExceptionFlags;
  struct _EXCEPTION_RECORD *ExceptionRecord;
  PVOID                    ExceptionAddress;
  DWORD                    NumberParameters;
  ULONG_PTR                ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
} EXCEPTION_RECORD;

其中,Exception:发生异常的原因,这是由硬件异常生成的代码,常见错误都有宏

ExceptionFlags:异常标志

ExceptionRecord:指向相关联的指针,这是一个链状结构

ExceptionAddress:发生异常的地址

NumberParameters:与一场关联的参数的个数

ExceptionInformation:描述异常的其他参数的数组

ContextRecord:

其中ContextRecord指向了发生异常时,处理器状态的说明(上下文)

#include <iostream>
#include <Windows.h>

LONG MyVEHCallBack(
	struct _EXCEPTION_POINTERS *ExceptionInfo
) {
	//向量化异常需要我们自己选择处理方式,以及是否回去
	//异常代码
	DWORD dwCode = ExceptionInfo->ExceptionRecord->ExceptionCode;
	//判断接收到的是什么异常
	if (dwCode == EXCEPTION_BREAKPOINT) {
		//异常处理
		std::cout << "This is Int3" << std::endl;
		system("pause");
		//我们这里想处理异常后,回去,继续执行后面的代码
		//EIP 指令指针寄存器,保存了下一行要执行的位置
		//我们将EIP+1,就会执行后面的代码了
		ExceptionInfo->ContextRecord->Eip += 1;
		//返回,继续执行
		return EXCEPTION_CONTINUE_EXECUTION;
	}
	return EXCEPTION_CONTINUE_EXECUTION;
	return 0;
}

int main()
{
	/*
	//线程上下文获取
	CONTEXT ctx;
	GetThreadContext(GetCurrentThread(), &ctx);
	//设置线程上下文
	ctx.Dr0 = 111;
	SetThreadContext(GetCurrentThread(), &ctx);
	*/

	//注册向量异常处理程序
	AddVectoredExceptionHandler(
		0,      //调用处理程序的顺序,程序第一个处理异常还是最后处理异常
		(PVECTORED_EXCEPTION_HANDLER)MyVEHCallBack   //指向要调用处理程序的指针,实际上就是我们定义的处理异常函数
	);

	//这里我们使用汇编,触发一个int3断点
	//int3 软件断点 0xCC
	_asm {
		int 3
	}

	std::cout << "异常之后的代码" << std::endl;

	system("pause");
	return 0;
}

异常Hook:

会了异常处理,这里我们来看一种基于异常的Hook:

VEH软件断点HOOK

思路:我们将API实现的第一个字节改为int3断点,然后我们捕获异常,处理这个异常,将API参数修改掉

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"

ULONG_PTR MessageBoxProc = (ULONG_PTR)GetProcAddress(GetModuleHandle(L"User32.dll"), "MessageBoxW");

struct _EXECEPTION_HOOK {
	//保存要Hook的地址
	ULONG_PTR ExceptionAddress;
	//原来位置的代码/硬编码
	UCHAR OldCode;
};

_EXECEPTION_HOOK HookInfo;

//这里实际上是设置int3断点
VOID SetVEHHook(ULONG_PTR ProcAddress) {
	DWORD dwProtect = 0;
	VirtualProtect((LPVOID)ProcAddress, 1, PAGE_EXECUTE_READWRITE, &dwProtect);
	//要Hook的地址,就是我们获取的API函数地址
	HookInfo.ExceptionAddress = ProcAddress;
	//函数地址上取一字节,就是原来的硬编码
	HookInfo.OldCode = *(UCHAR*)ProcAddress;
	//将函数内部第一个字节修改位int3
	*(UCHAR*)ProcAddress = 0xCC;
	//修复内存保护属性
	VirtualProtect((LPVOID)ProcAddress, 1, dwProtect, &dwProtect);
}

//这里才是真正的Hook(修改API参数)
LONG VEHHook(
	struct _EXCEPTION_POINTERS *ExceptionInfo
) {
	if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT) {
		if ((ULONG_PTR)ExceptionInfo->ExceptionRecord->ExceptionAddress == HookInfo.ExceptionAddress) {
			const WCHAR* szStr = L"我被Hook了";
			*(DWORD*)(ExceptionInfo->ContextRecord->Esp + 8) = (DWORD)szStr;
			ExceptionInfo->ContextRecord->Eip += 2;
			return EXCEPTION_CONTINUE_EXECUTION;
		}
	}
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
		AddVectoredExceptionHandler(1, (PVECTORED_EXCEPTION_HANDLER)VEHHook);
		SetVEHHook(MessageBoxProc);
		break;
    case DLL_THREAD_ATTACH:
		break;
    case DLL_THREAD_DETACH:
		break;
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}


Hook测试:

先运行目标程序(前面讲InlineHook的时候有源码)

注入我们刚生成的dll:

注入dll
Hook成功:

Hook成功

VEH硬件断点HOOK

断点寄存器

下断点需要保存地址:保存到DR0~DR3(断点地址寄存器)

开关:DR7 : 07(L:局部,G:全局)03对应DR0~3

类型:R/W读写域 0~3 (DR0~DR3)占两位

四种状态:

00:执行时断下来(硬件执行断点)

01:写数据的时候断下来(硬件写入断点)

10:I/O终端

11:读写数据的时候都断,但是读指令不断(硬件访问断点)


长度LEN域03(DR0DR3)

四种状态

00:断点一字节长

01:断点2字节长

10:断点8字节长

11:断点4字节长


GD:启用访问检测功能:

如果开启了此位,当修改DR系列寄存器的时候,CPU会触发异常


DR6:

B0~B3:某一组

如果B0被设置为1,说明DR0的R/W,LEN位都被满足条件了

VEH硬件断点优势:不修改内存,如果有内存检测,就不会触发

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"

ULONG_PTR MessageBoxProc = (ULONG_PTR)GetProcAddress(GetModuleHandle(L"User32.dll"), "MessageBoxW");

struct _EXECEPTION_HOOK {
	//保存要Hook的地址
	ULONG_PTR ExceptionAddress;
	//原来位置的代码/硬编码
	UCHAR OldCode;
};

_EXECEPTION_HOOK HookInfo;

//这里实际上是设置int3断点
VOID SetVEHHook(ULONG_PTR ProcAddress) {
	DWORD dwProtect = 0;
	VirtualProtect((LPVOID)ProcAddress, 1, PAGE_EXECUTE_READWRITE, &dwProtect);
	//要Hook的地址,就是我们获取的API函数地址
	HookInfo.ExceptionAddress = ProcAddress;
	//函数地址上取一字节,就是原来的硬编码
	HookInfo.OldCode = *(UCHAR*)ProcAddress;
	//将函数内部第一个字节修改位int3
	*(UCHAR*)ProcAddress = 0xCC;
	//修复内存保护属性
	VirtualProtect((LPVOID)ProcAddress, 1, dwProtect, &dwProtect);
}

//这里才是真正的Hook(修改API参数)
LONG VEHHook(
	struct _EXCEPTION_POINTERS *ExceptionInfo
) {
	if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT) {
		if ((ULONG_PTR)ExceptionInfo->ExceptionRecord->ExceptionAddress == HookInfo.ExceptionAddress) {
			const WCHAR* szStr = L"我被Hook了";
			*(DWORD*)(ExceptionInfo->ContextRecord->Esp + 8) = (DWORD)szStr;
			ExceptionInfo->ContextRecord->Eip += 2;
			return EXCEPTION_CONTINUE_EXECUTION;
		}
	}
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
		AddVectoredExceptionHandler(1, (PVECTORED_EXCEPTION_HANDLER)VEHHook);
		SetVEHHook(MessageBoxProc);
		break;
    case DLL_THREAD_ATTACH:
		break;
    case DLL_THREAD_DETACH:
		break;
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}


Hook测试:

先运行目标程序

注入dll:

注入dll
Hook成功:
Hook成功

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【JVM】垃圾回收算法

目录 一、判断对象已“死” 1.1、引用计数算法 1.2、可达性分析算法 1.3、引用的概念 二、垃圾收集算法理论 2.1、分代收集理论 三、垃圾收集算法 3.1、标记--清除算法 3.2、标记--复制算法 3.3、标记--整理算法 一、判断对象已“死” 在堆里面存放着Java世界中几乎所…

ATF(TF-A)安全通告 TFV-8 (CVE-2018-19440)

安全之安全(security)博客目录导读 ATF(TF-A)安全通告汇总 目录 一、ATF(TF-A)安全通告 TFV-8 (CVE-2018-19440) 二、CVE-2018-19440 一、ATF(TF-A)安全通告 TFV-8 (CVE-2018-19440) Title 不保存x0~x3寄存器可能会将信息从一个非安全世界的SMC client泄漏到另一个 CVE ID …

【电子通识】什么是异常分析中的A-B-A方法

工作有了一定的经验之后&#xff0c;在做问题分析的时候&#xff0c;经常会听到别人说把这个部品&#xff08;芯片/模块&#xff09;拿去ABA一下&#xff0c;看看跟谁走。那么对于新人来说是否就会问一个问题&#xff1a;什么是ABA呢&#xff1f; A-B-A 交换是一种简单直接的交…

Nvidia Jetson 编解码开发(1)介绍

前言 由于项目需要&#xff0c;需要开发Jetson平台的硬件编解码&#xff1b; 优化CPU带宽&#xff0c;后续主要以介绍硬件编解码为主 1.Jetson各平台编解码性能说明 如下是拿了Jetson nano/tx2/Xavier等几个平台做对比&#xff1b; 这里说明的编解码性能主要是对硬件来说的…

CefSharp自定义缓存实现

提高页面加载加速&#xff1a;CefSharp缓存可以缓存已经加载过的页面和资源&#xff0c;当用户再次访问相同的页面时&#xff0c;可以直接从缓存中加载&#xff0c;而不需要重新下载和解析页面和资源&#xff0c;从而加快页面加载速度。减少网络流量&#xff1a;使用缓存可以减…

使用chatGPT-4 畅聊量子物理学(三)

集合了人类智慧的照片&#xff0c;来自 1927 年举行的第五届索尔维国际会议。 Omer 什么是“物理系统在被测量之前不具有确定的属性。量子力学只能预测给定测量的可能结果的概率分布" ChatGPT 这句话描述了量子力学中的一种基本原则&#xff0c;即“物理系统在被测量之前…

使用Dockerfile部署java项目

1、移动java包到创建的目录下 2、编写Dockerfile文件 在同一目录下使用如下命令创建文件 touch Dockerfile 文件内容如下&#xff1a; #依赖的父镜像 FROM java:8 #作者 MAINTAINER maxurui #jar包添加到镜像中 ADD springboot3-0.0.1-SNAPSHOT.jar springboot3-0.0.1-SNAPSHO…

外贸邮箱签名怎么写?改版提升点击率的关键技巧揭秘!

外贸业务常用的一种营销工具就是电子邮件&#xff0c;而电子邮件的签名作为邮件信任度和品牌价值的体现&#xff0c;同样也是非常重要的。那么如何写一份优秀的外贸邮箱签名呢&#xff1f; 下面是几点建议。 第一&#xff0c;突出品牌形象。在签名中加入公司标志或相关图片可以…

Redis专题-秒杀

Redis专题-并发/秒杀 开局一张图&#xff0c;内容全靠“编”。 昨天晚上在群友里看到有人在讨论库存并发的问题&#xff0c;看到这里我就决定写一篇关于redis秒杀的文章。 1、理论部分 我们看看一般我们库存是怎么出问题的 其实redis提供了两种解决方案&#xff1a;加锁和原子操…

JavaWeb_LeadNews_Day6-Kafka

JavaWeb_LeadNews_Day6-Kafka Kafka概述安装配置kafka入门kafka高可用方案kafka详解生产者同步异步发送消息生产者参数配置消费者同步异步提交偏移量 SpringBoot集成kafka 自媒体文章上下架实现思路具体实现 来源Gitee Kafka 概述 对比 选择 介绍 producer: 发布消息的对象称…

开源远程控制硬件 BliKVM v4测试 1000公里外远程重装系统

测试准备 测试时间&#xff1a;20230818 测试硬件&#xff1a;BliKVM v4 文档 BliKVM v4是一款生产就绪、即插即用的 KVM-over-IP 设备&#xff0c;为专业用户提供了远程服务器或工作站管理的便捷解决方案。 它基于Linux并且完全开源。 借助 BliKVM&#xff0c;您可以轻松打…

19-普通组件的注册使用

普通组件的注册使用-局部注册 一. 组件注册的两种方式:1.局部注册:只能在注册的组件内使用 (1) 创建 vue 文件(单文件组件) (2) 在使用的组件内导入,并注册 components:{ 组件名: 组件对象 } // 导入需要注册的组件 import 组件对象 from.vue文件路径 import HmHeader from ./…

深入学习前端开发,掌握HTML、CSS、JavaScript等技术

课程链接&#xff1a; 链接: https://pan.baidu.com/s/1WECwJ4T8UQfs2FyjUMbxig?pwdi654 提取码: i654 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 --来自百度网盘超级会员v4的分享 课程介绍&#xff1a; 第1周&#xff1a;HTML5基础语法与标签 &#x1f…

基于Java+SpringBoot+vue前后端分离在线BLOG网站系统设计实现

基于JavaSpringBootvue前后端分离在线BLOG网站系统设计实现&#xff08;程序源码毕业论文&#xff09; 大家好&#xff0c;今天给大家介绍基于JavaSpringBootvue前后端分离在线BLOG网站系统设计与实现&#xff0c;本论文只截取部分文章重点&#xff0c;文章末尾附有本毕业设计完…

基于Python的高校学生成绩分析系统

随着计算机技术发展&#xff0c;计算机系统的应用已延伸到社会的各个领域&#xff0c;大量基于网络的广泛应用给生活带来了十分的便利。所以把高校成绩分析与现在网络相结合&#xff0c;利用计算机搭建高校成绩分析系统&#xff0c;实现高校成绩分析的信息化。则对于进一步提高…

Idea中隐藏指定文件或指定类型文件

Setting ->Editor ->Code Style->File Types → Ignored Files and Folders输入要隐藏的文件名&#xff0c;支持*号通配符回车确认添加

通过爬虫抓取上市企业利润表并在睿思BI中展示

睿思BI从v5.3开始支持网络爬虫&#xff0c;可以从指定URL抓取表格数据&#xff0c;本示例实现从网络上抓取上市企业招商银行的利润表数据&#xff0c;并在睿思BI中进行展现。 功能演示URL&#xff1a;https://www.ruisitech.com/rsbi-ultimate/#/dashboard/ShareView?token31…

Maven介绍_下载_安装_使用_原理

文章目录 1 Maven介绍1.1 Maven是介绍1.2 Maven的作用 2 Maven下载与安装2.1 官网下载2.2 文件目录2.3 环境配置 3 Maven基础概念3.1 仓库分类3.2 依赖坐标3.3 坐标组成 4 Maven配置4.1 本地仓库配置4.2 远程仓库的设置4.3 镜像仓库配置4.4 IDEA配置Maven 5 Maven项目创建5.1 M…

Dockers搭建个人网盘、私有仓库,Dockerfile制作Nginx、Lamp镜像

目录 1、使用mysql:5.6和 owncloud 镜像&#xff0c;构建一个个人网盘。 &#xff08;1&#xff09;下载mysql:5.6和owncloud镜像 &#xff08;2&#xff09;创建启动mysql:5.6和owncloud容器 &#xff08;3&#xff09;在浏览器中输入网盘服务器的IP地址&#xff0c;进行账…

CentOS6.8图形界面安装Oracle11.2.0.1.0

Oracle11下载地址 https://edelivery.oracle.com/osdc/faces/SoftwareDelivery 一、环境 CentOS release 6.8 (Final)&#xff0c;测试环境&#xff1a;内存2G&#xff0c;硬盘20G&#xff0c;SWAP空间4G Oracle版本&#xff1a;Release 11.2.0.1.0 安装包&#xff1a;V175…