Android逆向_Smal对抗篇

Java高级语法原理

Java 相比较C++而言, 会有很多很高级的语法,比如,内部类,枚举类, 还有反射, 这些高级语法是java编译器自带的,如果要研究这些语法实现原理, 剧需要了解编译后的字节码语法即 Smali语法, 现在我们已经学会Smali语法。我们可以看看Java中高级语法是怎么实现的。 这里只分析一两个高级语法,如果需要可以自行研究。

内部类 && 匿名类

C++中内部类,仅仅是给内部类多加一个作用域,可以是防止内名冲突和提高可读性, 说白了,只是一种代码管理方法, 内部类是不能访问所在类的成员的。Java 中内部类有两种, 一种叫静态内部类, 还一种叫非静态内部类,通过有无static关键字可以区分。 其中静态内部内就是和C++中内部类一致,这种类不是我们讲述的主题。 我们要谈的是非静态内部类。 非静态内部类的特点是可以访问所在类的成员和方法。如下图:

 

编译后,查看Smali指令,如下

 

 

 

其中还有一种内部类,由于没有类名,被称为匿名类的类,这种类和内部类实现原理一致。

枚举enum

C++中枚举是整形常量, 在java中枚举不再是枚举常量,枚举是一个类, 枚举成员是类对象, 但是在Java中, switch语言可以支持枚举类型,而枚举是一个类,这是怎么实现的呢。 如下,我们定义一个枚举COLOR,RED, BLUE, BLACK三种类型

public enum COLOR {
RED, BLUE,BLACK
}
COLOR color = COLOR.RED;
switch(color)
{
case BLUE:
Log.d("enum", "BLUE");
break;
case RED:
Log.d("enum", "RED");
break;
}


我们JAVA编译器如何做到switch支持类对象类型的。编译,然后使用JEB查看

枚举定义:


public enum COLOR {
    public static final enum COLOR BLACK;
    public static final enum COLOR BLUE;
    public static final enum COLOR RED;
    static {
        COLOR.RED =new COLOR("RED",0);
        COLOR.BLUE =new COLOR("BLUE",1);
        COLOR.BLACK =new COLOR("BLACK",2);
        COLOR.ENUM$VALUES =new COLOR[]{COLOR.RED,COLOR.BLUE,COLOR.BLACK};
    }
    private COLOR(String strName,int orginal) {
        super(strName, orginal);
    }
    public static COLOR valueOf(String strName) {
        return Enum.valueOf(COLOR.class, strName);
    }
    public static COLOR[] values() {
        COLOR[] srcColor = COLOR.ENUM$VALUES;
        int nLen = srcColor.length;
        COLOR[] destColor = new COLOR[nLen];
        System.arraycopy(srcColor,0, destColor, 0, nLen);
        return destColor;
    }
}


Switch-case 处编译

 switch(MainActivity.$SWITCH_TABLE$com$example$test$COLOR()[COLOR.RED.ordinal()]) {
  case 1:
       Log.d("enum","RED");
       break;
  case 2:
       Log.d("enum","BLUE");
       break;
 } 


其中MainActivity.$SWITCH_TABLE$com$example$test$COLOR()[COLOR.RED.ordinal()的定义如下:

static int[] $SWITCH_TABLE$com$example$test$COLOR() {
        int[] switchTable =MainActivity.$SWITCH_TABLE$com$example$test$COLOR;
        if(switchTable ==null) {
            switchTable = new int[COLOR.values().length];
            try {
                switchTable[COLOR.BLACK.ordinal()] =3;
            }
            catch(NoSuchFieldError v1) {
            }
            try {
                switchTable[COLOR.BLUE.ordinal()] =2;
            }
            catch(NoSuchFieldError v1) {
            }
 
            try {
                switchTable[COLOR.RED.ordinal()] =1;
            }
            catch(NoSuchFieldError v1) {
            }
 
            MainActivity.$SWITCH_TABLE$com$example$test$COLOR = switchTable;
        }
 
        return switchTable;
    }


总结: java语言定义枚举中, swith-case中,定义一个switchTable,用于记录COLRO的序号,本质还是使用整形作为switch-case. 定义枚举类, 默认生成一些函数,和初实话枚举类成员块。

 

构造函数:.method private constructor <init>(String, I)V

静态块:    .method static constructor <clinit>()V

 

Java 枚举的三种用法:参考

http://blog.csdn.net/qq_27093465/article/details/52180865

Smali对抗

由于没有保护的Smali语言,反汇编还原度比较高,软件制造商为了保护自家产品不被逆向,会出现很多对抗手段。 常用方法:混淆, 针对工具bug,等等

 

Smali 常用方法

1.函数合并 :十多个函数合并一个大函数

2.流程混淆 比较少见, 混淆实现比较难

3.命名混淆 类名,函数名,变量名,都混淆成a, b,c 或者跟复杂

4.指令膨胀 指令膨胀,JEB可以优化。

 

5.利用java源码和Dalivk 指令

 

 

JEB工具被针对

JEB默认一个方法30S解析,如果一个方法解析超过30S,就会解析失败, 解决方案:修改这个值为很大值。

 

JEB工具是java写的,Java程序的需要运行虚拟机中,栈大小,内存大小都很小。JEB工具中启动脚本就需要指定运行,有些程序会故意让JEB的栈撑爆。解决方案:修改大点

 

还有很多针对方法,暂且只知道这两个。

 

APK TOOL 被针对

腾讯经常使用针对APK TOOL, 微信的资源目录名就修改了

 

1. 资源目录被改

APK TOOL默认解析资源目录为res,ApkTool利用这点修改目录为其他,这样APK TOOL就是失效了。

 

2. 清单中可以多加一个组件

APK TOOL 解析程序清单时,根据组件解析,会在字节码解析这个类, 发现找不到,就会崩溃

 

3. 清单程序增加一个组件的属性是一个没有的值

无法解析,可能会崩亏

 

4.修改dex的名字,

APK Tool解析dex字节码,默认找解析class.dex文件, 利用这点,我们将真正的代码放在另外一个.dex文件,   然后将 class.dex放假代码。 这样你解析出代码。

运行的使用,dalvik可以指定启动某个.dex文件, 可以利用假的.dex启动资源。

 

 

利用 smali && Java语法差异

比如:函数重载

java语法上, 函数返回是不能成为函数重载的依据,所以下面代码是编译有误的

int fun()
{
return 0;  
}
void fun()
{}


为了编译通过,我们只能将其中一个重命名

int newfun()
{
return 0;  
}
void fun()
{}


然后我们在编译代码后如下:

.method fun()V
          .registers 1
          .prologue
          .line 17
00000000  return-void
.end method
.method newfun()I
          .registers 2
          .prologue
          .line 14
00000000  const/4                 v0,0x0
00000002  return                  v0
.end method


如果我们修改smail中 所有引用newfunfun, 然后回编,是不会报错的,因为smali语法是支持可以通过, 因为返回值不同,导致函数声明不冲突。所以汇编是成功了,然后我们在使用JEB工具,会产生如下代码:

int fun()
{
return 0;  
}
void fun()
{}


1. 而这种代码java语言是不能通过编译的。

2. JEB的重命名功能也无效了,无法区分这个两个函数

 

对于中方法混淆,我们只能通过人工根据Smail二进制代码来区分。 对于一两个我们还能忍受,但是对于大量,成百上千的这种混淆,我们会崩溃的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值