Android逆向之旅---解析编译之后的AndroidManifest文件格式

本文详细介绍了Android应用中编译后的AndroidManifest文件格式,包括头部信息、String Chunk、ResourceId Chunk、StartNamespaceChunk和StartTagChunk的解析。通过对文件的逐层解析,展示了AndroidManifest.xml文件在编译后的结构,为理解apk反编译和逆向分析奠定了基础。此外,文章还提及了aapt工具在解析资源文件中的作用。
摘要由CSDN通过智能技术生成

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

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

               


致谢:感谢看雪论坛的MindMac大神提供的资料:http://bbs.pediy.com/thread-194206.htm


一、前言

今天又是周六了,闲来无事,只能写文章了呀,今天我们继续来看逆向的相关知识,我们今天来介绍一下Android中的AndroidManifest文件格式的内容,有的同学可能好奇了,AndroidManifest文件格式有啥好说的呢?不会是介绍那些标签和属性是怎么用的吧?那肯定不会,介绍那些知识有点无聊了,而且和我们的逆向也没关系,我们今天要介绍的是Android中编译之后的AndroidManifest文件的格式,首先来脑补一个知识点,Android中的Apk程序其实就是一个压缩包,我们可以用压缩软件进行解压的:



二、技术介绍

我们可以看到这里有三个文件我们后续都会做详细的解读的:AndroidManifest.xml,classes.dex,resources.arsc

其实说到这里只要反编译过apk的同学都知道一个工具apktool,那么其实他的工作原理就是解析这三个文件格式,因为本身Android在编译成apk之后,这个文件有自己的格式,用普通文本格式打开的话是乱码的,看不懂的,所以需要解析他们成我们能看懂的东东,所以从这篇文章开始,陆续介绍这三个文件的格式解析,这样我们在后面反编译apk的时候,遇到错误能够精确的定位到问题。

今天我们先来看一下AndroidManifest.xml格式:


如果我们这里显示全是16进制的内容,所以我们需要解析,就像我之前解析so文件一样:

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

任何一个文件都一定有他自己的格式,既然编译成apk之后,变成这样了,那么google就是给AndroidManifest定义了一种文件格式,我们只需要知道这种格式的话,就可以详细的解析出来文件了:


看到此图是不是又很激动呢?这又是一张神图(看雪大神杰作,盗图),详细的解析了AndroidManifest.xml文件的格式,但是光看这张图我们可以看不出来啥,所以要结合一个案例来解析一个文件,这样才能理解透彻,但是这样图是根基,下面我们就用一个案例来解析一下吧:

案例到处都是,谁便搞一个简单的apk,用压缩文件打开,解压出AndroidManifest.xml就可以了,然后就开始读取内容进行解析:


三、格式解析

第一、头部信息

任何一个文件格式,都会有头部信息的,而且头部信息也很重要,同时,头部一般都是固定格式的。


这里的头部信息还有这些字段信息:

1、文件魔数:四个字节

2、文件大小:四个字节


下面就开始解析所有的Chunk内容了,其实每个Chunk的内容都有一个相似点,就是头部信息:

ChunkType(四个字节)和ChunkSize(四个字节)


第二、String Chunk内容

这个Chunk主要存放的是AndroidManifest文件中所有的字符串信息


1、ChunkType:StringChunk的类型,固定四个字节:0x001C0001

2、ChunkSize:StringChunk的大小,四个字节

3、StringCount:StringChunk中字符串的个数,四个字节

4、StyleCount:StringChunk中样式的个数,四个字节,但是在实际解析过程中,这个值一直是0x00000000

5、Unknown:位置区域,四个字节,在解析的过程中,这里需要略过四个字节

6、StringPoolOffset:字符串池的偏移值,四个字节,这个偏移值是相对于StringChunk的头部位置

7、StylePoolOffset:样式池的偏移值,四个字节,这里没有Style,所以这个字段可忽略

8、StringOffsets:每个字符串的偏移值,所以他的大小应该是:StringCount*4个字节

9、SytleOffsets:每个样式的偏移值,所以他的大小应该是SytleCount*4个字节

后面就开始是字符串内容和样式内容了。


下面我们就开始来看代码了,由于代码的篇幅有点长,所以这里就分段说明,代码的整个工程,后面我会给出下载地址的,

1、首先我们需要把AndroidManifest.xml文件读入到一个byte数组中:

byte[] byteSrc = null;FileInputStream fis = null;ByteArrayOutputStream bos = null;try{ fis = new FileInputStream("xmltest/AndroidManifest1.xml"); bos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len = 0while((len=fis.read(buffer)) != -1){  bos.write(buffer, 0, len); } byteSrc = bos.toByteArray();}catch(Exception e){ System.out.println("parse xml error:"+e.toString());}finallytry{  fis.close();  bos.close(); }catch(Exception e){ }}

2、下面我们就来看看解析头部信息:

/** * 解析xml的头部信息 * @param byteSrc */public static void parseXmlHeader(byte[] byteSrc)byte[] xmlMagic = Utils.copyByte(byteSrc, 0, 4); System.out.println("magic number:"+Utils.bytesToHexString(xmlMagic)); byte[] xmlSize = Utils.copyByte(byteSrc, 4, 4); System.out.println("xml size:"+Utils.bytesToHexString(xmlSize)); xmlSb.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>"); xmlSb.append("\n");}
这里没什么说的,按照上面我们说的那个格式解析即可



3、解析StringChunk信息

/** * 解析StringChunk * @param byteSrc */public static void parseStringChunk(byte[] byteSrc)//String Chunk的标示 byte[] chunkTagByte = Utils.copyByte(byteSrc, stringChunkOffset, 4); System.out.println("string chunktag:"+Utils.bytesToHexString(chunkTagByte)); //String Size byte[] chunkSizeByte = Utils.copyByte(byteSrc, 12, 4); //System.out.println(Utils.bytesToHexString(chunkSizeByte)); int chunkSize = Utils.byte2int(chunkSizeByte); System.out.println("chunk size:"+chunkSize); //String Count byte[] chunkStringCountByte = Utils.copyByte(byteSrc, 16, 4); int chunkStringCount = Utils.byte2int(chunkStringCountByte); System.out.println("count:"+chunkStringCount); stringContentList = new ArrayList<String>(chunkStringCount); //这里需要注意的是,后面的四个字节是Style的内容,然后紧接着的四个字节始终是0,所以我们需要直接过滤这8个字节 //String Offset 相对于String Chunk的起始位置0x00000008 byte[] chunkStringOffsetByte = Utils.copyByte(byteSrc, 28, 4); int stringContentStart = 8 + Utils.byte2int(chunkStringOffsetByte); System.out.println("start:"+stringContentStart); //String Content byte[] chunkStringContentByte = Utils.copyByte(byteSrc, stringContentStart, chunkSize); /**  * 在解析字符串的时候有个问题,就是编码࿱
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值