最近在学习Android的逆向,发现很多工具对Android异常处理方面的反汇编还原效果很差,甚至使用有些工具遇到复杂的情况还会发生错误,所以在对抗层面上,开发者会选择把重要的代码,套在异常处理中,这时候逆向者就需要手工去还原smali代码了,废话不多说,上个小例子

开发环境:Eclipse

逆向环境:JEB 2.2.7

系统环境:Win 7 64bit

首先来试试一个try 一个 catch 的情况:

 

android中的逆向 安卓逆向jeb_android中的逆向

编译完成,apk直接拖到JEB,按Q即可还原出代码:

android中的逆向 安卓逆向jeb_android中的逆向_02

  这时候试试复杂点的情况把(try 两句代码会产生异常,并使用两个对象接收):

android中的逆向 安卓逆向jeb_逆向_03

  这时候我们再使用JEB的Q功能还原,可以看到,JEB已经还原不完全了,虽然代码经我们稍作修改,也能还原!

但是如果碰到更复杂的,jeb还原的代码,就看得我们不知所措了!!

android中的逆向 安卓逆向jeb_Android逆向_04

 这时候我们再次按Q ,回到samli语法,拖动到该函数最尾部,可以看到catch的管理表:

android中的逆向 安卓逆向jeb_代码块_05

 表结构:

.catch Ljava/io/FileNotFoundException; {:10 .. :1A} :30
“10” : try开始的地方
“1A”try结束的地方
“30”catch处理的地方
“FileNotFoundException” : 指的是接收异常的对象类型

 接着综合表结构的知识,进行手工分析:

10 - 1A :

android中的逆向 安卓逆向jeb_逆向_06

 

// File file = new File("/data/local/1.txt"); // try上面的代码
try  {
  
     v4 =  new  FileOutputStream(file);
  
}

1A - 2C :

android中的逆向 安卓逆向jeb_表结构_07

 

 

我们看到v410 - 1A

)的是同一块

String v5 =  "hello" ;
v4.write(v5.getBytes());
FileOutputStream v3 = v4;


android中的逆向 安卓逆向jeb_代码块_08

30 - 3A :

确定范围是因为表项的第2项的“地址为3A”,所以确定第1项的范围到3A

catch  (FileNotFoundException e) {
     e.printStackTrace();
}

3A - 44:

android中的逆向 安卓逆向jeb_代码块_09

 

catch  (IOException e) {
     e.printStackTrace();
}

44 - 4A:

 

android中的逆向 安卓逆向jeb_表结构_10


综合以上代码可得:

// 3A
catch  (IOException e) {
// 3C
e.printStackTrace();
}
// 44
catch  (IOException e) {
  
FileOutputStream v3 = v4;
// goto 3C
}
// 4A

4A :

 

android中的逆向 安卓逆向jeb_android中的逆向_11

 

综合上面的代码可得

// 30
catch  (FileNotFoundException e) {
// 32
e.printStackTrace();
}
...
// 4A
catch  (FileNotFoundException e) {
  
FileOutputStream v3 = v4;
// goto 32
}

这时候我们看到”44” 处先保存v4 然后跳转到”3C”处,并且”44”处的.line是45(一个语句),”3A”处的.line也是45, 代表着 “44” 和 “3A” 可以归并为一个catch处理,

4A处,也相同的方式跳到”32”处,并且”4A”处的.line是41,”32”处的.line是43(相邻)代表着“4A” 和 “32”也可以归并为一个catch,

而FileOutputStream v3 = v4; 这句赋值代码,后面并没有看到v3的使用,可以将其优掉,综合表项以及上述进行分析,10 - 2c 也应该归并为同一个代码块,优化后的代码如下:

File file =  new  File( "/data/local/1.txt" );
FileOutputStream v4 =  null ;
  
try  {
v4 =  new  FileOutputStream(file);
String v5 =  "hello" ;
v4.write(v5.getBytes());
}
catch  (FileNotFoundException e) {
e.printStackTrace();
}
catch  (IOException e) {
e.printStackTrace();
  
}

总结:

重点是看表项内容,看try范围和对应接收异常的catch范围

其次综合.line所指的java代码行数和goto xxx看代码顺序,进行归并

最后笔者也仅仅是做个小例子,在实战中,其他没有混淆代码还是可以使用JEB的Q功能还原的,更复杂的情况,还原方法大同小异