PLT hook笔记
1. hook技术概述
hook技术是一种拦截用户函数调用的技术。通过hook技术可以实现统计用户对某些函数的调用次数,对函数注入新的功能的目标。在Linux平台,Hook技术可以分成用户和内核两个层面,每个类比中都存在不同的hook技术。本文主要介绍针对动态链接技术的PLT hook。
2. 代码实例
其次编写我们的main.c 该函数实现了将要替换strcmp函数的my_strcmp,和使hook生效的hook函数。代码的具体细节
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <inttypes.h>
#include <execinfo.h>
#include <sys/user.h>
#include <sys/mman.h>
#include "passwd.h" #define PAGE_SHIFT 12
#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1)) #define __AC(X,Y) (X##Y)
#define _AC(X,Y) __AC(X,Y) #define PAGE_START(addr) ((addr) & PAGE_MASK)
#define PAGE_END(addr) (PAGE_START(addr) + PAGE_SIZE) int my_strcmp(const char *s1, const char *s2)
{
return ;
} uintptr_t get_base_addr(char *libname)
{
FILE *fp;
char line[];
//char base_addr[1024];
uintptr_t base_addr = ; if (NULL == (fp = fopen("/proc/self/maps", "r"))) {
perror("open err");
return -;
} while (NULL != fgets(line, sizeof(line), fp)) {
if (NULL != strstr(line, libname)) {
sscanf(line, "%"PRIxPTR"-%*lx %*4s 00000000", &base_addr);
printf("line2:%s, base_addr:%"PRIxPTR"\n", line, base_addr);
break;
}
}
fclose(fp); return base_addr;
} void hook() {
uintptr_t base_addr;
uintptr_t addr;
//1. get the base addr of libpasswd.so
base_addr = get_base_addr("libpasswd");
if ( == base_addr) return;
addr = base_addr + 0x201020;
//2. add the write permisson
mprotect((void *)PAGE_START(addr), PAGE_SIZE, PROT_READ|PROT_WRITE);
//3. replace our hook func my_strcmp
*(void **)addr = my_strcmp;
//4. clear the cache
__builtin___clear_cache((void *)PAGE_START(addr),
(void *)PAGE_END(addr));
} int main()
{
hook();
check_is_authenticated("abcd");
return ;
}
在将libpasswd.so放置到/usr/lib/目录中之后,使用以下命令编译main.c

运行之后我们 可以看到验证结果始终是正确的,说明我们对于libpasswd.so中的strcmp函数的Hook已经生效。

怎么样,是不是很神奇呀!下面我们就来看看plt hook到底是怎么实现的。
3. PLT hook原理


