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

news2024/11/15 21:41:46

文章目录

  • 异常处理
  • 异常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成功

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

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

相关文章

学习笔记:Opencv实现图像特征提取算法SIFT

2023.8.19 为了在暑假内实现深度学习的进阶学习&#xff0c;特意学习一下传统算法&#xff0c;分享学习心得&#xff0c;记录学习日常 SIFT的百科&#xff1a; SIFT Scale Invariant Feature Transform, 尺度不变特征转换 全网最详细SIFT算法原理实现_ssift算法_Tc.小浩的博客…

如何获得Android 14复活节彩蛋

每个新的安卓版本都有隐藏复活节彩蛋的悠久传统&#xff0c;可以追溯到以前&#xff0c;每个版本都以某种甜食命名。安卓14也不例外&#xff0c;但这一次的主题都是围绕太空构建的——还有一个复活节彩蛋。 安卓14复活节彩蛋实际上是一款很酷的小迷你游戏&#xff0c;你可以乘…

[Mac软件]MacCleaner 3 PRO 3.2.1应用程序清理和卸载

应用介绍 MacCleaner PRO是一个应用程序包&#xff0c;将帮助您清除磁盘空间并加快Mac的速度&#xff01; MacCleaner PRO - 让您的Mac始终快速、干净和有条理。 App Cleaner & Uninstaller PRO - 完全删除未使用的应用程序并管理Mac扩展。 磁盘空间分析仪PRO-分析磁盘空…

飞天使-k8s简单搭建

文章目录 k8s概念安装部署-第一版无密钥配置与hosts与关闭swap开启ipv4转发安装前启用脚本开启ip_vs安装指定版本docker 安装kubeadm kubectl kubelet,此部分为基础构建模版 k8s一主一worker节点部署k8s三个master部署,如果负载均衡keepalived 不可用&#xff0c;可以用单节点做…

STM32 CubeMX (第四步Freertos内存管理和CPU使用率)

STM32 CubeMX STM32 CubeMX &#xff08;第四步Freertos内存管理和CPU使用率&#xff09; STM32 CubeMX一、STM32 CubeMX设置时钟配置HAL时基选择TIM1&#xff08;不要选择滴答定时器&#xff1b;滴答定时器留给OS系统做时基&#xff09;使用STM32 CubeMX 库&#xff0c;配置Fr…

【Spring Cloud 二】——Spring Cloud基本介绍

Spring Cloud基本介绍 一、Spring Cloud简介二、Spring Cloud核心组件Spring Cloud Netflix组件Spring Cloud Alibaba组件Spring Cloud原生组件微服务架构图 三、Spring Cloud与Spirng Boot的关系四、Spring Cloud的版本选择Spring Cloud Alibaba的版本选择 一、Spring Cloud简…

Gradio入门到进阶全网最详细教程:快速搭建AI算法可视化部署演示(侧重项目搭建和案例分享)

常用的两款AI可视化交互应用比较&#xff1a; Gradio Gradio的优势在于易用性&#xff0c;代码结构相比Streamlit简单&#xff0c;只需简单定义输入和输出接口即可快速构建简单的交互页面&#xff0c;更轻松部署模型。适合场景相对简单&#xff0c;想要快速部署应用的开发者。便…

Azure静态网站托管

什么是静态网站托管 Azure Blob的静态网站托管是一项功能&#xff0c;它允许开发人员在Azure Blob存储中托管和发布静态网站。通过这个功能&#xff0c;您可以轻松地将静态网页、图像、视频和其他网站资源存储在Azure Blob中&#xff0c;并直接通过提供的URL访问这些资源。 官…

kafka-- kafka集群 架构模型职责分派讲解

一、 kafka集群 架构模型职责分派讲解 生产者将消息发送到相应的Topic&#xff0c;而消费者通过从Topic拉取消息来消费 Kafka奇数个节点消费者consumer会将消息拉去过来生产者producer会将消息发送出去数据管理 放在zookeeper

python安装 jieba 后显示 ModuleNotFoundError: No module named ‘jieba‘

