AndroidManifest 反编译失败问题分析
问题
问题
最近使用 jadx
反编译一个 apk
时,发现 AndroidManifest.xml
反编译失败了,提示如下错误信息
1
2
3
4
5
6
| Error decode manifest
java.io.IOException: Expected strings start, expected offset: 0x550, actual: 0x48ac
at jadx.core.xmlgen.ParserStream.checkPos(ParserStream.java:124)
at jadx.core.xmlgen.CommonBinaryParser.parseStringPoolNoType(CommonBinaryParser.java:29)
at jadx.core.xmlgen.BinaryXMLParser.decode(BinaryXMLParser.java:109)
at jadx.core.xmlgen.BinaryXMLParser.parse(BinaryXMLParser.java:81)
|
使用 apktool
进行解包,提示类似的错误信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| >java -jar apktool.jar d f5a.apk
I: Using Apktool 2.6.0 on f5a.apk
I: Loading resource table...
W: Skipping package group: im.poqoxovpld.messenger
I: Decoding AndroidManifest.xml with resources...
Exception in thread "main" brut.androlib.err.RawXmlEncounteredException: Could not decode XML
at brut.androlib.res.decoder.XmlPullStreamDecoder.decode(XmlPullStreamDecoder.java:145)
at brut.androlib.res.decoder.XmlPullStreamDecoder.decodeManifest(XmlPullStreamDecoder.java:151)
at brut.androlib.res.decoder.ResFileDecoder.decodeManifest(ResFileDecoder.java:159)
at brut.androlib.res.AndrolibResources.decodeManifestWithResources(AndrolibResources.java:193)
at brut.androlib.Androlib.decodeManifestWithResources(Androlib.java:140)
at brut.androlib.ApkDecoder.decode(ApkDecoder.java:109)
at brut.apktool.Main.cmdDecode(Main.java:175)
at brut.apktool.Main.main(Main.java:78)
Caused by: java.io.EOFException: reached end of stream after reading 32680 bytes; 877722808 bytes expected
at com.google.common.io.ByteStreams.readFully(ByteStreams.java:790)
at com.google.common.io.ByteStreams.readFully(ByteStreams.java:771)
at com.google.common.io.LittleEndianDataInputStream.readFully(LittleEndianDataInputStream.java:65)
at brut.util.DataInputDelegate.readFully(DataInputDelegate.java:66)
at brut.androlib.res.decoder.StringBlock.read(StringBlock.java:70)
at brut.androlib.res.decoder.AXmlResourceParser.doNext(AXmlResourceParser.java:814)
at brut.androlib.res.decoder.AXmlResourceParser.next(AXmlResourceParser.java:98)
at brut.androlib.res.decoder.AXmlResourceParser.nextToken(AXmlResourceParser.java:108)
at org.xmlpull.v1.wrapper.classic.XmlPullParserDelegate.nextToken(XmlPullParserDelegate.java:105)
at brut.androlib.res.decoder.XmlPullStreamDecoder.decode(XmlPullStreamDecoder.java:138)
... 7 more
|
错误信息提示我们文件格式可能被修改了,由于 AndroidManifest.xml
文件已经被编译成了二进制文件,我们需要借助 010 Editor
工具辅助分析。
010 Editor 导入模板
010 Editor
支持导入模板,模板可以根据指定的规则解析二进制文件格式,并提供可视化界面进行分析和修改,官方的模板仓库在 010 Editor - Binary Template Repository 。
将 AndroidManifestg.xml
拖入 010 Editor
中,此时只能查看二进制信息
我们导入 AndroidManifest.bt,将模板文件下载到本地后,首先 Open Template
选择模板文件,再点击 Run Template
运行模板文件
此时 Template Results
界面出现了文件的格式数据,我们可以进行下一步分析了
文件格式分析
查看报错信息
1
| Expected strings start, expected offset: 0x550, actual: 0x48ac
|
如图中所示正常情况 0X550
应该为第一个字符串数据,但是实际位置为 0x24+0x4888=0x48ac
,导致 jadx
解析失败了
对比下 AndroidManifest.xml结构图
stringChunk
中的参数如下
-
String count
:4bytes
,表示字符串的数量 -
String Offsets
:int
数组,大小为 String Count
, 存储每个字符串在字符串池中的相对偏移量 -
Style Offets
:同上为 int
数组,大小为 Style Count * 4 bytes
-
String pool
:字符串池,存储了所有字符串
以上参数是顺序存储的,style count
值为 0,意味着没有 Style offsets
,所以 String Offsets
与 string pool
位置连续。
而 string pool
的起始位置为 0X550
,String Offsets
的起始位置为 0x24
,可得以下公式
1
2
3
| scStringOffsets.start + (scStringCount * 4) = scStringPool.start
=> 0x24 + (scStringCount * 4) = 0x550
=> scStringCount = 0x14B = 331
|
文件修复
由上可知,scStringcount
的值是错误的,应该为 331 而不是 4642,修改为正确的值后保存
按 F5 重新解析文件格式,发现其它数据也正常显示出来了
将 xml
文件放回 apk
中,再次使用 jadx
反编译,xml
已经可以正常解析