dex中方法指令隐藏
通过了解dex文件格式,获取到指定方法的指令码的偏移,将指令码清空,达到对指定方法实现的隐藏效果。
原理
dex文件格式这里就不详讲了,可以通过010editor直观得看到dex文件中各个区域信息。
关键是我们怎么获取到对应方法的指令码。
我们看到,首先获取到class_defs_item,找到类信息的偏移(class_data_off),得到class_data_item,里面有direct方法列表和virtual方法列表,每一项记录了对应方法的code_item的偏移,由该偏移我们就能找到存放指令码的区域。
即然要实现指定方法的查找,就需要解析dex,解析出所有方法并存放起来,再由我们指定取出,来将其指令置空。
通过这篇文章中的提示,修改了部分代码,完成了对指定方法的置空。
实现
在解析dex代码中,我们将string、type、proto都先存放起来,以便对方法名、参数类型解析时获取。
按照之前讲的索引过程,就需要先解析class_def_item,得到class_data_item
public static void parseClassIds(byte[] srcByte)
|
/private static ClassDefItem parseClassDefItem(byte[] srcByte)
|
/public static void parseClassData(byte[] srcByte)
我编译得到的dex部分class_def_item的class_data_off为0,这里我加了个对0的判断。
得到class_data_item后就可以获取对应类的方法列表。
private static ClassDataItem parseClassDataItem(byte[] srcByte, int offset)
这个函数在解析class_data_item时,4个字段的类型应该是uleb128,源代码中直接byte转int,故修改了size计算函数。
class_data_item中有direct方法列表和virtual方法列表,在遍历方法时需要分开遍历。
public static void parseCode(byte[] srcByte)
|
/private static CodeItem parseCodeItem(byte[] srcByte, int offset)
在解析code_item时,关键是获取到指令码数组和指令码的文件偏移。
1 | short[] insnsAry = new short[item.insns_size]; |
遍历方法函数,利用directMethodCodeItemMap
和virtualMethodCodeItemMap
将所有的方法存放起来,一个方法名对应一个方法实例。
部分method_item的code_off为0,也需要忽略处理。
private static String getMethodSignStr(MethodIdsItem methodItem)
由方法中各个字段,获取到方法的类名、方法名、参数名、返回类型,组成一个字符串。数据来源就是之前得到的string、type、proto三个列表。
1 | codeItemMap.putAll(ParseDexUtils.directMethodCodeItemMap); |
将所有方法合并成一个map,遍历搜索指定方法签名。获取到对应的code_item,取出指令码偏移,指令码个数,挨个置空。之后修复dex的signature和checksum。完成后替换原apk中的dex即可。
之后讲解指令码还原部分。