【加密与解密(第四版)】第十三章笔记

第十三章 HOOK技术

13.1 Hook概述

IAT HOOK(改地址)

BOOL IAT_InstallHook()

{

BOOL bResult = FALSE ;

HMODULE hCurExe = GetModuleHandle(NULL);

PULONG_PTR pt ;

ULONG_PTR OrginalAddr;

bResult = InstallModuleIATHook(hCurExe,"user32.dll","MessageBoxA",(PVOID)My_MessageBoxA,&pt,&OrginalAddr);

if (bResult)

{

printf("[*]Hook安装完毕! pThunk=0x%p  OriginalAddr = 0x%p\n",pt,OrginalAddr);

g_PointerToIATThunk = pt ;

OldMessageBox = (PFN_MessageBoxA)OrginalAddr ;

}

return bResult;



}



//************************************

// FullName:    InstallModuleIATHook

// Description: 为指定模块安装IAT Hook

// Access:      public

// Returns:     BOOL

// Parameter:   HMODULE hModToHook , 待Hook的模块基址

// Parameter:   char * szModuleName , 目标函数所在模块的名字

// Parameter:   char * szFuncName , 目标函数的名字

// Parameter:   PVOID DetourFunc , Detour函数地址

// Parameter:   PULONG * pThunkPointer , 用以接收指向修改的位置的指针

// Parameter:   ULONG * pOriginalFuncAddr , 用以接收原始函数地址

//************************************

BOOL InstallModuleIATHook(

    HMODULE hModToHook,// 要钩取的模块的句柄

    char *szModuleName,// 要钩取的模块的名称

    char *szFuncName,// 要钩取的函数的名称

    PVOID DetourFunc,// 替换原始函数的钩子函数的地址

    PULONG_PTR *pThunkPointer,// 用于存储指向导入地址的指针的指针

    ULONG_PTR *pOriginalFuncAddr// 用于存储原始函数地址的指针

    )

