微软detours代码借鉴点备注

comeasy

借鉴点1 Loadlibray的时间选择

注入库wrotei.dll,为了获取istream的接口,需要loadlibrary,但是在dllmain中是不建议这样做的。因此,动态库在dllmain的时候直接挂载了comeasy.exe的入口

//获取入口

TrueEntryPoint = (int (WINAPI *)(VOID))DetourGetEntryPoint(NULL);

...

//挂载入口

DetourAttach(&(PVOID&)TrueEntryPoint, TimedEntryPoint);

从加载顺序上看

红色箭头指向的wrotei64.dll在ole32.dll之前就已经启动了,而要挂载的函数在ole32.dll里,因此在不调用的loadlibary的情况挂载这些函数可以挂载exe的entrypoint,在exe加载完毕所有dll后运行entrypoint时再调用钩子函数进行ole32函数的挂载。

借鉴点2挂载虚函数

获取istream直接挂载指定的虚函数,直接对虚函数进行挂载,而不是挂载CreateInstance等函数返回一个对象。

CreateStreamOnHGlobal(NULL, TRUE, &pStream);

...
DetourAttach(&(PVOID&)RealIStreamWrite, MineIStreamWrite);

注意MineIStreamWrite的第一个参数是IStream *this。这是因为this是c++方法的第一个默认对象。

commem

借鉴点:虚函数挂载

一个标准的com虚函数挂载样例,演示了虚函数直接调用的方式,充分说明了虚函数的第一个参数this的使用。

Disas

借鉴点:指令拷贝

每个机器指令都有自己的长度,本用例演示了如何从指定的位置拷贝一个完整的指令。

主要使用了

DetourCodeFromPointer和DetourCopyInstruction

Dtest

演示了hook 0个参数1个参数到多个参数,可变参数的hook方法,同时演示了多个detours hook同一个函数时的调用效果

Dumpe

借鉴点:导出表遍历

使用detour函数遍历DLL的导出表,并给出导出函数的序号,位置(RVA),名称。

主要演示了导出表遍历的回调处理。

Dumpi

借鉴点:导入表遍历

使用detour函数遍历exe的导入表,并给出导入函数的模块和名称。

主要演示了导入表遍历的回调处理。

dynamic_alloc

借鉴点,动态分配内存并拷贝代码作为detour运行。

注意该函数还不完整,因为没有调用trampoline。

detours前

// return a non-nullptr value.
void *target_function() {
00007FF6A50511E0  sub         rsp,28h  std::cout << '+' << __FUNCTION__ << std::endl;
00007FF6A50511E4  mov         dl,2Bh  
00007FF6A50511E6  lea         rcx,[std::cout (07FF6A50A1640h)]  
00007FF6A50511ED  call        std::operator<<<std::char_traits<char> > (07FF6A5051D50h)  
00007FF6A50511F2  lea         rdx,[__xt_z+8h (07FF6A508A420h)]  
00007FF6A50511F9  mov         rcx,rax  
00007FF6A50511FC  call        std::operator<<<std::char_traits<char> > (07FF6A50520C0h)  
00007FF6A5051201  lea         rdx,[std::endl<char,std::char_traits<char> > (07FF6A5053330h)]  
00007FF6A5051208  mov         rcx,rax  
00007FF6A505120B  call        std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF6A5054E70h)  return nullptr;
00007FF6A5051210  xor         eax,eax  
}
00007FF6A5051212  add         rsp,28h  
00007FF6A5051216  ret  

准备的地址,00007FF66504FFF0,如下

00007FF66504FFEE  nop  
00007FF66504FFEF  ret  
00007FF66504FFF0  nop  
00007FF66504FFF1  nop  
00007FF66504FFF2  mov         rax,0DEADBEEF00000000h  
00007FF66504FFFC  nop  
00007FF66504FFFD  ret  

detours之后

