aapt部分源码分析
之前由于二进制修改AndroidManifest.xml失败,一开始只插入属性的字符和标签node发现失败,比较后发现要插入资源id,但是还是无法生效。
之前修改的方法都可以正常安装应用,正常启动,而且xml解析都没问题,插入的debuggable="true"
就是无法生效。了解到可以aapt list
打印相应属性。
aapt list -v -a |grep debuggable
成功的xml:A: android:debuggable(0x0101000f)=(type 0x12)0xffffffff
失败的xml:A: android:debuggable=(type 0x12)0xffffffff
发现是缺少资源id,即使在XmlResourceMapType
中插入资源id,还是无法识别。
所以尝试在aapt源码中看一下,是怎么查找到资源id的。
list打印AndroidManifest.xml部分:
1 | for (i=0; i<N; i++) { |
这个部分关键:
1 | printf("%sA: ", prefix.string()); |
Resid初始化:
1 | if (type == RES_STRING_POOL_TYPE) { |
mResIds指向RES_XML_RESOURCE_MAP_TYPE
开头
mNumResIds为资源id数目
因为mResIds是顺序的,问题不在这儿,那么是由标签属性名来查找对应资源id的.
1 | int32_t ResXMLParser::getElementNamespaceID() const |
1 | int32_t ResXMLParser::getAttributeNameID(size_t idx) const |
由这两个函数可以看出,是根据index来确定标签属性名字符或命名空间名字符。
所以像A: android:debuggable(0x0101000f)=(type 0x12)0xffffffff
格式的输出流程如下:
- 顺序存储XmlResourceMapType中资源id
- 顺序遍历tag,获取tag属性的index(在string pool的索引)
- 如果在string pool中的index正好是Resid中的索引,即该tag属性的资源id为对应index的值。
所以我们插入的属性字符在string pool尾部,而Resid中值太少,无法将0x0101000f的index和string pool 中的字符debuggable
的index匹配,所以输出时并不输出资源值。
我们可以在XmlResourceMapType中填充一些资源值,把debuggable的资源值撑到和string pool中字符debuggable
的index值一致。
我插入一些相同的资源值,撑到二者index一致,当然Resid header里的size要改,chunk header里size也要改。
修改完后,放入apk中,在输出就可以看到了
修改虽然成功,但是发现debuggable还是无法生效。
最后意外的发现,修改debuggable属性的位置就可以了
debuggable不生效:
1 | A: android:label(0x01010001)=@0x7f070000 |
debuggable生效:
1 | A: android:label(0x01010001)=@0x7f070000 |
不清楚为什么标签属性位置也会影响?太坑了。。。