文档章节

【C#】【APK】APK文件解析AXML-层层深入APK文件解析之一

Parser7
 Parser7
发布于 2015/02/14 18:13
字数 1660
阅读 2984
收藏 126
点赞 2
评论 4

APK解析是很久以前想完成的一件事,但是因为一些事情搁下了。

当时使用Iteedee的代码在200多个APK文件中有将近四分之一的文件是无法成功解析AXML的。Iteedee下称I

因此,本文的代码基于I的代码修改,效果基本接近于APKTOOL(https://code.google.com/p/android-apktool/)

毋庸置疑的是,在解析的时候,会遇到各种奇葩的编码问题,首先会遇到文件的压缩解压缩码流问题,不得不说SharpZip的性能还是可以的,注意APK使用的Zip压缩格式是非固实压缩,虽然压缩性能(Performance of Compression ,BenchMark)降低了,但是对于文件寻址来说还是很方便的。

常用的APK解析读取APK信息的方法有很多种:

1、AAPT工具、2、apkTool工具、3、AXMLPrinter2工具、4、自带ZIP解压引擎纯字节流解码分析、5、其它...

这里要讲的就是第四种,是基于开源库SharpZipLib的。

‍‍下面言归正传,谈谈个中遇到的一些问题:

1、关于怎么解压zip可以看这个问题的某层回答:

http://bbs.csdn.net/topics/390421494

注意GZip和Zip不一样,Gzip在HTTP请求中比较常见

使用到的sharp库到如下网站去找

http://icsharpcode.github.io/SharpZipLib/

2、zip版本问题(788):

大部分文件的解压版本都是0x14,而个别文件出现0x0314,因此抛出了异常,具体原因无法考究,解决方案是在SharpZipLib源码中加入代码过滤掉,影响应该不大:

 if (extractVersion==788)
{
    extractVersion &= 0xff; 
}

记得备案,免得那天遇到问题了不知道这一茬。


3、文本编码问题:

从I那儿下载的代码经过测试后还是存在不少问题的,这里说的文本编码就是一个典型的例子。

I使用的是UTF8编码格式进行转码

通过 http://tool.chinaz.com/Tools/URLEncode.aspx  查了下"赶集"两字的UTF8的码流形式为:%e8%b5%b6%e9%9b%86 .

 然而,把解析之前的AndroidManifest.xml在程序里dump出来发现实际上是这样的:

那么问题就来了,通过http://tool.chinaz.com/Tools/Unicode.aspx 查了一下unicode码流(unicode的编码据说没有一个统一的标准,所以才出现了UTF8\16\32等编码),给出的结果是:\u8d76\u96c6\u7b80\u6613\u5730\u56fe。

原因真的就找到了吗,有时候人真的是聪明反被聪明误啊,博主考虑了大小端的问题,于是字节换序、去00字节、重返UTF8(为什么再使用UTF8也是基于很多原因)各种方法试过皆无果之后,探究了下Unicode编码在c#中实现的具体码流:

            byte[] bytes = Encoding.Unicode.GetBytes(textBox1.Text);
            for (int ii = 0; ii < bytes.Length; ii++)
            {
                textBox2.Text += string.Format("{0:x2} ", bytes[ii]);
            }

结果如下:

显然字序跟AXML中的是一模一样,注意00字节,可见AXML和c#中的unicode都使用了双字节对齐的(这不废话么),那么修复了编码Bug之后的某个子函数是这样的:

 private String compXmlStringAt(byte[] arr, int strOff)
        {
            int strLen = arr[strOff + 1] << 8 & 0xff00 | arr[strOff] & 0xff;
            byte[] chars = new byte[strLen<<=1 ];
            for (int ii = 0; ii < strLen ; ii++)
            {
                chars[ii] = arr[strOff + 2 + ii];
            }
            return Encoding.Unicode.GetString(chars);//Change to Unicode of Encoding by Parser7
        }

如此而来,就成功支持了中文/多语言了。然而让我郁闷的是,通篇的注释都在说Unicode,只字未提UTF8,代码的原作者居然赫然在目地写着错误的代码,令人费解的注释


4、TEXT事件类型的处理:

I写的代码,只对startTag之类的事件做了处理,然而XmlPullParser使用了五类事件,但是I对未知事件的处理是直接break了,这样会造成manifest等元素在流中未关闭的问题,严重的致命/FATOL ERROR。

由于此处对TEXT内容并不关心,所以使用对offset简单处理防止死循环的方法跳过。后面有空了再来细细研究这个东西。有需要的朋友可以一起交流下。

XmlPullParser的源码我估计可能就在这个网站http://www.xmlpull.org/ ,找到的记得发我一份,先谢谢了。

相关资料:

http://blog.csdn.net/andyhuabing/article/details/8036340

5、size=0问题导致无法正确读到androidmanifest.xml:

I使用了如下的方法遍历每一个压缩包中的文件

 while ((item = zip.GetNextEntry()) != null)
{...}

在某个APK的解析中发现出现size=0导致未能成功读取androidmanifest.xml文件。

跟踪了size读写器所有的过程后,发现在ZipFile构造函数中已经能够获得所有的ZipEntry,而I的代码这里调用GetNextEntry方法显然不仅是画蛇添足而且还引入了Bug,废话少说,使用迭代器轻松搞定:

PZipFile = new ZipFile(fsStream);
 foreach (ZipEntry entry in PZipFile )
 {    ...    }

小结:

至此,已经能成功解析1021个文件的AXML,但还有35个文件不能成功解析。

经检验,有21个文件已经损坏,但还有14个文件可以成功打开压缩包,具体原因还在分析中。

6、XmlException抛出的EntityName解析错误:并指出在35行51列

I的代码似乎没有实现将decompressXML之后的result转为XMLDocument,这里是我自己加了相应的代码,但是却出现这样的问题。

dump出解析的xml内容后发现在指定位置出现了xml非法字符'&',将非法字符转义处理就行了。

下面就是很直接、赤裸裸的代码了:

public static string HandleInvalidCharAtXMLDoc(string filename)
{
 return filename.Replace("<", "&lt;").Replace(">", "&gt;").Replace("&", "&amp;").Replace("'", "&apos;").Replace("\"", "&quot;");
}


7、压缩包签名头问题:

apktool解不开,winrar能看到目录结构,从压缩档中拖拽文件貌似可以解压AXML,但是会提示文件损坏,将解压出来的AXML文件放入成功解析的APK后能正确解析出AXML明文内容。

经过一些实验后,发现dump出来的字节流跟能解析出来的字节流不一样,说明可能是entry索引出了问题,或者内容被破坏了。根据上文描述,明显问题出在entry索引问题,或者是其它问题(不是788等版本问题)

© 著作权归作者所有

共有 人打赏支持
Parser7
粉丝 23
博文 14
码字总数 21280
作品 1
杭州
程序员
加载中

评论(4)

Parser7
Parser7

引用来自“yujiff”的评论

涉及编码,就应该弄清unicode与utf8,utf16,utf32等等的关系。
是的,一般的系统unicode好像都是16位实现,其实就是宽char吧,之前因为解析过sqlite,对编码接触也不多,所以绕了一大弯。
y
yujiff
涉及编码,就应该弄清unicode与utf8,utf16,utf32等等的关系。
Parser7
Parser7

引用来自“FlashCHen”的评论

这是所谓的反编译的意思吗?

只是解析了AXML,反编译的一部分。
FlashCHen
FlashCHen
这是所谓的反编译的意思吗?
OSChina 技术周刊第二十二期 —— DUBBO 配置规则详解

每周技术抢先看,总有你想要的! 移动开发 【翻译】为你的 Android 应用增加本地搜索功能 前端开发 【软件】AngularJS 的剪贴板扩展 ngClip 【软件】国际化和本地化 JavaScript 库 Globaliz...

OSC编辑部 ⋅ 2015/02/16 ⋅ 0

OSChina 技术周刊第二十二期 —— DUBBO配置规则详解

每周技术抢先看,总有你想要的! 移动开发 【翻译】为你的 Android 应用增加本地搜索功能 前端开发 【软件】AngularJS 的剪贴板扩展 ngClip 【软件】国际化和本地化 JavaScript 库 Globaliz...

OSC编辑部 ⋅ 2015/02/16 ⋅ 0

转载分享:Android APP二次打包操作步骤介绍

看到好的技术教程就想转载一下,不喜勿喷!谢谢配合,仅供菜鸟学习研究,不要做坏事哦(^o^)/~ 关于Android APP 二次打包现象已经屡见不鲜,为何“打包党”就吃准了Android平台,二次打包的操...

科技创造 ⋅ 2015/08/26 ⋅ 2

Android apk仿反编译套路(一)

反编译Apk时你是否遇到过下图中的错误,反编译进行到就报错了,然后就没有然后了。 pic001.png 这是因为该apk的文件被特殊处理过,导致在反编译时报错。 我们知道是以AXML格式存在于apk中的,...

hellsam ⋅ 03/22 ⋅ 0

APK安装流程详解16——Android包管理总结

APK安装流程系列文章整体内容如下: APK安装流程详解0——前言 APK安装流程详解1——有关"安装ing"的实体类概述 APK安装流程详解2——PackageManager简介 APK安装流程详解3——PackageManage...

隔壁老李头 ⋅ 2017/12/20 ⋅ 0

Android PackageManagerService详细分析

本篇主要分析了系统启动阶段包管理服务的启动流程,其中的几个接口在 apk 安装时也会被调用。包管理服务启动时主要做的工作大致有如下几方面: 1. 建立 java 层的 installer 与 c 层的 instal...

wangjian19 ⋅ 2014/01/07 ⋅ 0

MultiDex 源码剖析

1,apk中的classes2.dex ..classesN.dex... 等文件被解析出来分别存储在 /data/data/packagename/files/secondary-dex/ 下 的zip文件中(这一过程只在app安装后第一次启动时进行); classesN...

lightUp ⋅ 2015/03/25 ⋅ 0

重用布局文件

1.使用include标签。并用android:id属性覆盖被参考布局文件中顶层节点的id属性值。 如参考mylayout.xml <include android:id="@+id/layout01" layout="@layout/mylayout"/> 2.问题:你觉得直...

一别经年 ⋅ 2013/12/24 ⋅ 0

【源码】c#编写的安卓客户端与Windows服务器程序进行网络通信

源码(包含客户端与服务器端所有工程文件) 数据库文件 为了方便测试,我临时搭建了一个服务器可以安装apk文件,直接测试 apk文件下载地址 通信框架为来自英国的NetworkComms2.3.1开源通信框...

拉偶有所依 ⋅ 2015/03/09 ⋅ 0

struts2上传Apk 文件?

上传图片和一些压缩文件都没有问题。但是是传apk exe文件报404 然后连action里面的方法都不执行了。private File min; private String minContentType; private String minFileName; 是不是s...

rational ⋅ 2012/07/06 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

设计模式--装饰者模式

装饰者模式 定义 动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。 通用类图 意图 动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比...

gaob2001 ⋅ 56分钟前 ⋅ 0

JavaScript零基础入门——(八)JavaScript的数组

JavaScript零基础入门——(八)JavaScript的数组 欢迎大家回到我们的JavaScript零基础入门,上一节课我们讲了有关JavaScript正则表达式的相关知识点,便于大家更好的对字符串进行处理。这一...

JandenMa ⋅ 今天 ⋅ 0

sbt网络问题解决方案

转自:http://dblab.xmu.edu.cn/blog/maven-network-problem/ cd ~/.sbt/launchers/0.13.9unzip -q ./sbt-launch.jar 修改 vi sbt/sbt.boot.properties 增加一个oschina库地址: [reposit......

狐狸老侠 ⋅ 今天 ⋅ 0

大数据,必须掌握的10项顶级安全技术

我们看到越来越多的数据泄漏事故、勒索软件和其他类型的网络攻击,这使得安全成为一个热门话题。 去年,企业IT面临的威胁仍然处于非常高的水平,每天都会看到媒体报道大量数据泄漏事故和攻击...

p柯西 ⋅ 今天 ⋅ 0

Linux下安装配置Hadoop2.7.6

前提 安装jdk 下载 wget http://mirrors.hust.edu.cn/apache/hadoop/common/hadoop-2.7.6/hadoop-2.7.6.tar.gz 解压 配置 vim /etc/profile # 配置java环境变量 export JAVA_HOME=/opt/jdk1......

晨猫 ⋅ 今天 ⋅ 0

crontab工具介绍

crontab crontab 是一个用于设置周期性被执行的任务工具。 周期性执行的任务列表称为Cron Table crontab(选项)(参数) -e:编辑该用户的计时器设置; -l:列出该用户的计时器设置; -r:删除该...

Linux学习笔记 ⋅ 今天 ⋅ 0

深入Java多线程——Java内存模型深入(2)

5. final域的内存语义 5.1 final域的重排序规则 1.对于final域,编译器和处理器要遵守两个重排序规则: (1)在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用...

江左煤郎 ⋅ 今天 ⋅ 0

面试-正向代理和反向代理

面试-正向代理和反向代理 Nginx 是一个高性能的反向代理服务器,但同时也支持正向代理方式的配置。

秋日芒草 ⋅ 今天 ⋅ 0

Spring 依赖注入(DI)

1、Setter方法注入: 通过设置方法注入依赖。这种方法既简单又常用。 类中定义set()方法: public class HelloWorldOutput{ HelloWorld helloWorld; public void setHelloWorld...

霍淇滨 ⋅ 昨天 ⋅ 0

马氏距离与欧氏距离

马氏距离 马氏距离也可以定义为两个服从同一分布并且其协方差矩阵为Σ的随机变量之间的差异程度。 如果协方差矩阵为单位矩阵,那么马氏距离就简化为欧氏距离,如果协方差矩阵为对角阵,则其也...

漫步当下 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部