以上就是第一次调用strcmp函数的流程,可以看出开销还是不小的。在后续的调用中,首先还是跳转到strcmp的plt条目中,然后执行jmpq *0x200aaa(%rip)指令,不同的是这是strcmp对应的GOT条目已经被写入了strcmp的运行时地址,所以这条jmp指令直接将程序的执行跳转到strcmp函数中。那么是不是只要在strcmp对应的GOT条目中写入我们自己的函数的地址,就可以将控制跳转到自己实现的函数中了嘛。本着这样的思路我们来看看开始时的代码。
4. 代码分析
- 第一步我们要获取libpasswd在进程中的首地址,时刻记住我们拦截的是动态库中的函数,将来要替换的GOT[strcmp]也属于libpasswd。
第二步就是获取libpasswd中调用strcmp对应的GOT条目的地址,为什么是addr = base_addr + 0x201020呢?我们回到上文的libpasswd的plt段,可以看到strcmp的plt条目的第一条指令已经写出了相应的GOT条目的地址就是0x201020。又因为我们拦截的动态库的strcmp函数,所以必须加上libpasswd在main中的首地址。
3. 因为我们要写入目标进程的数据段,所以必须给相应的页增加写权限,这里使用mprotect函数来调整相应页的权限。
void hook() {
uintptr_t base_addr;
uintptr_t addr;
//1. get the base addr of libpasswd.so
base_addr = get_base_addr("libpasswd");
if ( == base_addr) return;
addr = base_addr + 0x201020;
//2. add the write permisson
mprotect((void *)PAGE_START(addr), PAGE_SIZE, PROT_READ|PROT_WRITE);
//3. replace our hook func my_strcmp
*(void **)addr = my_strcmp;
//4. clear the cache
__builtin___clear_cache((void *)PAGE_START(addr),
(void *)PAGE_END(addr));
}
参考
PLT hook笔记的更多相关文章
- Linux Hook 笔记
相信很多人对"Hook"都不会陌生,其中文翻译为"钩子".在编程中, 钩子表示一个可以允许编程者插入自定义程序的地方,通常是打包好的程序中提供的接口. 比如,我 ...
- hook笔记①
汇编中push 0x*** retn表示跳转到某个地址继续执行 取消hook时会在多线程环境中可能被检测 去掉函数框架可以规避寄存器cpu前后状态监测 #pragma comment(linker,& ...
- hook笔记②
- 基于Android的ELF PLT/GOT符号和重定向过程ELF Hook实现(by 低端农业代码 2014.10.27)
介绍 技术原因写这篇文章,有两种: 一个是在大多数在线叙述性说明发现PLT/GOT第二十符号重定向过程定向x86的,例<Redirecting functions in shared ELF l ...
- 基于Android的ELF PLT/GOT符号重定向过程及ELF Hook实现(by 低端码农 2014.10.27)
引言 写这篇技术文的原因,主要有两个: 其一是发现网上大部分描写叙述PLT/GOT符号重定向过程的文章都是针对x86的.比方<Redirecting functions in shared EL ...
- 羽夏笔记——Hook攻防基础
写在前面 本笔记是由本人独自整理出来的,图片来源于网络.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇文章有帮助你 ...
- 孙鑫MFC学习笔记20:Hook编程
1.HOOK拦截消息,设置越后的钩子优先级越高(钩子队列)2.SetWindowHookEx设置钩子 如果thread identifier为0或其他进程创建的线程,回调函数需要在动态链接库中声 ...
- CI框架源码阅读笔记6 扩展钩子 Hook.php
CI框架允许你在不修改系统核心代码的基础上添加或者更改系统的核心功能(如重写缓存.输出等).例如,在系统开启hook的条件下(config.php中$config['enable_hooks'] = ...
- 我的Hook学习笔记
关于Hook 一.基本概念: 钩子(Hook),是Windows消息处理机制的一个平台,应用程序能够在上面设置子程以监视指定窗体的某种消息,并且所监视的窗体能够是其它进程所创建的.当消息到达后,在目标 ...
随机推荐
- Java基础(九)
综合案例 此前我们已经练习了根据集合当中的字符串对象读写文件,而本综合案例主要练习根据集合当中的自定义对象来读写文件. 场景介绍 很多网络游戏当中都有组队模式,例如魔兽世界.DotA.英雄联盟(LOL ...
- 小菜鸟之Cisco
Switch>enable// Switch#configure// Switch#show vlan//展示vlan接口 Switch(config)#enable password 1234 ...
- 第1章 Java开发入门
一.填空题 1.Java SE.Java EE.Java ME 2.JRE 3.javac 4.bin 5.path.-class path 二.判断题 1.√ 2.× JDK: java devel ...
- assign()-JS
------------恢复内容开始------------ 现需要在js中,使用一个新的对象的值覆盖旧有对象,js中有一个方法: Object.assign(target,…sources) 当ta ...
- Luogu P3520 [POI2011]SMI-Garbage
题目 把要变边权的边拿出来找欧拉回路就行了.正确性显然,因为一条边经过两次相当于对欧拉回路度数的奇偶性没有影响. 然后把一个个小环输出即可,具体的我也不知道怎么输,题目没讲清楚,我按着题解的来的. # ...
- Python 入门 之 初识面向对象
Python 入门 之 初识面向对象 1.初识面向对象编程 (核心--对象) (1)观察以下代码: # 面向过程编程 s = "alexdsb" count = 0 for i i ...
- 小白学习tornado框架第一站-环境设置
首先建立一个虚拟环境 mkvirtualenv -p /usr/bin/python3 tornado_1 安装tornado框架 pip install tornado pycham中建立同步 创 ...
- Spring经典高频面试题,原来是长这个样子
Spring经典高频面试题,原来是长这个样子 2019年08月23日 15:01:32 博文视点 阅读数 719 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文 ...
- 对ArrayList中的Person对象按照先年龄从大到小,相同年龄的再按照姓名(姓名是英文的)的字母顺序进行排序.
ListDemo2.java ----------------- package com.fs.test; import java.util.ArrayList; import java.util.C ...
- 07 MySQL之索引原理
一.介绍 为什么有索引:使用索引可快速访问数据库表中的特定信息.索引是对数据库表中一列或多列的值进行排序的一种结构. 作用: 1. 快速查询数据 2. 保证数据的唯一性 3 ...