{

    PIMAGE_IMPORT_DESCRIPTOR  pImportDescriptor; // 指向导入描述符表的指针

    PIMAGE_THUNK_DATA         pThunkData; // 指向导入函数表的指针

    ULONG ulSize; // 导入描述符表的大小

    HMODULE hModule=0; // 加载模块的句柄

    ULONG_PTR TargetFunAddr; // 目标函数的地址

    PULONG_PTR lpAddr; // 导入地址的指针

    char *szModName; // 当前模块的名称

    BOOL result = FALSE ; // 返回值,默认为失败

    BOOL bRetn = FALSE; // 操作结果,默认为失败



    hModule = LoadLibrary(szModuleName); // 加载要钩取的模块

    TargetFunAddr = (ULONG_PTR)GetProcAddress(hModule,szFuncName); // 获取要钩取的函数的地址

    printf("[*]Address of %s:0x%p\n",szFuncName,TargetFunAddr); // 输出目标函数的地址

    printf("[*]Module To Hook at Base:0x%p\n",hModToHook); // 输出要钩取的模块的基地址

    pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(hModToHook, TRUE,IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize); // 获取导入描述符表的地址

    printf("[*]Find ImportTable,Address:0x%p\n",pImportDescriptor); // 输出导入描述符表的地址

    while (pImportDescriptor->FirstThunk) // 遍历导入描述符表,直到遇到空描述符

    {

        szModName = (char*)((PBYTE)hModToHook+pImportDescriptor->Name) ; // 获取当前模块的名称

        printf("[*]Cur Module Name:%s\n",szModName); // 输出当前模块的名称

        if (stricmp(szModName,szModuleName) != 0) // 若当前模块名称与要钩取的模块名称不匹配

        {

            printf("[*]Module Name does not match, search next...\n"); // 输出模块名称不匹配的信息

            pImportDescriptor++; // 继续下一个导入描述符表

            continue; // 继续下一次循环

        }

        // 程序的导入表处理完毕后OriginalFirstThunk可能是无效的,不能再根据名称来查找,而是遍历FirstThunk直接根据地址判断

        pThunkData = (PIMAGE_THUNK_DATA)((BYTE *)hModToHook + pImportDescriptor->FirstThunk); // 获取导入函数表的地址

        while(pThunkData->u1.Function) // 遍历导入函数表,直到遇到空条目

        {

            lpAddr = (ULONG_PTR*)pThunkData; // 获取导入地址的指针

            // 找到了地址

            if((*lpAddr) == TargetFunAddr) // 如果导入地址与目标函数地址相等

            {

                printf("[*]Find target address!\n"); // 输出找到目标地址的信息

                // 通常情况下导入表所在内存页都是只读的,因此需要先修改内存页的属性为可写

                DWORD dwOldProtect; // 旧的保护属性

                MEMORY_BASIC_INFORMATION  mbi; // 内存页信息结构体

                VirtualQuery(lpAddr,&mbi,sizeof(mbi)); // 获取内存页的信息

                bRetn = VirtualProtect(mbi.BaseAddress,mbi.RegionSize,PAGE_EXECUTE_READWRITE,&dwOldProtect); // 修改内存页的保护属性为可写

                if (bRetn) // 如果修改成功

                {

                    // 内存页属性修改成功,继续下一步操作,先保存原始数据

                    if (pThunkPointer != NULL) // 如果指针不为空

                    {

                        *pThunkPointer = lpAddr ; // 将导入地址的指针赋值给pThunkPointer

                    }

                    if (pOriginalFuncAddr != NULL) // 如果指针不为空

                    {

                        *pOriginalFuncAddr = *lpAddr ; // 将导入地址的值赋值给pOriginalFuncAddr

                    }

                    // 修改地址

                    *lpAddr = (ULONG_PTR)DetourFunc; // 将导入地址的值修改为钩子函数的地址

                    result = TRUE ; // 操作成功

                    // 恢复内存页的属性

                    VirtualProtect(mbi.BaseAddress,mbi.RegionSize,dwOldProtect,0); // 恢复内存页的保护属性

                    printf("[*]Hook ok.\n"); // 输出钩子成功的信息

                }

               

                break; // 跳出循环

            }

            //---------

            pThunkData++; // 继续下一个导入函数表条目

        }

        pImportDescriptor++; // 继续下一个导入描述符表

    }

   

    FreeLibrary(hModule); // 释放加载的模块

    return result; // 返回操作结果

}

InLine Hook(改内容)

13.2  HOOK的分类

名目繁多的 Hook,总结起来其实只有两种:Address Hook和Inline Hook。

Address Hook:IAT、EAT、user32.dll的回调函数表、IDT(中断描述符表)、SSDT(系统服务描述符表)、C++类的虚函数表、COM接口的功能函数表、处理例程地址、特殊寄存器中的地址、特定的函数指针

Inline Hook:

基于异处理的HOOK

13.3 HOOK位置的挑选

影响最小的 Hook:应用程序中的call Hook,可精确到特定位置对特定 API的调用。

影响最大的Hook:在系统内核中,大部分Hook的位置都会影响整个系统的调用过程,越往下就越明显。

在内核中,KiFastCallEnlry和KeServiceDescriptorTable(含 Shadow)是两个绝佳的Hook位置。

13.4 HOOK的典型过程

Address Hook 的实施过程:定义Detour()函数、定义函数指针、查表(遍历匹配)替换原函数地址、关闭写保护、写入Detour()函数的地址

Inline Hook 的实施过程:确定 Hook方式及需要在Trampoline 中执行的指令、准备TrampolineFun函数、准备jmp指令并写入、CALLL HOOK

二次HOOK

13.5  Detour函数的典型用法

检查参数、检查结果、拦截调用或下发

13.6  HOOK中的注意事项

多线程安全、保存和恢复现场、注意返回值、避免重入

13.7  HOOK在X64平台上的新问题

指针的定义与操作、内存地址对齐、PE格式、调用约定的变化、跳转指令的问题、PatchGuard问题

