首页 > 其他分享 >hook初识之inline hook

hook初识之inline hook

时间:2024-04-19 14:22:46浏览次数:25  
标签:fun1 int jmp hook 地址 初识 fun inline

文章首发阿里云先知社区:https://xz.aliyun.com/t/14033

什么是 hook

hook 翻译过来就是钩子,它用于拦截并改变某个事件或操作的行为,比如我们大家在写 shellcode loader 时,直接使用申请内存,copy 内存等高危操作可能会报毒,然后尝试更换冷门的 api 或者直接使用内核函数时,成功绕过杀软,这个时候可能就是因为杀软 hook 了高危 api 但是没有 hook 一些冷门 api 导致的。

inline hook

inline hook 只是众多 hook 方式中的一种,它用到的是 jmp 指令,我们接下来用一个小 demo 来学习一下 inline hook。

demo

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

extern"C" __declspec(dllexport) void fun() {
    while (1) {
        Sleep(1000);
        printf("hello world\n");
    }
}

int main()
{
    fun();
}

我们先随便设个断点,然后在调试,查看反汇编:
image.png
可以看到调用 fun 函数的时候 call 07FF778971280h,我们跟到这个地址再去看看
image.png
发现这个地址相邻都有很多 jmp 指令,jmp 的目的地就是各个函数,我们去 07FF778971920h 看一下:
image.png
可以发现 07FF778971920h就是真正的 fun 的地址。
那么我们到这里就对一个调用流程有了一个基本的认知了,调用时首先 call 一下,在 call 的地方会有一个 jmp 指令等着你去跳转到真正的 fun 函数处。
那么我们办法修改 jmp 指令的地址,使其跳转到我们想要跳转的函数,不就实现了一个 hook 吗,我们可以在 x64dbg 中简单的验证一下想法:
image.png
符号处找到 main 函数
image.png
直接双击上图红框处
image.png
可以看到那一堆 jmp 指令处了,我们直接修改一下看看会发生什么
image.png
直接会发生异常,因为这块内存好像还是 fun 函数内部的东西,所以异常是正常的
image.png
image.png
我们修改一下源代码,增加一个 fun1 函数,方便我们修改 jmp 地址:

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

extern"C" __declspec(dllexport) void fun() {
	while (1) {
		Sleep(1000);
		printf("hello world\n");
	}
}
extern"C" __declspec(dllexport) void fun1() {
	MessageBox(0, 0, 0, 0);
}

int main()
{
	fun();
}

我们直接进行修改:
image.png
注意到上图代码和注释不一样,我们来运行一下
image.png
弹出来 messagebox,所以可以证明 hook 成功,接下来我们要做的事情就是将上述流程用代码来实现。

代码实现上述 demo

代码实现的难点是确定修改的字节,我们可以先分析一下 jmp 处的详情:

00007FF6996412E9 | E9 12060000 | jmp <hook.fun> |
00007FF6996412EE | E9 8D3D0000 | jmp <hook.__scrt_is_managed_app> |
00007FF6996412F3 | E9 58420000 | jmp <hook.__castguard_set_user_handler> |

E9 是 jmp,然后就是一个地址了,并且我们可以发现 <hook.fun> 的地址并不是 AB060000,其他两个例子同理,这两个数是怎么算出来的呢?
第一个数是硬编码,第二个数是 <hook.fun> 的地址,他们之间有以下规则:

硬编码 = 要跳转的地址 - 指令完成的下一条地址

我们用上述 fun 的例子验证一下,先看一下参数:
image.png
硬编码 = 00007FF699641900-00007FF6996412EE = 612
由于计算机是小端格式存储,所以说是 E9 12060000。
由于指令的长度是 5,所以公式也可以表示为:

硬编码 = 要跳转的地址 - (当前指令地址 + 5)

接下来就是代码实现了:
我们先来明确一下我们的目标,通过一个 hook 函数,让我们在调用 fun 函数时,调用 fun1 函数。
所以我们先需要获取 fun 和 fun1 函数的地址:
image.png
这里的地址其实就是上面那堆 jmp 处的地址,所以我们只需要在这个地址的基础上修改内存硬编码即可。
我们先将地址强转为 char*类型,这样单位是一个字节,所以chfunaddr + 1就把 E9 跳过去了,直接来到了硬编码的地方,方便我们修改
image.png
接下来套用上面的公式计算出硬编码
image.png
但是注意我们此时还不能直接修改内存,因为我们的程序都在.text 端,内存属性是只读的,所以我们需要修改内存属性,然后再修改内存即可
image.png
这样我们就完成了一次 hook ,看效果:
image.png
并没有调用 fun,而是调用了 fun1,我们目前的代码如下 :

// hook.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

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

extern"C" __declspec(dllexport) void fun()
{
	while (true)
	{
		Sleep(1000);
		printf("Hello World!\n");
	}
}

void fun1() {
	MessageBox(0, 0, 0, 0);
}

auto funaddr = fun;
auto fun1addr = fun1;

void hook() {

	char* chfunaddr = (char*)funaddr;
	int* hardaddr = (int*)(chfunaddr + 1);
	
	//计算fun1的硬编码
	int newhard = (int)fun1addr - (int)(chfunaddr + 5);

	DWORD oldprotect;
	VirtualProtect(hardaddr, 0x100, PAGE_EXECUTE_READWRITE, &oldprotect);
	hardaddr[0] = newhard;

}

int main()
{
	hook();
	fun();
}

