linux so 加壳,[android] 从加壳的so文件中抽出symbols
0x00 背景
大家可能碰到过加壳的so文件,一般很轻松能从内存中dump出解密后的so文件,但是问题是dump出来的so文件里的symbol虽然都在,但是symbol所对应的函数地址都没有了,这样你dump出的so即使放在IDA中分析,看上去也是没有symbol的,难以分析。所以我做了一个可以把内存里的符号表也dump出来的小工具。
0x01 原理
原理很简单,一般加壳工具会利用init_array来加密解密,当系统调用dlopen的load一个so文件时,最先执行的是init_array部分,如果将init_array的第一个函数替换成自己的解密函数的地址,然后在解密函数完成后调用原来的函数,so文件就能实现自解密,具体参见IDA调试android so的.init_array数组。所以其实dlopen被执行之后,so文件就已经是解密状态了。
接着,参考这篇文章:android下运行时动态链接dlopen()和dlsym()的实现,我们可以发现,dlopen返回的其实是一个soinfo结构体,这个结构体可以在安卓的
linker.h源码中找到。注意到这个结构体中有两个域分别是symtab和strtab,它们就存储了我们的主角符号表相关信息,symtab的定义参见elf.h的Elf32_Sym结构体。
再仔细读一下android下运行时动态链接dlopen()和dlsym()的实现这篇文章的最后一段关于soinfo_elf_lookup的源码,就可以分析出symtab和strtab的用法:symtab其实利用了hash来实现的快速查找,我们只要遍历所有hash bucket即可dump出所有symbol了。
static Elf32_Sym *soinfo_elf_lookup(soinfo *si, unsigned hash, const char *name)
{
Elf32_Sym *s;
Elf32_Sym *symtab = si->symtab;
const char *strtab = si->strtab;
unsigned n;
TRACE_TYPE(LOOKUP, "%5d SEARCH %s in %s@0x%08x %08x %d\n", pid,
name, si->name, si->base, hash, hash % si->nbucket);
n = hash % si->nbucket;
for(n = si->bucket[hash % si->nbucket]; n != 0; n = si->chain[n]){
s = symtab + n;
if(strcmp(strtab + s->st_name, name)) continue;
/* only concern ourselves with global and weak symbol definitions */
switch(ELF32_ST_BIND(s->st_info)){
case STB_GLOBAL:
case STB_WEAK:
if(s->st_shndx == SHN_UNDEF)
continue;
TRACE_TYPE(LOOKUP, "%5d FOUND %s in %s (%08x) %d\n", pid,
name, si->name, s->st_value, s->st_size);
return s;
}
}
return NULL;
}
0x03 代码
待续。
0x04 代码混淆
这中间学到了一些代码混淆的方法,比如
SMLATTEQ R0, R10, R0, R0
意思是R0 = R0 + (R0[31:16] * R10[31:16]),如果R0[31:16]或者R10[31:16]为零,或者条件EQ不满足(也就是Z flag寄存器为0),那么该语句将不会对任何寄存器产生影响。SMLATTEQ的具体解释可以参见:SMULxy and SMLAxy。
再比如
BGT 0xFFFFFFFF
当GT条件满足时会跳转到0xFFFFFFFF这个无效地址,所以如果通过让GT条件不满足来避免跳转,程序就不会出现access violence,该指令也就是一条无用指令。如何让GT条件不满足,可以通过函数调用来实现。任何函数在执行结束后都会check stack canary,也就是说会进行CMP操作,如果函数正常结束,CMP的结果肯定为1,也就是Z flag寄存器一定为1,而只要Z = 1,那么GT条件就不会满足,具体可以参见这篇文章:Condition Codes 1: Condition Flags and Codes。
0x05 关于section header和program header
观察一些加壳后的so文件,可以发现它们有些把section header给删除了,我们可以推测出,section header在装载和动态链接中并没有什么用处。让我们来分析一下库的装载代码:
首先find_library会调用load_library,load_library结束后还要再调用init_library,init_library会直接调用一个叫soinfo_link_image的函数,这个函数继续调用phdr_table_get_dynamic_section,而这个phdr_table_get_dynamic_section函数仅仅就是参照program header返回了dynamic这个域。之后soinfo_link_image拿到dynamic域,就能这样直接初始化诸如init_array,symtab,symstr等field。可以看到在这个过程中并没有用到section header。
0x06 其他的一些参考
linux so 加壳,[android] 从加壳的so文件中抽出symbols相关推荐
- 将文本文件abc.txt中的所有行加上行号后写到newabc.txt文件中
问题及代码: /* *Copyright (c) 2016,烟台大学计算机学院 *All rights reserved. *文件名称:main.cpp *作 者:李磊涛 *完成时间:2016年6月2 ...
- 一加6t android,一加6T使用体验:可能是最流畅的安卓旗舰
11月5日,一加在深圳举办了主题为"Unlock The Speed"的新品发布会,正式发布了一加6T国行版.作为深受极客和发烧友喜爱的手机品牌,一加手机轻快流畅的特点已经深入人心 ...
- android地图图片加载,Android图片加载解析之Bitmap
写在前面的话,本篇文章是参考自<Android开发艺术探索>所写,看此书已是2015年的事情啦,由于独立开放项目,以至于对于Android原理性东西生疏,最近需要换工作,重新捡起此书,仍有 ...
- android给图片加边框,android 图片加边框 ImageView border 成效
android 图片加边框 ImageView border 效果 1.布局文件 res/layout/some_page.xml android:id="@+id/respImageBor ...
- Linux sudo命令报错:用户不在sudoers文件中
Linux普通用户如果需要使用sudo以暂时获取root权限,需要在/etc/sudoers文件中添加用户的权限配置,具体步骤如下(以CentOS 7.2示例): 例如:以test用户获取sudo权限 ...
- 笔记:Linux下C编程实现每隔一秒向文件中写入当前时间
2019独角兽企业重金招聘Python工程师标准>>> #include <stdio.h> #include <stdlib.h> #include < ...
- linux内核的I2C子系统详解4——i2c-s3c2410.c文件中的adapter、algorithm
以下内容源于朱有鹏<物联网大讲堂>课程的学习,如有侵权,请告知删除. 主要分析i2c-s3c2410.c文件. 8.adapter模块的注册 (1)平台总线方式注册 因为I2C控制器属于内 ...
- linux查看一小时之内的日志,linux – 在[timespan]内(例如最后一小时)查找日志文件中的条目...
我的服务器CPU使用率不高,我可以看到Apache正在使用太多的内存. 我有一种感觉,我正在用一个IP进行DOS.-也许你可以帮我找到他? 我已经使用以下行找到10个最"活跃"的I ...
- 【linux命令】Centos下如何匹配内容在哪个文件中
grep -nR _CACHE_WRITE_ERROR_ ./ 命令 参数 需要查找的内容 路径
- linux导出表数据dmp,导出表的部分数据到dmp文件中
例子: exp buffer=4096 log=e:\ic10.log file=e:\ic10.dmp query='where aab001=''13040100706''' tables=(ic ...
最新文章
- 《资本说》如何帮助企业从“0”到“1”,看王波玩转投资攻略
- 机器学习基础:理解梯度下降本质「附Python代码」
- java基础之【堆、栈、方法区】结构图
- opencv 直线检测
- 图像对象paip.Image对象出现“对象当前正在其他地方使用或者GDI+中发生一般性错误的解决...
- mysql按升序创建索引_Mysql中的降序索引底层实现
- python数据分析与应用
- Scala教程之:深入理解协变和逆变
- 两种方式解决 生产者消费者问题
- “人肉”背后隐藏的网络风险
- 自定义 ocelot 中间件输出自定义错误信息
- UI素材干货|听说UI设计师更喜欢Sketch
- Exchange 2010 (四) CAS Array部署
- 判断当前是否运行于Design Mode
- 一般人都不知道的功能强大的超级搜索引擎!!!!
- Nagios基本介绍
- jQuery图片特效脚本prettyPhoto简介
- LaTeX 文字对齐
- 广义表((a,b),c,d)表头和表尾分别是什么?
- Linux Kernel PANIC(一)--概述(Hard Panic/Aieee和Soft Panic/Oops)
热门文章
- [Dubbox异常] Unable to locate Spring NamespaceHandler for XML schema namespace [http://dubbo.apache[
- C++11新特性,推荐使用emplace_back()替换push_back()的原因
- 让计算机提速的方法,如何让电脑提速(让电脑提速的方法步骤详解 )
- 全球及中国焦磷酸钠行业需求态势及发展趋势预测报告(2022-2027年)
- matlab求松弛迭代发,[求助]Matlab超松弛迭代法 高手帮忙看看
- 情景式领导力学习(2) - 实践案例及思考
- c语言第一章复习思维导图
- Java实现Excel中的Rate函数
- Oracle 历史数据表迁移方案
- minecraft fabric_server 和 MCDR 安装与运行