天天看点

Android resources.arsc资源文件防护原理分析

主要防止apktool反编译resources.acrs资源文件,从而对资源文件进行保护

resources.acrs资源文件格式主要引用老罗的博客内容

Resources.arsc文件格式是由一系列的chunk构成,每一个chunk均包含如下结构的ResChunk_header,用来描述这个chunk的基本信息。
struct ResChunk_header
 {
     enum 
     {
         RES_NULL_TYPE               = ,
         RES_STRING_POOL_TYPE        = ,
         RES_TABLE_TYPE              = ,
         RES_XML_TYPE                = ,
         RES_XML_FIRST_CHUNK_TYPE    = ,
         RES_XML_START_NAMESPACE_TYPE= ,
         RES_XML_END_NAMESPACE_TYPE  = ,
         RES_XML_START_ELEMENT_TYPE  = ,
         RES_XML_END_ELEMENT_TYPE    = ,
         RES_XML_CDATA_TYPE          = ,
         RES_XML_LAST_CHUNK_TYPE     = ,
         RES_XML_RESOURCE_MAP_TYPE   = ,
         RES_TABLE_PACKAGE_TYPE      = ,
         RES_TABLE_TYPE_TYPE         = ,
         RES_TABLE_TYPE_SPEC_TYPE    = 
     };
     //当前这个chunk的类型
     uint16_t type;
     //当前这个chunk的头部大小
     uint16_t headerSize;
     //当前这个chunk的大小
     uint32_t size;
 };
           

我们先看反编译错误信息,后面再说如何实现

apktool错误日志:

Exception in thread "main" brut.androlib.err.UndefinedResObject: resource spec: 
  at brut.androlib.res.data.ResPackage.getResSpec(ResPackage.java:)
  at brut.androlib.res.data.ResTable.getResSpec(ResTable.java:)
  at brut.androlib.res.data.ResTable.getResSpec(ResTable.java:)
  at brut.androlib.res.data.value.ResReferenceValue.getReferent(ResReferenceValue.java:)
  at brut.androlib.res.data.value.ResReferenceValue.encodeAsResXml(ResReferenceValue.java:)
  at brut.androlib.res.data.value.ResScalarValue.encodeAsResXmlValue(ResScalarValue.java:)
  at brut.androlib.res.data.value.ResScalarValue.serializeToResValuesXml(ResScalarValue.java:)
  at brut.androlib.res.AndrolibResources.generateValuesFile(AndrolibResources.java:)
  at brut.androlib.res.AndrolibResources.decode(AndrolibResources.java:)
  at brut.androlib.Androlib.decodeResourcesFull(Androlib.java:)
  at brut.androlib.ApkDecoder.decode(ApkDecoder.java:)
  at brut.apktool.Main.cmdDecode(Main.java:)
  at brut.apktool.Main.main(Main.java:)
           

错误提示是resource spec: 0x7f000005,下面就来看看使用aapt d resources test.apk 查看资源信息

appt d resources的基本格式如下:

resource <Resource ID> <Package Name>:<Type>/<Name>: t=<DataType> d=<Data> (s=<Size> r=<Res0>)
Resource ID R.java中的资源ID 
Package Name 资源所在的的包 
Type 资源的类型 
Name 资源名称 
DataType 数据类型,按照以下枚举类型取值 
Data 资源的值,根据dataType进行解释 
Size 一直为0x0008
Res0 固定为0x00
           
aapt d resources test.apk
Package Groups ()
Package Group  id= packageCount= name=com.example.myapp
  Package  id= name=com.example.myapp
    type  configCount= entryCount=
      spec resource  com.example.myapp:drawable/ic_launcher: flags=
      config ldpi-v4:
        resource  com.example.myapp:drawable/ic_launcher: t= d= (s= r=)
      config mdpi-v4:
        resource  com.example.myapp:drawable/ic_launcher: t= d= (s= r=)
      config hdpi-v4:
        resource  com.example.myapp:drawable/ic_launcher: t= d= (s= r=)
      config xhdpi-v4:
        resource  com.example.myapp:drawable/ic_launcher: t= d= (s= r=)
    type  configCount= entryCount=
      spec resource  com.example.myapp:layout/main: flags=
      config (default):
        resource  com.example.myapp:layout/main: t= d= (s= r=)
    type  configCount= entryCount=
      spec resource  com.example.myapp:string/app_name: flags=
      config (default):
        resource  com.example.myapp:string/app_name: t= d= (s= r=)
           
Android resources.arsc资源文件防护原理分析

我随便弄了一个com.example.myapp进行测试,通过上面信息可以看到app_name: t=0x02 已经改变,也就是DataType 数据类型。

直接使用010 Editor或其他HEX工具打开resources.arsc搜索对应的d=0x00000005(十六进制搜索需要反过来)

直接搜索HEX值:05000000然后将前面对应的08 00 00 02改成08 00 00 03然后保存打包,再反编译测试

经过测试drawable或string对应的DataType 数据类型值t=0x03修改为0x01或0x02都可以导致apktool反编译失败