但是到这里还没有完善 hook,因为 hook 还有一个事情要做那就是还原,不仅先调用了 fun1,还要再调用 fun,不能让用户察觉到异常,所以我们接下来继续完善代码:
我们需要申请一段内存空间,用来存储修改之前的指令,然后在 hook 操作结束之后直接执行即可
我们在修改内存的时候提前保存一下原来的硬编码
image.png
在执行 fun1 的时候先 unhook 一下,恢复 funadd r原来的值,再直接调用即可
image.png
完整的代码如下:

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

extern"C" __declspec(dllexport) void fun()
{
	while (true)
	{
		Sleep(1000);
		printf("Hello World!\n");
	}
}
void fun1();

auto funaddr = fun;
int oldAddrHard = 0;
auto fun1addr = fun1;

void fun1() {
	memcpy(((char*)funaddr + 1), &oldAddrHard, 4);

	MessageBox(0, 0, 0, 0);
	funaddr();
}

void hook() {

	char* chfunaddr = (char*)funaddr;
	int* hardaddr = (int*)(chfunaddr + 1);

	//计算fun1的硬编码
	int newhard = (int)fun1addr - (int)(chfunaddr + 5);

	oldAddrHard = hardaddr[0];
    
	DWORD oldprotect;
	VirtualProtect(hardaddr, 0x100, PAGE_EXECUTE_READWRITE, &oldprotect);
	hardaddr[0] = newhard;

}

int main()
{
	hook();
	fun();
}

这样我们就实现了调用完 fun1 再调用 fun 的 hook。

标签:fun1,int,jmp,hook,地址,初识,fun,inline
From: https://www.cnblogs.com/fdxsec/p/18133962

相关文章

  • 详解Hook框架frida,让你在逆向工作中效率成倍提升
    https://zhuanlan.zhihu.com/p/41662447一、frida简介frida是一款基于python+javascript的hook框架,可运行在androidioslinuxwinosx等各平台,主要使用动态二进制插桩技术。本期“安仔课堂”,ISEC实验室的彭老师为大家详解frida,认真读完这篇文章会让你在逆向工作中效率成倍提升哦......
  • vue2 mixin 和 vue3 hook
    mixin1.逻辑函数的复用2vue组件中的选项式API(例如:data,computed,watch)或者组件的生命周期钩子(created、mounted、destroyed)使用方法mixins:[mixins],//注册mixin,这样mixin中所有的钩子函数等同于组件中钩子1mixin中的生命周期函数会和组件的生命周期函数一起合并执行。2......
  • dbt-checkpoint 确保dbt 项目质量的pre-commit hooks 工具
    dbt-checkpoint实际上属于pre-commithooksplugin实现了不少hooks可以用来提升dbt项目的模型质量内部处理上实际是对于dbt的元数据进行解析,当然dbt-checkpoint也提供了不少其他扩展目前包含的hooks只大概说明下,详细的后边介绍下,目前涉及了,model,source,script,macro,modifier......
  • pre-commit 多语言pre-commit hooks 框架
    pre-commit多语言pre-commithooks框架基于python开发,功能很强大参考使用安装pipinstallpre-commit添加配置.pre-commit-config.yamlrepos:-repo:https://github.com/pre-commit/pre-commit-hooksrev:v2.3.0hoo......
  • 《Evading EDR》— FUNCTION-HOOKING_DLLS
    最近一直在做EDR相关的工作,虽然略有了解EDR的机制,但是并未深究其完整的工作框架和可能的绕过机制,借工作空闲时间依靠智谱清言阅读一下《EvadingEDRTheDefinitiveGuidetoDefeatingEndpointDetectionSystems》一书。在众多现代端点安全产品的组件中,最常部署的是负责函数......
  • gitee基于webhooks实现前端简单自动化部署
    1.为什么采用自动化部署简而言之,程序员优秀传统:懒=>高级生产力.基于gitee进行的自动化部署,服务器环境为Ubuntu基于webhooks进行的自动化部署更加轻快便捷2.部署步骤1).服务器购买可以购买阿里云抢占式服务器进行实验,花费应该在一大洋以内,或者直接购买一年低配服务......
  • c++ inline
    当在头文件中定义函数时,如果这个头文件被多个.cpp文件包含,那么每个包含该头文件的.cpp文件都会有一个该函数的副本。这在链接阶段会引起“多重定义”的错误,因为链接器找到多个相同符号的定义。使用inline关键字可以解决这个问题。当一个函数被声明为inline,编译器会尝试将......
  • 初识-python因果推断
    初识-DoWhyDoWhy是一个用于因果推理的Python库,支持因果假设的显式建模和测试。DoWhy基于因果推理的统一语言,结合了因果图形模型和潜在结果框架。DoWhy-Github简介和主要特点决策涉及了解不同变量如何相互影响,并预测其中一些变量更改为新值时的结果。例如,给定一个结果变......
  • github-webhook+docker实现项目可持续自动化部署
    目录一、项目手动部署二、项目自动部署自动构建部署流程docker概念补充使用nginx+pm2+github-webhook+docker实现项目自动部署注:docker也能实现pm2的守护进程功能(持续启动项目),所以使用了docker就不需要使用pm2了但是需要注意的是使用node启动的webhook服务器不......
  • 一个使用HOOK/WH_GETMESSAGE解决软件交互问题的案例
    一、问题背景:1、某设计软件AD,可以打开/编辑二维电路设计界面,其交互方式如下:(1)鼠标右键按下拖动(2)鼠标滚轮上下移动(3)鼠标滚轮按下+鼠标移动缩放(4)ctrl+鼠标滚轮缩放   该软件的交互方式可以通过软件设置修改,但是基本的使用习惯就是如此,用户的一个场景是通过每台机器msts......