简述

有什么用?

​ 通过hook全局符号表实现各种黑科技功能,比如我们可以hook open,write和read监控文件的IO读写,hook malloc,calloc,realloc 和 free统计分配了多少内存,内存是否被泄露,也可以对其他进程进行hook实现各种 黑科技功能(root),这种hook方式比较简单,只需更改表中符号地址即可,但只能hook导入函数。

ELF

​ ELF是一种用于二进制文件、可执行文件、目标代码、共享库和核心转储格式文件。

具体实现

1. 获取模块基址

​ Elf加载的地址是随机的我们只有在elf加载后才能获取到他的基址,下面有两种方式获取

通用:

​ 我们可以读取 /proc/self/maps,对其进行解析,下面是maps文件的格式

 address           perms offset  dev   inode       pathname00400000-00452000 r-xp 00000000 08:02 173521      /usr/bin/dbus-daemon00651000-00652000 r--p 00051000 08:02 173521      /usr/bin/dbus-daemon00652000-00655000 rw-p 00052000 08:02 173521      /usr/bin/dbus-daemon00e03000-00e24000 rw-p 00000000 00:00 0           [heap]00e24000-011f7000 rw-p 00000000 00:00 0           [heap]...
Android 5.0 +:

​ 通过翻阅 Linux 资料我们找到了 dl_iterate_phdr 函数

static int callback(struct dl_phdr_info *info, size_t size, void *data)
{..auto *pInfo = new struct dl_phdr_info(*info);if (strstr(pInfo->dlpi_name, "模块名")) {// pInfo->dlpi_addr便是我们的基地址..}
}extern "C" JNIEXPORT jstring JNICALL
Java_com_example1_gothook_MainActivity_stringFromJNI(JNIEnv *env,jobject /* this */) {...dl_iterate_phdr(&callback, nullptr);...
}

2. 获取Program_header_table

// dl_iterate_phdr
Elf32_Phdr *phdr = &(pInfo->dlpi_phdr[i]);//通用,读取Elf_Ehdrtypedef struct{unsigned char e_ident[EI_NIDENT]; Elf32_Half e_type;    //文件的类型Elf32_Half e_machine; //体系结构Elf32_Word e_version; //文件的版本Elf32_Addr e_entry;     //入口地址Elf32_Off e_phoff;    //Program header tableElf32_Off e_shoff;    //Section header tableElf32_Word e_flags;Elf32_Half e_ehsize;Elf32_Half e_phentsize;Elf32_Half e_phnum;Elf32_Half e_shentsize;Elf32_Half e_shnum;Elf32_Half e_shstrndx;
} Elf32_Ehdr;Elf_Ehdr *ehdr = (Elf_Ehdr *) base;
Elf32_Phdr *phdr = (Elf32_Phdr *)ehdr->e_phoff + base

3.获取DT_STRTAB,DT_JMPREL,DT_SYMTAB

我们对Program_header_table进行遍历获取 PT_DYNAMIC

通过 p_vaddr 获取Elf_Dyn

JMPREL

ELFStringTable

ELFSymolTable