python安装 jieba 后显示 ModuleNotFoundError: No module named jieba Traceback (most recent call last): File "d:\python\python37\lib\runpy.py", line 193, in _run_module_as_main "__main__", mod_spec) File "d:\python\python37\l…

大文本的全文检索方案附件索引

一、简介 Elasticsearch附件索引是需要插件支持的功能&#xff0c;它允许将文件内容附加到Elasticsearch文档中&#xff0c;并对这些附件内容进行全文检索。本文将带你了解索引附件的原理和使用方法&#xff0c;并通过一个实际示例来说明如何在Elasticsearch中索引和检索文件附…

BDA初级分析——SQL清洗和整理数据

一、数据处理 数据处理之类型转换 字符格式与数值格式存储的数据&#xff0c;同样是进行大小排序&#xff0c; 会有什么区别&#xff1f; 以rev为例&#xff0c;看看字符格式与数值格式存储时&#xff0c;排序会有什么区别&#xff1f; 用cast as转换为字符后进行排序 SEL…

Wazuh安装及使用

环境配置 官方网址Quickstart Wazuh documentation 可以选择Elastic Stack安装&#xff0c;也可以选择下载虚拟机&#xff08;OVA&#xff09;安装 这里展示虚拟机安装 下载好文档中提供的文件 虚拟机配置要求 在VM左上角 文件->打开->刚刚下载的.ova文件&#xff0c…

力扣974被K整除的子数组

同余定理 使用前缀和哈希表 由于可能是负数所以要进行修正&#xff1a;(sum%kk)%k class Solution { public:int subarraysDivByK(vector<int>& nums, int k) {unordered_map<int,int> hash;hash[0 % k] 1; //0 这个数的余数int sum 0, ret 0;for(auto x…

Swing程序设计(1)概述及常用组件

文章目录 前言一、什么是GUI?二、Swing概述 1.Swing包2.Swing常用组件总结 前言 该文介绍了Java中Swing组件的概述&#xff0c;以及常用组件的介绍。Swing程序是关于开发软件界面的一种轻量级Java组件。那什么是Swing组件&#xff1f;弹出对话框&#xff0c;窗体&#xff0c;设…

Java创建对象的几种方式

在Java中&#xff0c;对象是程序中的一种基本元素&#xff0c;它通过类定义和创建。本篇教程旨在介绍Java中创建对象的几种方式&#xff0c;包括使用new关键字、反射、clone、反序列化等方式。 使用new关键字创建对象 在Java中&#xff0c;最常用的创建对象方式是使用new关键…

Linux笔试题(4)

67、在局域网络内的某台主机用ping命令测试网络连接时发现网络内部的主机都可以连同,而不能与公网连通,问题可能是__C_ A.主机ip设置有误 B.没有设置连接局域网的网关 C.局域网的网关或主机的网关设置有误 D.局域网DNS服务器设置有误 解析&#xff1a;在局域网络内的某台主…

ACE内存池管理器积累

源起 近来由于研究ACE内存分配的组件&#xff0c;想做一个应用程序级的内存管理&#xff0c;有人还想自己写一个&#xff0c;我觉得可以直接用ACE自己提供的内存管理器&#xff0c;避免重复发明轮子。 结合以前认识&#xff0c;和前辈们的积累&#xff0c;觉得可以记下来一些…

【AutoLayout案例3 Objective-C语言】

一、咱们接下来,再把这个案例实现一下 1.要求, 1)在控制器的顶部,有两个UIView,一个是蓝色View,一个是红色View 2)这两个UIView的高度,永远是相等的,蓝色和红色的高度是相等的,都是50 3)红色View和蓝色View,是右对齐的 4)蓝色View,距离父控件的左边、上边、右…

双指针算法实例1(移动零)

常⻅的双指针有两种形式&#xff1a; 1 对撞指针&#xff08;左右指针&#xff09;&#xff1a; a 对撞指针从两端向中间移动。⼀个指针从最左端开始&#xff0c;另⼀个从最右端开始&#xff0c;然后逐渐往中间逼 近 b 终止条件一般是两指针相遇or错过&#xff08;也可能在循…