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相关推荐

  1. 将文本文件abc.txt中的所有行加上行号后写到newabc.txt文件中

    问题及代码: /* *Copyright (c) 2016,烟台大学计算机学院 *All rights reserved. *文件名称:main.cpp *作 者:李磊涛 *完成时间:2016年6月2 ...

  2. 一加6t android,一加6T使用体验:可能是最流畅的安卓旗舰

    11月5日,一加在深圳举办了主题为"Unlock The Speed"的新品发布会,正式发布了一加6T国行版.作为深受极客和发烧友喜爱的手机品牌,一加手机轻快流畅的特点已经深入人心 ...

  3. android地图图片加载,Android图片加载解析之Bitmap

    写在前面的话,本篇文章是参考自<Android开发艺术探索>所写,看此书已是2015年的事情啦,由于独立开放项目,以至于对于Android原理性东西生疏,最近需要换工作,重新捡起此书,仍有 ...

  4. android给图片加边框,android 图片加边框 ImageView border 成效

    android 图片加边框 ImageView border 效果 1.布局文件 res/layout/some_page.xml android:id="@+id/respImageBor ...

  5. Linux sudo命令报错:用户不在sudoers文件中

    Linux普通用户如果需要使用sudo以暂时获取root权限,需要在/etc/sudoers文件中添加用户的权限配置,具体步骤如下(以CentOS 7.2示例): 例如:以test用户获取sudo权限 ...

  6. 笔记:Linux下C编程实现每隔一秒向文件中写入当前时间

    2019独角兽企业重金招聘Python工程师标准>>> #include <stdio.h> #include <stdlib.h> #include < ...

  7. linux内核的I2C子系统详解4——i2c-s3c2410.c文件中的adapter、algorithm

    以下内容源于朱有鹏<物联网大讲堂>课程的学习,如有侵权,请告知删除. 主要分析i2c-s3c2410.c文件. 8.adapter模块的注册 (1)平台总线方式注册 因为I2C控制器属于内 ...

  8. linux查看一小时之内的日志,linux – 在[timespan]内(例如最后一小时)查找日志文件中的条目...

    我的服务器CPU使用率不高,我可以看到Apache正在使用太多的内存. 我有一种感觉,我正在用一个IP进行DOS.-也许你可以帮我找到他? 我已经使用以下行找到10个最"活跃"的I ...

  9. 【linux命令】Centos下如何匹配内容在哪个文件中

    grep -nR _CACHE_WRITE_ERROR_ ./ 命令    参数    需要查找的内容    路径

  10. linux导出表数据dmp,导出表的部分数据到dmp文件中

    例子: exp buffer=4096 log=e:\ic10.log file=e:\ic10.dmp query='where aab001=''13040100706''' tables=(ic ...

最新文章

  1. 《资本说》如何帮助企业从“0”到“1”,看王波玩转投资攻略
  2. 机器学习基础:理解梯度下降本质「附Python代码」
  3. java基础之【堆、栈、方法区】结构图
  4. opencv 直线检测
  5. 图像对象paip.Image对象出现“对象当前正在其他地方使用或者GDI+中发生一般性错误的解决...
  6. mysql按升序创建索引_Mysql中的降序索引底层实现
  7. python数据分析与应用
  8. Scala教程之:深入理解协变和逆变
  9. 两种方式解决 生产者消费者问题
  10. “人肉”背后隐藏的网络风险
  11. 自定义 ocelot 中间件输出自定义错误信息
  12. UI素材干货|听说UI设计师更喜欢Sketch
  13. Exchange 2010 (四) CAS Array部署
  14. 判断当前是否运行于Design Mode
  15. 一般人都不知道的功能强大的超级搜索引擎!!!!
  16. Nagios基本介绍
  17. jQuery图片特效脚本prettyPhoto简介
  18. LaTeX 文字对齐
  19. 广义表((a,b),c,d)表头和表尾分别是什么?
  20. Linux Kernel PANIC(一)--概述(Hard Panic/Aieee和Soft Panic/Oops)

热门文章

  1. [Dubbox异常] Unable to locate Spring NamespaceHandler for XML schema namespace [http://dubbo.apache[
  2. C++11新特性,推荐使用emplace_back()替换push_back()的原因
  3. 让计算机提速的方法,如何让电脑提速(让电脑提速的方法步骤详解 )
  4. 全球及中国焦磷酸钠行业需求态势及发展趋势预测报告(2022-2027年)
  5. matlab求松弛迭代发,[求助]Matlab超松弛迭代法 高手帮忙看看
  6. 情景式领导力学习(2) - 实践案例及思考
  7. c语言第一章复习思维导图
  8. Java实现Excel中的Rate函数
  9. Oracle 历史数据表迁移方案
  10. minecraft fabric_server 和 MCDR 安装与运行