void *target_function() {
00007FF6A50511E0  jmp         00007FF665030178  std::cout << '+' << __FUNCTION__ << std::endl;
00007FF6A50511E5  int         3  
00007FF6A50511E6  lea         rcx,[std::cout (07FF6A50A1640h)]  
00007FF6A50511ED  call        std::operator<<<std::char_traits<char> > (07FF6A5051D50h)  
00007FF6A50511F2  lea         rdx,[__xt_z+8h (07FF6A508A420h)]  
00007FF6A50511F9  mov         rcx,rax  
00007FF6A50511FC  call        std::operator<<<std::char_traits<char> > (07FF6A50520C0h)  
00007FF6A5051201  lea         rdx,[std::endl<char,std::char_traits<char> > (07FF6A5053330h)]  
00007FF6A5051208  mov         rcx,rax  
00007FF6A505120B  call        std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF6A5054E70h)  return nullptr;
00007FF6A5051210  xor         eax,eax  
}
00007FF6A5051212  add         rsp,28h  
00007FF6A5051216  ret  
00007FF665030178  jmp         qword ptr [7FF665030170h]

最终跳转到00007FF66504FFF0,得到一个非空的返回值,输出如下

1. target_function() without Detour+target_function
0000000000000000
detour: 00007FF6A50511E0 --> 00007FF66504FFF0 (trampoline: 00007FF665030120 )
2. target_function() with Detour
DEADBEEF00000000
3. target_function() without Detour
+target_function
0000000000000000

虽然有tranmpoline但是没调用,因为detours函数没有调用trampoline。

echo

借鉴点:挂接exe的导出表

有意思的是exe导出了echo,而注入dll,依赖exe以及其导出函数echo。

einst

借鉴点:动态库特征查找

通过插入.detours段,并在里面放置guid,然后遍历所有dll,并在dll里查找.detours段,遍历里面的section,查找数据结构中的guid。

execp

借鉴点:异常捕获的detours处理

获取异常处理函数KiUserExceptionDispatcher,NtContinue。

对KiUserExceptionDispatcher进行hook。该hook是一个通用的处理,用户可以自己设置自己的异常处理函数,而且仅关注业务 就可以了。 在真正的hook处理Detour_KiUserExceptionDispatcher中,需要进行一些异常的处理,然后调用用户自己的异常处理函数,Detour_KiUserExceptionDispatcher根据用户的返回值决定继续还是调用下一个,或是交给调试器。

借鉴点:异常的三种处理方法

程序开始申请了一个可写内存,写入数据,然后将该内存设置为只读。随后顺序调用了safe和raw两个方法,这两个方法会调用BadCode方法,该方法会做两个赋值,位置一个正确但是只读,一个是错误的内存,两处都会触发异常。异常会进入KiUserExceptionDispatcher,由于已经HOOK,因此会进入Detour_KiUserExceptionDispatcher中。在该函数中会调用自己编写的MyVirtualFaultFilter异常处理,MyVirtualFaultFilter会根据异常的类型“访问被拒绝”,以及根据指针是否我们要访问的只读的指针,如果是则将只读的变量值修改为可写,返回continue标志,如果不是则返回查找下一个异常处理函数。如果是要访问的地址,则Detour_KiUserExceptionDispatcher根据continue标志会调用NtContinue继续处理。如果不是要访问的地址,则Detour_KiUserExceptionDispatcher会查找下一个异常处理函数,在safe函数调用中由于包含try catch,会自行正常处理并继续。在raw函数中不包含try catch,程序会异常退出。如果是调试模式则该异常会再次传递给调试器。

注意,NtContinue 是一个系统级调用,它用于在 Windows 内核模式下恢复线程的执行。这个调用通常与异常处理和上下文切换相关。当 NtContinue 被调用时,它实际上是在修改当前线程的上下文,以便线程可以从之前保存的某个点继续执行。以下是exception处理函数CONTEXT参数的内容

NtContinue 不需要返回,因为它实际上是在改变线程的执行流程,而不是像常规函数调用那样执行一些操作然后返回到调用者。当 NtContinue 被调用时,它使用提供的上下文信息来恢复线程的状态,并导致线程从该状态继续执行。这通常意味着线程将从之前保存的某个指令地址开始执行,而不是从 NtContinue 调用之后的点继续。

因此,从调用者的角度来看,NtContinue 之后的代码可能永远不会被执行,因为线程的执行流程已经被改变。这就是为什么 NtContinue 不需要(也不会)返回到调用它的代码位置的原因。实际上,如果 NtContinue 调用成功,那么线程将继续执行,就好像它从未停止过一样,只是现在的状态可能与之前有所不同。

需要注意的是,直接调用或依赖于 NtContinue 这样的低级系统调用通常是不安全的,并且可能破坏系统的稳定性。这些调用通常只在操作系统内核、驱动程序或非常底层的系统级软件中使用。在应用程序级别的代码中直接使用这些调用是不推荐的,除非你对系统的内部工作原理有深入的了解,并且知道你在做什么。

