关于Apktool编译和回编译问题的研究与修复

转载请注明地址:https://blog.csdn.net/lynnchurch/article/details/95100451

为了防止安卓App被Apktool反编译和回编译,有一种比较有效的手段就是针对Apktool的漏洞进行防护,使Apktool在反编译或回编译的过程中发生异常而导致失败。所以要想绕过此类防护手段,就得修复Apktool的相关漏洞,好在Apktool是开源的,于是我们就可以通过研究Apktool的源代码来进行修复。下面是关于目前所遇到的一些问题的说明与修复。

注意:本文的目的在于逆向分析技术的学习与研究,切勿用于非法目的

原Apktool项目地址:https://github.com/iBotPeaches/Apktool

问题一:Could not decode file

反编译的过程中出现如下错误:

S: Could not decode file, replacing by FALSE value: layout/xxx_item.xml

这是由于向resources.arsc文件中定义了一些并不存在且实际app又不需要的资源,所以按照此无实际资源的文件路径进行解码的时候会出现异常。

解决方案就是在ARSCDecoder.readEntry()方法中创建ResResSpecResResource实例之前去判断资源路径所指的资源是否存在,存在则创建相应实例,否则就过滤该资源,代码如下所示:

		if (value instanceof ResFileValue) {
			String valueStr = value.toString();
			Directory apkDir;
			try {
				apkDir = ApkDecoder.getApkFile().getDirectory();
			} catch (DirectoryException e) {
				throw new AndrolibException(e.getMessage());
			}
			if (!apkDir.containsFile(valueStr)) {
				return;
			}
		}

问题二:Cant find 9patch chunk in file

反编译的过程中出现如下警告:

W: Cant find 9patch chunk in file: "drawable-hdpi-v4/abc_list_selector_disabled_holo_light.9.png". Renaming it to *.png.

这是由于打包的时候在gradle中配置了 shrinkResources true,这样那些没有被用到的.9.png图会被处理成宽高各3个像素的png图(虽然文件扩展名是.9.png,但实际格式是png),所以Apktool遇到这种图会修改他们的扩展名为.png,而遇到真正的.9.png图就会给他们周边加相应的黑线(apk包里的.9.png图在打包的过程中会把黑线去掉,而我们用Apktool进行回编译是需要黑线的)。


问题三:No resource found that matches the given name(APKTOOL_DUMMY_xxx)

回编译过程出现如下警告:

W: D:\demo\res\anim\abc_grow_fade_in_from_bottom.xml:4: error: Error: No resource found that matches the given name (at 'interpolator' with value '@android:anim/APKTOOL_DUMMY_6').

继而出现如下异常:

brut.androlib.AndrolibException: brut.common.BrutException: could not exec (exit code = 1)

这个问题是由于ARSCDecoder.addMissingResSpecs()方法导致的,顾名思义就是添加丢失的资源规格。Apktool在解析ResTable_entry偏移数组的时候发现有些条目的偏移值为-1,这就意味着该条目没有相应的资源规格,对于这种情况Apktool会强行添加名如APKTOOL_DUMMY_6这种形式的规格名去构建相应的资源规格,这样一来回编译的时候就会出现No resource found that matches the given name这样的警告。解决方案简单粗暴,就是注释掉ARSCDecoder.addMissingResSpecs()方法,后面验证发现可以正常回编译。


问题四:No resource identifier found

回编译过程出现如下警告并出现异常导致失败:

W: D:\demo_res_guard\res\layout\a2.xml:5: error: No resource identifier found for attribute 'exampleColor' in package 'me.lynnchurch.customview'

出现这个警告是由于使用了如微信的AndResGuard进行了资源混淆,就会找不到相应的资源ID。

aapt在编译布局文件的时候会给其中的自定义属性添加ID(在这之前会对values目录下的资源如自定义属性生成对应的ID),添加ID是通过属性名去之前生成的资源ID表中去查找的。经过资源混淆的apk在用Apktool反编译生成的atrrs.xml文件中的属性名也是混淆的,但是布局文件中的属性名却还是原名,所以通过布局文件中的属性名去查找ID会提示No resource identifier found for attribute 'xxxAttr'

所以要想解决这个问题,就得让Apktool在反编译的时候对混淆的属性名进行还原。通过分析Apktool的源码,发现进行xml文件解析的主要是AXmlResourceParser这个类,其中getAttributeName()方法用于读取属性名,而这个属性名正是我们需要的原属性名,拿到这个属性名后就可以替换从resources.arsc中读取的混淆后的属性名,原属性名和混淆后的属性名通过属性资源ID进行映射。关键代码如下:

			ResID resID = new ResID(getAttributeNameResource(index));
			if (mAttrDecoder.getCurrentPackage().hasResSpec(resID)) {
				ResResSpec resSpec = mAttrDecoder.getCurrentPackage().getResSpec(resID);
				resSpec.setName(value);
			}

经测试成功将混淆的属性名还原,再进行回编译已无No resource identifier found for attribute 'xxxAttr'警告,如此便可绕过AndResGuard这类资源混淆工具的反编译防护机制。


问题五:No resource found that matches the given name(?attr/xxx)

回编译过程出现如下警告并出现异常导致失败:

W: D:\demo\res\layout\a1.xml:5: error: Error: No resource found that matches the given name (at 'style' with value '?attr/actionBarStyle'). 

通过aaptdump出能够正常回编译的xml文件style属性是这样的:A: style=?0x7f020005,dump出回编译异常的xml文件style属性是这样的:A: style=?0x7f020005 (Raw: "?attr/actionBarStyle"),通过对比发现发生异常的xml文件style属性多了个(Raw: "?attr/actionBarStyle")

正常的xml反编译后生成的style属性内容是这样的style="?f",而异常的xml反编译后生成的style属性却是这样的style="?attr/actionBarStyle",前者能够成功找到所需的资源,后者却找不到并报出No resource found that matches the given name这样的警告。

通过以上分析,解决问题的思路就出来了,那就是解析形如A: style=?0x7f020005 (Raw: "?attr/actionBarStyle")这样的属性时,只取?0x7f020005这样的值。

回到Apktool源码中,发现ResScalarValue.encodeAsResXmlAttr()方法是对属性值进行处理的,具体处理细节如下:

    public String encodeAsResXmlAttr() throws AndrolibException {
        if (mRawValue != null) {
            return mRawValue;
        }
        return encodeAsResXml();
    }

发现它是优先取mRawValue这个值,也就是上面所说的(Raw: "?attr/actionBarStyle")这样的值,那么忽略掉mRawValue这样的值应该就能解决问题了,如下:

    public String encodeAsResXmlAttr() throws AndrolibException {
        return encodeAsResXml();
    }

经过以上处理,反编译回编译验证通过。


暂时对这五个问题进行分析修复,后续遇到新的问题会更新本文,大家如有遇到新的问题,欢迎在本文下方评论,一起学习交流,文中如有不妥之处,还请斧正。

本文fork的Apktool项目地址:https://github.com/lynnchurch/Apktool

  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值