13.8  HOOK技术的应用

实现增强的二次开发或补丁、信息截获、安全防护

13.9  HOOK的检测、恢复与对抗

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

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

相关文章

将联表查询到的数据按1000一批次存入数据库-模板

idea模板: /*** ${Shitilei}信息 服务层实现。** author admin*/ Service RequiredArgsConstructor public class Operate${Shitilei}Service {private final ${Shitilei}Mapper ${shitilei}Mapper;private final RegionUtil util;/*** ${shitilei}表* return 操作结…

解决Ubuntu无法使用root登录的问题

1、登录普通用户 2、使用vi编辑器打开/etc/pam.d/gdm-autologin并注释掉auth required pam_succeed_if.so user ! root quiet_success 3、使用vi编辑器打开/etc/pam.d/gdm-password并注释掉auth required pam_succeed_if.so user ! root quiet_success 4、注销用户重新用roo…

【网络协议】【OSI】一次HTTP请求OSI工作过程详细解析

目录 1. 一次HTTP请求OSI工作过程 1.1 应用层(第7层) 1.2 表示层(第6层) 1.3 会话层(第5层) 1.4 传输层(第4层) 1.5 网络层(第3层) 1.6 数据链路层&am…

Z缓冲技术在AI去衣中的关键角色

引言: 人工智能(AI)技术的飞速发展,为图像处理领域带来了革命性的变化。其中,AI去衣技术作为一种新兴的应用,引起了广泛关注。它不仅在多媒体内容的编辑、虚拟现实和增强现实等领域具有重要的应用价值&…

Java八大类型详解

整数类型 (4种) 整数的类型 类型占用内存空间范围byte [字节]1字节-128 ~ 127存放的范围是>二进制short [短整型]2字节 -(2⁵) ~ 2⁵-1 -32768 ~ 32767 int [整形]4字节 -2 ~ 2-1 -2147483648 - 2147483647 long [长整形]8字节-2⁶ ~ 2⁶-1 整数类型的使用细节 1. Java个…

el-table 划入划出方法

<template><div><el-table :data"tableData" style"width: 100%" cell-mouse-enter"handleMouseEnter" cell-mouse-leave"handleMouseLeave"><el-table-column prop"ddd" label"日期2" widt…

Java 数组的基本使用

目录 含义语法格式语句特点数组的长度数组的元素打印数组显示数组数组的复制扩展示例【12】&#xff1a; 含义 数组&#xff08;array&#xff09;是一种最简单的复合数据类型&#xff0c;它是有序数据的集合&#xff0c;数组中的每个元素具有相同的数据类型&#xff0c;可以用…

Mysql基础教程(06):NOT IN

数据准备 首先创建一个数据库educational_manage&#xff0c;记住字符集和排序规则如下选择&#xff1a; 接着创建表和数据&#xff0c;具体的sql代码如下&#xff1a; SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS 0;-- ---------------------------- -- Table structure f…

JavaScript-隐式转换和显式转换

为什么需要类型转换&#xff1f; 因为JavaScript是弱类型声明&#xff0c;在没赋值前是不知道数据的类型的&#xff0c;只有赋值了才知道&#xff0c;表单和prompt获取的数据都是字符串型&#xff0c;此时就不能直接的简单加减法运算 所以需要转换数据类型 隐式转换 某些运算符…

Xcode=> 安装 simulator

XCode xcode中下载 simulator 点击加号➕&#xff0c;选择对应的版本&#xff0c;即可下载 下载完成&#xff1a; 其他下载办法 因为使用上述下载&#xff0c;会经常性的出现断开&#xff0c;再次下载又是从头开始&#xff0c;太费时费力。下面使用下载地址&#xff0c;然后用…

仓库管理WMS软件(Warehouse Management Software)百科解析

一、什么是仓库管理软件&#xff08;WMS&#xff09;&#xff1f; 仓库管理软件&#xff08;WMS&#xff09;全称Warehouse Management System&#xff0c;是一种专门用于仓库作业流程优化和库存控制的软件系统。它通过先进的自动识别与数据采集技术&#xff0c;实现对仓库货物…

人工智能(Educoder)-- 机器学习 -- 神经网络(初级)

第一关 注&#xff1a; 神经网络的起源和应用 起源&#xff1a;神经网络最早由心理学家和神经学家开创&#xff0c;目的是模拟生物神经系统对真实世界物体的交互反应。应用&#xff1a;现代神经网络用于分类&#xff08;如图像识别、文本分类&#xff09;和数值预测&#xff08…

全球手游4月战报,《Monopoly GO!》荣耀再续!全球手游畅销榜冠军

易采游戏网5月22日消息&#xff0c;在刚刚过去的四月里&#xff0c;全球移动游戏市场的角逐愈发激烈。根据最新发布的数据&#xff0c;Scopely旗下的经典游戏《Monopoly GO!》再次蝉联全球手游畅销榜首冠军宝座&#xff0c;展现了无与伦比的市场魅力与玩家黏度。 4月Scopely《M…

Docker | 基础指令

环境&#xff1a;centos8 参考&#xff1a; 安装 Docker | Docker 从入门到实践https://vuepress.mirror.docker-practice.com/install/ 安装Docker 卸载旧版本&#xff0c;安装依赖包&#xff0c;添加yum软件源&#xff0c;更新 yum 软件源缓存&#xff0c;安装 docker-ce…

Neural Filters:风景混合器

Ps菜单&#xff1a;滤镜/Neural Filters/创意/风景混合器 Neural Filters/CREATIVE/Landscape Mixer 风景混合器 Landscape Mixer滤镜通过与另一个图像混合或改变诸如时间和季节等属性&#xff0c;神奇地改变景观。 “风景混合器”滤镜利用人工智能和机器学习技术&#xff0c;首…

使用Prometheus + Blackbox-exporter快速监控一个网站性能和SSL过期时间

使用blackbox-exporter快速监控一个网站性能和SSL过期时间 环境介绍什么是blackbox-exporter下载blackbox-exporter安装blackbox-exporter配置Prometheus服务端查看job上线监控面板参考文献 环境介绍 本文实验环境 操作系统&#xff1a;Centos 7.9Prometheus版本&#xff1a;…

局部直方图均衡化去雾算法

目录 1. 引言 2. 算法流程 3. 代码 4. 去雾效果 1. 引言 局部直方图算法是一种基于块的图像去雾方法&#xff0c;它将图像分割为若干个块&#xff0c;并在每个块内计算块的局部直方图。通过对各个块的直方图进行分析和处理&#xff0c;该算法能够更好地适应图像中不同区域的…

软件测评在项目中的作用

软件测评在项目中的作用至关重要&#xff0c;主要体现在以下几个方面&#xff1a; 确保软件质量&#xff1a;软件测评是确保软件质量的关键环节。通过对软件的功能、性能、安全性等方面进行全面测试&#xff0c;可以发现软件中的缺陷、错误或不符合需求的地方&#xff0c;从而…

使用OpenVINO™.CSharp.API.Extensions.PaddleOCR NuGet Package快速实现OCR文本识别

PP-OCR是PaddleOCR自研的实用的超轻量OCR系统&#xff0c;可以实现端到端的图像文本检测。为了在C#平台实现使用OpenVINO™部署PP-OCR模型实现文本识别&#xff0c;让更多开发者快速上手PP-OCR项目&#xff0c;基于此&#xff0c;封装了OpenVINO.CSharp.API.Extensions.PaddleO…

selenium环境安装和web自动化基础

webUI自动化背景 因为web页面经常会变化&#xff0c;所以UI自动化测试的维护成本很高。不如接口的适用面广&#xff0c;所以大部分公司会做接口自动化测试&#xff0c;但是未必会做UI自动化测试&#xff1b; UI自动化测试要做也是覆盖冒烟测试&#xff0c;不会到很高的覆盖率&a…