借鉴点:自己处理堆栈

一般情况下不需要用户处理堆栈,但是由于此处的处理特殊性,使用了__declspec(naked)修饰符来自己处理堆栈。因此函数在开始处自己维护堆栈信息。

findfunc

借鉴点:未导出函数的hook

未导出的函数可通过加载符号表的方式找到函数指针然后再hook。

impmunge

借鉴点:隐藏导入库和导入函数

使用方法:

修改导入库和导入表

impmunge.exe /m /o:2.exe 1.exe

注意命令行最后是被修改的文件,顺序不能错。变换如下

  file    KERNEL32.dll                     mf_KERNEL32.dll
  symbol  CreateFileA                      ms_CreateFileA
  symbol  CloseHandle                      ms_CloseHandle

恢复导入表

impmunge.exe /r /o:2.exe 1.exe

member

借鉴点:使用相似类的成员直接Hook

要点:两个类没有成员,可以直接用。如果有成员变量,则需要相同的结构,一边在hook的成员函数中使用目标对象的成员变量。

类成员的指针

static void (CMyTest ::* Real_Target)(void);
这是一个静态成员函数指针,它指向CMyTest类的一个没有参数并且返回类型为void的成员函数。
由于它是静态的,所以你可以在没有CMyTest类的对象的情况下访问它,但你需要一个对象来通过它调用实际的成员函数(因为它是一个成员函数指针,不是指向静态成员函数的指针)。
语法可能看起来有点复杂,但基本上它定义了一个指针,该指针可以指向类CMyTest的任何非静态成员函数,该函数没有参数并返回void。
使用这种成员函数指针的一种常见情况是实现回调函数或策略模式,其中你可以在运行时改变对象的行为。
注意:虽然Real_Target是一个静态成员,但它指向的成员函数可以是非静态的。静态成员只是意味着你不需要类的对象来访问该静态成员本身(在这种情况下是成员函数指针),但你仍然需要一个对象来调用该静态成员所指向的非静态成员函数。

opengl

中规中矩的hook例子,演示如何hook opengl的函数

region待补充

setdll

将dll插入到其他二进制的导入表中,这样该二进制启动的时候会自动加载该dll

simple

中规中矩的hook例子,演示如何hook sleep,并再退出时给出sleep的总毫秒数。

>sleep5.exe
sleep5.exe: Starting.
sleep5.exe: Done sleeping.

>withdll.exe /d:simple64.dll sleep5.exe
withdll.exe: Starting: `sleep5.exe'
withdll.exe:   with `E:\OpenSource\Detours\bin.X64\simple64.dll'
simple64.dll: Starting.
simple64.dll: Detoured SleepEx().
sleep5.exe: Starting.
sleep5.exe: Done sleeping.
simple64.dll: Removed SleepEx() (result=0), slept 5016 ticks.

simple_safe

同simple,区别:

//  The difference between simple and simple_safe is that simple_safe
//  uses the C++ 14 overloads which help prevent mismatching types.
 

slept

中规中矩的hook例子,以上内容的借鉴点包含此例子的内容。

syelog

演示进程间日志记录和处理

syelogd.exe这个可执行文件通常用作一个系统事件日志守护进程(daemon)。它负责接收并记录由 Detours 拦截的 API 调用信息。这些信息对于了解系统行为、调试或分析应用程序非常有用。syelogd.exe 通常与 Detours 库的其他部分一起使用,以提供实时的 API 调用跟踪和日志记录功能。

traceapi

借鉴点:使用syelogd.exe输出日志

使用方式:启动syelogd.exe或syelogd.exe output.log或start syelogd.exe output.log将日志输出到屏幕或日志文件。

启动程序并注入监控dll,监控dll会将api的调用信息输出给syelogd.

withdll.exe /d:trcapi64.dll testapi.exe

trcbld 

借鉴点:跟踪进程启动,以及子进程,输出进程的命令行参数。

Runs the build commands and figures out which files have dependencies..

举例:

tracebld /o:tracenotepad  notepad.exe

启动notepad.exe,然后通过notepad.exe的打开对话框启动mspaint等程序。

最后退出这些程序,可以得到一个tracenotepad.xml文件,该文件记录了notepad CreateProcess,CloseProcess,DeviceIoControl的调用及其参数,通过这些信息可以分析程序的行为以及子进程。

