1 概述
比如,进行漏洞扫描的时候,经常需要对APK进行反编译,然后使用python对每个反编译进行解析,得到结果
但是:在反编译android应用的时候,使用现有的工具,比如jadx某些时候会存在解析不出来的时候,这时候就不得不使用jeb或者apktools了,
1、使用jeb反编译并导出java文件,这个过程使用自动化是特别慢的,估计一个稍微大的应用就会差不多两个小时,速度很慢
2、最后还是回到了apktools,解析smali代码了
2 smali 代码的格式
参考文章smali语法
2.1 常用类型
smali语法 | Java语法 | 类型 |
---|---|---|
B | byte | 原始类型 |
C | char | 原始类型 |
D | double (64 bits) | 原始类型 |
F | float | 原始类型 |
I | int | 原始类型 |
J | long (64 bits) | 原始类型 |
S | short | 原始类型 |
V | void 只能用于返回值类型 | 原始类型 |
Z | boolean | 原始类型 |
[ | [] | 数组类型 |
Lxx/yy/zz; | xx.yy.zz | 对象类型 |
2.2 方法
形式:Lxxx/yyy/zzz;->methodName(Lxxx/yyy/zzz;Lxxx/yyy/zzz;I)Z
Lxxx/yyy/zzz;(类名)
->methodName(方法名)
(Lxxx/yyy/zzz;Lxxx/yyy/zzz;I)(参数)
Z(返回值)
ex:如 int Log.i(String str2, String str2)转换后是 Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I
2.3 变量
形式:Lxxx/yyy/zzz;->FieldName:Lxxx/yyy/zzz;
Lxxx/yyy/zzz;(类名)
->FieldName:(变量)
Lxxx/yyy/zzz;(类型)
ex:如:ff = "aa"; 转换后是 Lcom/example/reforceapk/MyLog;->ff:Ljava/lang/String
2.4 常用语法指令
smali指令 | 含义 |
---|---|
.field private isFlag:z | 定义变量 |
.method | 方法 |
.prologue | 方法开始 |
.end method | 方法结束 |
.parameter | 方法参数 |
.line 12 | 此方法位于第12行 |
invoke-super | 调用父函数 |
invoke-direct | 调用函数 |
invoke-static | 调用静态函数 |
const/high16 v0, 0x7f03 | 把0x7f03赋值给v0 |
return-void | 函数返回void |
new-instance | 创建实例 |
move-result v0 | 将上一个invoke类型的指令操作的非对象结果赋值给v0寄存器 |
move-result-object v0 | 将上一个invoke类型指令操作的对象赋值给v0寄存器 |
3 使用Python对函数解析
3.1 总体思路
不知道其他的大神是怎么做的,搜了半天也没有找到,我琢磨了半天,总结了以下的思路
总体思路:将函数中的类型转换为标准的java类型,然后考虑一下例外情况,
- 常用类型:比如 I 直接替换为int
- 如果存在数组:需要做1个顺序的调整
- 如果存在对象:需要将对象替换为标准的java函数
总结下来就是这样了:
3.2 实现算法
案例:在之前的反编译代码中找到一个稍微复杂点的方法(含有对象数组,含有二维数组,对象中含有常见大写字符,对象中可能疑似函数对象“Lx/xL/xx;”)
".method private static decodeStream(Ljava/io/InputStream;Ljava/iL/InputStream;[Ljava/iLo/InputStream;[BI[[IIF)Landroid/graphics/Bitmap;\n"
通过手动转换应该是:
private static decodeStream android.graphics.Bitmap(java.io.InputStream,java.iL.InputStream,java.iLo.InputStream[],byte[],int,int[][],int,float)