Android逆向之旅---SO ELF 文件格式详解

本文详述了Android逆向分析中的SO文件ELF格式,从前言到实际操作,包括准备资料、理解ELF文件结构、使用readelf工具,以及用Java和C++代码解析ELF文件。通过手动编写解析类,加深对ELF文件格式的理解,并提供了相关资源下载链接。
摘要由CSDN通过智能技术生成

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               

第一、前言

从今天开始我们正式开始Android的逆向之旅,关于逆向的相关知识,想必大家都不陌生了,逆向领域是一个充满挑战和神秘的领域。作为一名Android开发者,每个人都想去探索这个领域,因为一旦你破解了别人的内容,成就感肯定爆棚,不过相反的是,我们不仅要研究破解之道,也要研究加密之道,因为加密和破解是相生相克的。但是我们在破解的过程中可能最头疼的是native层,也就是so文件的破解。所以我们先来详细了解一下so文件的内容下面就来看看我们今天所要介绍的内容。今天我们先来介绍一下elf文件的格式,因为我们知道Android中的so文件就是elf文件,所以需要了解so文件,必须先来了解一下elf文件的格式,对于如何详细了解一个elf文件,就是手动的写一个工具类来解析一个elf文件。


第二、准备资料

我们需要了解elf文件的格式,关于elf文件格式详解,网上已经有很多介绍资料了。这里我也不做太多的解释了。不过有两个资料还是需要介绍一下的,因为网上的内容真的很多,很杂。这两个资料是最全的,也是最好的。我就是看这两个资料来操作的:

第一个资料是非虫大哥的经典之作:


看吧,是不是超级详细?后面我们用Java代码来解析elf文件的时候,就是按照这张图来的。但是这张图有些数据结构解释的还不是很清楚,所以第二个资料来了。

第二个资料:北京大学实验室出的标准版

http://download.csdn.net/detail/jiangwei0910410003/9204051

这里就不对这个文件做详细解释了,后面在做解析工作的时候,会截图说明。

关于上面的这两个资料,这里还是多数两句:一定要仔细认真的阅读。这个是经典之作。也是后面工作的基础。


第三、工具

当然这里还需要介绍一个工具,因为这个工具在我们下面解析elf文件的时候,也非常有用,而且是检查我们解析elf文件的模板。

就是很出名的:readelf命令

不过Window下这个命令不能用,因为这个命令是Linux的,所以我们还得做个工作就是安装Cygwin。关于这个工具的安装,大家可以看看这篇文章:

http://blog.csdn.net/jiangwei0910410003/article/details/17710243

不过在下载的过程中,我担心小朋友们会遇到挫折,所以很贴心的,放到的云盘里面:

http://pan.baidu.com/s/1C1Zci

下载下来之后,需要改一个东西才能用:


该一下这个文件:


这个路径要改成你本地cygwin64中的bin目录的路径,不然运行错误的。改好之后,直接运行Cygwin.bat就可以了。

关于readelf工具我们这里不做太详细的介绍,只介绍我们要用到的命令:

1、readelf -h xxx.so

查看so文件的头部信息



2、readelf -S xxx.so

查看so文件的段(Section)头的信息



3、readelf -l xxx.so

查看so文件的程序段头信息(Program)



4、readelf -a xxx.so

查看so文件的全部内容



还有很多命令用法,这里就不在细说了,网上有很多介绍的~~


第四、实际操作解析Elf文件(Java代码&C++代码)

上面我们介绍了elf文件格式资料,elf文件的工具,那么下面我们就来实际操作一下,来用Java代码手把手的解析一个libhello-jni.so文件。关于这个libhello-jni.so文件的下载地址:

http://download.csdn.net/detail/jiangwei0910410003/9204087

1、首先定义elf文件中各个结构体内容

这个我们需要参考elf.h这个头文件的格式了。这个文件网上也是有的,这里还是给个下载链接吧:

http://download.csdn.net/detail/jiangwei0910410003/9204081

我们看看Java中定义的elf文件的数据结构类:

package com.demo.parseso;import java.util.ArrayList;public class ElfType32 {  public elf32_rel rel; public elf32_rela rela; public ArrayList<Elf32_Sym> symList = new ArrayList<Elf32_Sym>(); public elf32_hdr hdr;//elf头部信息 public ArrayList<elf32_phdr> phdrList = new ArrayList<elf32_phdr>();//可能会有多个程序头 public ArrayList<elf32_shdr> shdrList = new ArrayList<elf32_shdr>();//可能会有多个段头 public ArrayList<elf32_strtb> strtbList = new ArrayList<elf32_strtb>();//可能会有多个字符串值  public ElfType32() {  rel = new elf32_rel();  rela = new elf32_rela();  hdr = new elf32_hdr(); }  /**  *  typedef struct elf32_rel {    Elf32_Addr r_offset;    Elf32_Word r_info;  } Elf32_Rel;  *  */ public class elf32_rel {  public byte[] r_offset = new byte[4];  public byte[] r_info = new byte[4];    @Override  public String toString(){   return "r_offset:"+Utils.bytes2HexString(r_offset)+";r_info:"+Utils.bytes2HexString(r_info);  } }  /**  *  typedef struct elf32_rela{    Elf32_Addr r_offset;    Elf32_Word r_info;    Elf32_Sword r_addend;  } Elf32_Rela;  */ public class elf32_rela{  public byte[] r_offset = new byte[4];  public byte[] r_info = new byte[4];  public byte[] r_addend = new byte[4];    @Override  public String toString(){   return "r_offset:"+Utils.bytes2HexString(r_offset)+";r_info:"+Utils.bytes2HexString(r_info)+";r_addend:"+Utils.bytes2HexString(r_info);  } }  /**  * typedef struct elf32_sym{    Elf32_Word st_name;    Elf32_Addr st_value;    Elf32_Word st_size;    unsigned char st_info;    unsigned char st_other;    Elf32_Half st_shndx;  } Elf32_Sym;  */ public static class Elf32_Sym{  public byte[] st_name = new byte[4];  public byte[] st_value = new byte[4];  public byte[] st_size = new byte[4];  public byte st_info;  public byte st_other;  public byte[] st_shndx = new byte[2];    @Override  public String toString(){   return "st_name:"+Utils.bytes2HexString(st_name)     +"\nst_value:"+Utils.bytes2HexString(st_value)     +"\nst_size:"+Utils.bytes2HexString(st_size)     +"\nst_info:"+(st_info/16)     +"\nst_other:"+(((short)st_other) & 0xF)     +"\nst_shndx:"+Utils.bytes2HexString(st_shndx);  } }  public void printSymList(){  for(int i=0;i<symList.size();i++){   System.out.println();   System.out.println("The "+(i+1)+" Symbol Table:");   System.out.println(symList.get(i).toString());  } }  //Bind字段==》st_info public static final int STB_LOCAL = 0public static final int STB_GLOBAL = 1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值