tracelnk

演示枚举模块和各个模块的导入函数枚举

tracemem

跟踪heapalloc

tracereg、traceser、tracessl、tracetcp

标准的hook例子

tryman

c# managed hook例子

withdll

借鉴点:修改程序导入表,插入新的动态库

使用方法 withdll /d:extends.dll findfunc.exe

将extends.exe插入到findfunc.exe

API说明

DetourGetEntryPoint  得到主程序的入口,方法获取module的基地址,此处是PIMAGE_DOS_HEADER,根据这个信息查找PIMAGE_NT_HEADERS,从里面获取entrypoint的地址,一个例外是如果存在PDETOUR_CLR_HEADER,则获取模块MSCOREE.DLL,返回该dll的函数_CorExeMain。

DetourCodeFromPointer  调用了detour_skip_jmp,跳过几个jmp指令ff25,eb等
DetourCopyInstruction  从src拷贝完整的指令到目标位置

detour_find_jmp_bounds  根据给出的指令地址,找出一个可以放置detours tramplines的位置,该函数解析了目标函数的第一个指令,如果是相对跳转,则根据相对跳转的指令的位置,重新计算tramplines的位置。位置使用目标指令位置前后2GB的位置区间。

detour_alloc_trampoline_allocate_new 以目标地址和给定的区间申请一个地址。在区间中查找地址,并使用VirtualAlloc尝试在给定的位置申请空间。

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

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

相关文章

数据仓库面试总结

文章目录 1.什么是数据仓库&#xff1f;2.ETL是什么&#xff1f;3.数据仓库和数据库的区别&#xff08;OLTP和OLAP的区别&#xff09;4.数据仓库和数据集市的区别5.维度分析5.1 什么是维度&#xff1f;5.2什么是指标&#xff1f; 6.什么是数仓建模&#xff1f;7.事实表7.维度表…

SecureCRT通过私钥连接跳板机,再连接到目标服务器

文章目录 1. 配置第一个session&#xff08;跳板机&#xff09;2. 设置本地端口3. 设置全局firewall4. 配置第二个session&#xff08;目标服务器&#xff09; 服务器那边给了一个私钥&#xff0c;现在需要通过私钥连接跳板机&#xff0c;再连接到目标服务器上 &#x1f349; …

【C++】stack和queue

个人主页 &#xff1a; zxctscl 如有转载请先通知 文章目录 1. stack的介绍和使用1.1 stack的介绍1.2 stack的使用1.3 stack的模拟实现 2. queue的介绍和使用2.1 queue的介绍2.2 queue的使用2.3 queue的模拟实现 3. 容器适配器3.1 概念3.2 STL标准库中stack和queue的底层结构3.…

如何建立一个网页模版

创建一个网页模板涉及的主要步骤如下: 基本HTML结构模板创建: 创建HTML文件: 首先,你需要创建一个新的HTML文件,并在其中编写基本的HTML结构,例如: <!DOCTYPE html> <html lang="zh"> <head><meta charset="UTF-8"

VMware ESXi 6.7

1.浏览器中输入地址&#xff0c;进入管理界面 2.选择 存储 右击浏览&#xff0c;创建新的目录 3.点击 上载 &#xff0c;选择镜像文件 4.等待上载完成 5.点击 虚拟机-新建虚拟机 6.进入新建虚拟机界面 7.进入Windows安装界面 8.安装VMware Tools

python爬虫获取豆瓣前top250的标题(简单)

今天是简略的一篇&#xff0c;简单小实验 import requests from bs4 import BeautifulSoup# 模拟浏览器的构成&#xff08;请求头&#xff09; headers {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Ch…

使用CSS计数器,在目录名称前加上了序号,让目录看起来更加井然有序

目录&#xff08;Text of Contents缩写为TOC&#xff09;&#xff0c;其实就是一篇文章的概要或简述。这好比&#xff0c;去书店买书&#xff0c;先是被这本书的标题所吸引&#xff0c;而后我们才会&#xff0c;翻开这本书目录&#xff0c;看看这本书主要是在讲些什么&#xff…

Restful Web Service

Restful 1.特点 RESTful是一种架构风格&#xff0c;强调简单、轻量级和对资源的状态less操作。RESTful是通过HTTP协议进行通信的。RESTful的应用程序可以调用运行在不同服务器上的服务或函数。RESTful的接口通常使用JSON&#xff0c;但实际上它们都支持多种数据格式。RESTful…

