【Android 逆向】函数拦截 ( 修改内存页属性 | x86 架构插桩拦截 )

举报
韩曙亮 发表于 2022/01/11 01:54:22 2022/01/11
【摘要】 文章目录 一、修改内存页属性二、x86 架构下的插桩拦截 一、修改内存页属性 实际函数 的 函数指针为 unsigned char* pFunc , 拦截函数 的函...





一、修改内存页属性



实际函数 的 函数指针为 unsigned char* pFunc , 拦截函数 的函数指针为 unsigned char* pStub , 在执行 pFunc 函数时 , 无条件跳转到 pStub 函数中 ;


要修改 pFunc 函数 , 要先设置该函数所在的内存页的访问 属性 , 否则如果用户没有相关内存访问权限 , 强行修改会报错 ;

首先 , 获取 pFunc 函数 所在内存页地址 , 每个内存页 4KB ;

	/* 获取 pFunc 函数入口 , 先获取该函数所在内存页地址 */
	void* pBase = (void*)(0xFFFFF000 & (int)pFunc);

  
 
  • 1
  • 2

然后 , 修改内存页属性 , 修改为 可读 | 可写 | 可执行 , 避免因为内存访问权限问题导致操作失败 ; mprotect 函数只能对整个页内存的属性进行修改 , 每个 内存页 大小都是 4KB ;

	/* 修改整个内存页属性 , 修改为 可读 | 可写 | 可执行 , 
	 * 避免因为内存访问权限问题导致操作失败
	 * mprotect 函数只能对整个页内存的属性进行修改 
	 * 每个 内存页 大小都是 4KB 
	 */
	int ret = mprotect(pBase, 0x1000, PROT_WRITE | PROT_READ | PROT_EXEC);

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6




二、x86 架构下的插桩拦截



插桩拦截 时 , 在 实际函数 入口处写入的 跳转代码 就是 汇编中的 跳转指令 ;

跳转指令 可以理解为 " 指令 " 或 " 机器码 " , 指令是人看到的 汇编指令 , 机器码是给 CPU 执行的 二进制机器码 ; 二者是等效的 ;


x86 架构下的跳转指令 : 下面的二进制数都是十六进制数 ; 32 32 32 位指令 ;

E9 00 00 00 00 , JMP target ;

JMP 是强制跳转指令 , E9 是对应的机器码 ;


首先 , 准备跳转指令 ,

	/* E9 是 JMP 无条件跳转指令 , 后面 4 字节是跳转的地址 */
	unsigned char code[] = { 0xE9,0,0,0,0 };

  
 
  • 1
  • 2

然后 , 计算 pStub 函数跳转地址 , 目标函数 pStub 地址 - 当前函数 pFunc 地址 - 5 , x86 架构中 , 跳转指令 跳转的是 偏移量 , 不是绝对地址值 ;

	/* 计算 pStub 函数跳转地址 , 目标函数 pStub 地址 - 当前函数 pFunc 地址 - 5 
	 * 跳转指令 跳转的是 偏移量 , 不是绝对地址值
	 */
	*(unsigned*)(code + 1) = pStub - pFunc - 5;

  
 
  • 1
  • 2
  • 3
  • 4

最后 , 将跳转代码拷贝到 pFunc 地址处 , 这是 pFunc 函数的入口地址 ;

	/* 将跳转代码拷贝到 pFunc 地址处 , 这是 pFunc 函数的入口地址 */
	memcpy(pFunc, code, sizeof(code));

  
 
  • 1
  • 2

文章来源: hanshuliang.blog.csdn.net,作者:韩曙亮,版权归原作者所有,如需转载,请联系作者。

原文链接:hanshuliang.blog.csdn.net/article/details/121236962

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。