for (int i = 0; i < pInfo->dlpi_phnum; ++i) {__u8 *str_table = nullptr;Elf_Rela *jmprel = nullptr;Elf_Sym *sym_table = nullptr;if (phdr->p_type == PT_DYNAMIC) {auto *dyn = (Elf_Dyn *) (phdr->p_vaddr + pInfo->dlpi_addr);int i1 = 1;while (dyn->d_tag) {if (dyn->d_tag == DT_STRTAB) { //是否DT_STRTABstr_table = (__u8 *) (dyn->d_un.d_ptr + pInfo->dlpi_addr);}if (dyn->d_tag == DT_JMPREL) {  //是否DT_JMPRELjmprel = (Elf_Rela *) (dyn->d_un.d_ptr + pInfo->dlpi_addr);}if (dyn->d_tag == DT_SYMTAB) { //是否DT_SYMTABsym_table = (Elf_Sym *) (dyn->d_un.d_ptr + pInfo->dlpi_addr);}dyn = reinterpret_cast<Elf_Dyn *>(phdr->p_vaddr + pInfo->dlpi_addr +sizeof(Elf_Dyn) * i1++);}...}
}

4.进行Hook

查看strstr函数原型我们自己实现了一个用来替换的函数,每次调用strstr都会到我们自己的函数这里打印日志

Hook代码

if (jmprel && str_table && sym_table) {for (int j = 0; jmprel->r_info; ++j) { //遍历jmprelElfW(Word) sym = ELFW(R_SYM)(jmprel[j].r_info); //取符号下标char *name = (char *) (sym_table[sym].st_name + str_table); //从sym_table获取st_name在str_table的偏移if (strstr(name, "strstr")) { //需要hook的函数void *i2 = (void *) (jmprel[j].r_offset + pInfo->dlpi_addr); ElfW(Addr) page_start = PAGE_START(jmprel[j].r_offset + pInfo->dlpi_addr);mprotect((ElfW(Addr) *) page_start, PAGE_SIZE, PROT_WRITE | PROT_READ);//使用mprotect解除内存访问权限 https://man7.org/linux/man-pages/man2/mprotect.2.html*((ElfW(Addr) *) i2) = (ElfW(Addr)) myStrstr + jmprel[i].r_addend;//修改got表地址mprotect((ElfW(Addr) *) page_start, PAGE_SIZE, PROT_READ);//还原内存访问权限break;}}

​ 宏定义如下

#define PAGE_SIZE 4096
#define PAGE_START(a) ((a) & ~(PAGE_SIZE-1))
#if defined(__LP64__)
#define ELFW(what) ELF64_ ## what#define Elf_Dyn Elf64_Dyn
#define Elf_Sym Elf64_Sym
#define Elf_Rela Elf64_Rela
#else
#define ELFW(what) ELF32_ ## what
#define Elf_Dyn Elf32_Dyn
#define Elf_Sym Elf32_Sym
#define Elf_Rela Elf32_Rela#endif#define ELF32_R_SYM(x) ((x) >> 8)
#define ELF32_R_TYPE(x) ((x) & 0xff)
#define ELF64_R_SYM(i) ((i) >> 32)
#define ELF64_R_TYPE(i) ((i) & 0xffffffff)

5.大功告成

我们每次调用strstr都会打印出两个的参数

extern "C" JNIEXPORT jstring JNICALL
Java_com_example1_gothook_MainActivity_stringFromJNI(JNIEnv *env,jobject /* this */) {dl_iterate_phdr(&callback, nullptr);strstr("test1", "test2"); //调用strstrreturn env->NewStringUTF(hello.c_str());
}hook_MainActivity_stringFromJNI(JNIEnv *env,jobject /* this */) {dl_iterate_phdr(&callback, nullptr);strstr("test1", "test2"); //调用strstrreturn env->NewStringUTF(hello.c_str());
}

代码下载:https://github.com/Mrack/GotHook
关注我的技术公众号
不定期分析各种技术文章

GOT Hook的简单实现与原理相关推荐

  1. JS函数简单的底层原理 -变量重复声明无效,隐式申明,变量提升,函数提升,以及堆栈内存的变化

    JS函数简单的底层原理 (个人理解): 1. 已经使用var申明且赋值,若再次申明,则第二次申明(不赋值)无效. 2.在同一个作用域下,只要是发生了同名,且变量完成赋值,后者会覆盖前者.存在两个相同的 ...

  2. [EDA] 2.2 简单PLD结构原理-潘松版

    2.2 简单PLD结构原理 知识点: 2.1 PLD概述 名称概念: PLD:Programmable Logic Device,可编程器件 PLD的分类:1.按集成度分,可分为简单PLD和复杂PLD ...

  3. pureMVC简单示例及其原理讲解四(Controller层)

    本节将讲述pureMVC示例中的Controller层. Controller层有以下文件组成: AddUserCommand.as DeleteUserCommand.as ModelPrepCom ...

  4. Unity优化——简单AOI实现原理

    声明:本文为个人笔记,用于学习研究使用非商用,内容为个人研究及综合整理所得,若有违规,请联系,违规必改. Unity网络--简单AOI实现原理 文章目录 Unity网络--简单AOI实现原理 一.开发 ...

  5. android hook技术教学视频,[科普向]hook技术简单介绍

    首先 1.  这只是科普向,会介绍相关Hook技术及原理,但是不会给源码.源码请自行百度 2.请至少有一点Windows编程经验,知道系统API是什么...以免看科普内容给您带来不适 3.这里结合了一 ...

  6. API HOOK 金山词霸取词功能原理

    本文由本人整理 1 屏幕抓词     屏幕抓词(或者叫动态翻译)是指随着鼠标的移动,软件能够随时获知屏幕上鼠标位置的单词或汉字,并翻译出来提示用户.它对於上网浏览.在线阅读外文文章等很有帮助作用,因此 ...

  7. promise是什么?简单分析promise原理

    预备知识 回调函数 高级函数 发布-订阅模式 promise A+ 规范 promise是什么,能干什么 Promise是异步编程的一种解决方案,它可以解决异步回调地狱的问题,防止层层嵌套对程序代码带 ...

  8. 线程的3种实现方式并深入源码简单分析实现原理

    前言 本文介绍下线程的3种实现方式并深入源码简单的阐述下原理 三种实现方式 Thread Runnable Callable&Future 深入源码简单刨析 Thread Thread类实现了 ...

  9. html轮播图原理,30_用js实现一个轮播图效果,简单说下原理

    一.原理 将一些图片在一行中平铺,然后计算偏移量再利用定时器实现定时轮播. 步骤一:建立html基本布局 如下所示: 轮播图 1 2 3 4 5 < > 只有五张图片,却使用7张来轮播,这 ...

最新文章

  1. 小朋友你是否有很多问号?疫情期间不打游戏却在背ABC,百度翻译日活同比增长40%...
  2. wxWidgets:滚动Scrolling
  3. ImageLoader设置圆形图片
  4. java两个字符串前缀_java – 找到两个字符串的最长公共前缀
  5. 传统的6d位姿估计fangfa1_李飞飞团队最新论文:基于anchor关键点的类别级物体6D位姿跟踪...
  6. flex gallery / 产品展示
  7. Macaca基础原理解析
  8. mysql 存储时间 时间戳_具体场景下MySQL中用“时间戳”存储时间的问题
  9. JavaScript:split() 方法和join() 方法
  10. 安装java虚拟机_JAVA虚拟机的安装以及JAVA的环境配置
  11. python|cookie和session介绍——以12306验证码破解
  12. 关于CUDA,cuDNN,TF,CUDA驱动版本兼容问题
  13. 抽签助手|抽签助手2.8绿色免费版下载
  14. mac系统添加VSCode到右键菜单
  15. dataframe动态命名(读取不同文件并规律命名)
  16. win10安装红警运行出现FATALString Manager failed to initilaized properly
  17. excel离散度图表怎么算_excel离散数据表格-Excel 离散程度分析图表如何做
  18. “background-image:url(data:image”data类型的Url格式简介
  19. 【电商网站】将商品加入购物车代码
  20. 2022起重机司机(限桥式起重机)理论题库及答案

热门文章

  1. 如何通过设计验证让SoC芯片流片成功
  2. 北大王选所数据管理研究室成功举办学术交流年会
  3. 分布式数据库技术论坛回顾
  4. 【报告分享】2021年中国高端汽车出行生态趋势洞察报告-腾讯新闻上汽奥迪(附下载)
  5. css图片位置改变过度效果_CSS位置:绝对的,过度使用的
  6. 2020年Delphi25周年庆FireMonkey25个免费样本源码
  7. A标签下载文件 IE浏览器
  8. 外贸供应链管理解决方案丨汇信外贸软件
  9. 亚当斯分区曝光法俗解之三
  10. webpack打包优化(polyfill/HappyPack/dllPlugin)