【vue + springboot】切片+断点上传 + 秒传

需要了解透彻请参考&#xff1a;如何实现大文件上传、断点续传、切片上传_断点上传-CSDN博客 说明 切片&#xff1a;根据指定的大小对文件进行切块上传。 断点上传&#xff1a;每次上传完成一个切片后端保存信息&#xff0c;前端每次上传都判断所上传的文件是否存在&#xf…

纪念品分组

题源 贪心做法 &#xff0c;先排序再分组 题目描述 元旦快到了&#xff0c;校学生会让乐乐负责新年晚会的纪念品发放工作。为使得参加晚会的同学所获得 的纪念品价值相对均衡&#xff0c;他要把购来的纪念品根据价格进行分组&#xff0c;但每组最多只能包括两件纪念品&#xff…

1.9 面试经典150题 除自身以外数组的乘积

除自身以外数组的乘积 给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0…

vue如何搭建项目?

首先我们下载安装router&#xff0c;less / scss&#xff0c;pinia&#xff0c;axios&#xff0c; element / Ant Design Vue&#xff0c;Echarts 以及如何配置别名&#xff0c;自定义组件 npm npm create vitelatest yarn yarn create vite 然后安装依赖 成功后 在src下…

PyTorch搭建Informer实现长序列时间序列预测

目录 I. 前言II. InformerIII. 代码3.1 输入编码3.1.1 Token Embedding3.1.2 Positional Embedding3.1.3 Temporal Embedding 3.2 Encoder与Decoder IV. 实验 I. 前言 前面已经写了很多关于时间序列预测的文章&#xff1a; 深入理解PyTorch中LSTM的输入和输出&#xff08;从i…

python 笔记

文章目录 pdbpdb开始调试pythonpdb设置断点单步执行进入到函数的内部执行到下一个断点或程序结束调用栈查看命令查看当前函数调用堆栈向上一层函数查看调用堆栈查看源代码 importimport 用法 numpy导入numpy模块numpy常用函数np.argmaxnp.sum range生成连续序列生成不连续序列 …

离线数仓(十)【ADS 层开发】

前言 剩下的 ADS 层主要就是写 SQL 了&#xff0c;就像我们之前练习的 HQL 题一样&#xff0c;不同的是这里的数据从哪张表读取&#xff08;DWD 还是 ADS 甚至个别表需要从 DIM 层读取&#xff09;需要我们自己来分析。 ADS 的建表语句和 MySQL 是对应的&#xff0c;我们到时候…

从0到1实现RPC | 04 负载均衡和静态注册中心

一、Router的定义 Router路由用于预筛选&#xff0c;Dubbo有这样的设计&#xff0c;SpringCloud没有。 二、LoadBanlancer定义 负载均衡器&#xff1a;默认取第一个 当前支持随机和轮询两种负载均衡器。 随机&#xff1a;从所有provider中随机选择一个。 轮询&#xff1a;每…

【C++】引用与指针

​​ &#x1f331;博客主页&#xff1a;青竹雾色间. &#x1f618;博客制作不易欢迎各位&#x1f44d;点赞⭐收藏➕关注 ✨人生如寄&#xff0c;多忧何为 ✨ 目录标题 前言一.引用&#xff08;Reference&#xff09;二.指针&#xff08;Pointer&#xff09;三. 比较与总结 前…

面试题:Spring Boot Starter的功能与使用场景

Spring Boot Starter 是 Spring Boot 框架为了简化项目的初始化和配置工作而设计的一种模块化依赖管理方式。它主要具有以下几个关键功能和使用场景&#xff1a; 功能&#xff1a; 1. 依赖管理每个 Starter 都是一组相关的依赖项集合&#xff0c;这些依赖项都是为了实现特定功能…

机器学习第33周周报Airformer

文章目录 week33 AirFormer摘要Abstract一、论文的前置知识1. 多头注意力机制&#xff08;MSA&#xff09;2. 具有潜变量的变分模型 二、文献阅读1. 题目2. abstract3. 问题与模型阐述3.1 问题定义3.2 模型概述3.3 跨空间MSA&#xff08;DS-MSA&#xff09;3.4 时间相关MSA&…

【Qt 学习笔记】使用两种方式实现helloworld

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 使用两种方式实现helloworld 文章编号&#xff1a;Qt 学习笔记 / 05 …