加密so文件中指定的函数
来源:互联网 发布:vb app 编辑:程序博客网 时间:2024/04/30 15:16
加密so文件中指定的函数
作者: 0n1y3nd丶 分类: 逆向学习 发布时间: 2014-09-04 22:24 ė 61条评论
前言
上一篇文章中详细分析了对so文件中自定义section的加密,这一篇来分析下对so文件中自定义函数的加密
原文地址:http://bbs.pediy.com/showthread.php?t=191649
0×1
需要加密的函数是 : Java_com_example_shelldemo2_MainActivity_getString
0×2
加密
a、整个加密过程中最重要的便是在文件中找到指定函数的位置,然后去做加密处理,最后将加密过后的数据写入原位置
b、从一个ELF动态链接库文件中,根据已知的函数名称,找到相应的函数起始地址的过程如下:
从ELF的header找到文件的偏移ehdr->e_phoff。找到d_tag为PT_DYNAMIC的pargram header。
一个phdr对应一个Segment。包含了好几个节
从这个Segment开始位置找到名为:DT_DYNAMIC的节,然后从这个节中找到Elf32_Sym这个一个结构
根据结构的成员变量st_name,来和函数名称比较,相符,就用st_value和st_size两个变量找到函数的数据
c、结合代码详细分析此流程
①、main函数:
②、findTargetSectionAddr 函数,根据section名称找到对应的section位置,这里就不做详细介绍了,上一篇中已经详细提到过。
③、getTargetFuncInfo 函数,根据函数名称,寻找函数地址及大小
该函数返回包含函数信息的结构体funcInfo
st_value代表位置,st_size代表大小,根据位置和大小 去读取函数的信息。
d、文字叙述:
根据e_phoff找到第一个program header
根据p_type 找到 p_type == PT_DYNAMIC 的这个phdr [数组元素给出动态链接信息]
此段包含.dynamic这个section。
通过.dynamic这个里面的p_offset就能找到Elf32_Dyn这样一个结构体
根据d_tag标识,找到标识为 d_tag == DT_SYMTAB、d_tag == DT_HASH、d_tag ==DT_STRTAB、d_tag == DT_STRSZ、的这一系列section。
申请大小为d_uu.d_val的内存空间,为读取.dynstr做准备
可以借助readelf查看.dynstr这个节里的内容
可以知道.dynstr这个section中保存的正是所有函数的名称
通过函数名称,调用elfhash函数,计算出一个hash值
读取hash表里面的一些信息
读取.hash这个section的前四字节。保存在nbucket
读取.hash这个section的第4-8字节。保存在nchain
那么,这两个数值有什么用呢
这得从hash表的组织结构说起
hash表的结构如下:
nbucket
nchain
bucket[nbucket]
chain[nchain]
4部分,nbucket,nchain,bucket数组,chain数组
两个数组中都保存着符号表索引。
hash函数根据函数名称得到一个hash值,设为X,则bucket[X % nbucket]给出了一个索引,设为Y
该索引可用于符号表,也可用于chain表,如果符号表项不是所需要的,那么chain[Y]则给出了具有相同hash值的下一个符号表项
我们就可以根据chain这个类似于链的结构,一直向下搜索。直到找到所需的符号表项。或者chain项中包含值STN_UNDEF。
通过hash表,能够找到一系列的符号表
符号表结构如下
通过st_name来判断找到的符号表正是我们需要的
所有有了下面这样一个循环
这个循环的发生是在bucket数组中没有找到我们需要的符号表才进入的。也就是说,这个过程其实是在遍历chain这个数组
lseek(fd, dyn_hash + 4 * (2 + nbucket + funIndex), SEEK_SET);
其中funIndex是函数的索引值
hash表前两项是 nbucket 和 nchain 两个int型数据。
还有一个int型数组bucket[] 长度是nbucket
所以,根据dyn_hash + (2 + nbucket + funIndex) * 4 便实现了根据索引定位到chain数组中函数的位置
然后再去dyn_symtab中找到对应的Elf32_Sym结构
根据其中的st_name来进行判断,循环查找
0×3
解密
a、解密的过程和加密过程基本上一致的,只是说我们必须得到内存中去寻找那一系列的地址。
大致过程是:
在内存中找到so文件被加载到的地址,记为base
寻找函数
修改内存页属性
解密函数数据
还原内存页属性
b、解密入口函数如下:
里面用到了getLibAddr,getTargetFuncInfo两个函数。
getLibAddr函数用来在程序的内存空间中找到so被加载到的位置。
getTargetFuncInfo函数是用来在程序内存空间中的so中找到需要解密的函数。
可以看到,和加密过程中寻找函数地址是一样的。只是在定位过程中得计算偏移地址。
0×4
加密程序执行效果:
解密过程效果:
0 0
- 加密so文件中指定的函数
- 删除文件中指定的部分内容
- VC中指定include文件的目录
- 查询文件中指定字符的记录
- java读取jar中指定的文件
- C++替换文件中指定的内容
- sed 删除文件中指定的行
- mfc中指定文件打不开的问题
- 获取js文件中指定的数据
- 【Java】文件中指定单词的替换
- so文件的局部函数加密
- 显示EXE,DLL或PDB文件中指定函数的Parameter和local variables信息
- 显示EXE,DLL或PDB文件中指定函数的Parameter和local variables信息
- 显示EXEDLL或PDB文件中指定函数的Parameter和local variables信息
- 显示EXE,DLL或PDB文件中指定函数的Parameter和local variables信息
- C语言版GetPrivateProfileString()函数,从初始化文件中指定的条目取得字串
- 读出文件文件中指定字符后的字符串
- python 使用-读取文件、替换文件中指定的内容
- 大数据的排序策略
- 实现截屏并存储在本地
- 第十二章 二叉搜索树
- html5d的indexDB使用
- Spring mvc中@Requestmapping再探
- 加密so文件中指定的函数
- SQL VIEW(视图) 高级教程
- 技术大牛资源网址
- 如何使用Swiper在同一个页面上多个轮播组件
- 汉诺塔问题递归算法求解
- unity之通知中心
- jsp页面引入spring Controller
- python 爬虫小记
- 《C++并发编程实战》读书笔记1---多线程基本使用