从应用加固的角度看Android新支持的Kotlin语言

2017/05/27 Android

Kotlin语言是什么

2017年5月18日Google在I/O大会上宣布,支持将Kotlin语言作为Android开发的编程语言. 一夜之间网络上多了很多关于Kotlin语言的介绍.我也因此对该语言产生了兴趣,于是就对Kotin做了一定的调研.

Kotlin语言是一门静态类型JVM语言,由JetBrains设计开发并进行了 开源.JetBrains就是开发了著名的IntelliJ IDEA的公司.Kotlin语言的创建的目的是为 开发人员创建一种通用语言,可作为一种安全,简介,灵活与Java 100%兼容的的语言.Kotlin 语言比Java语法更简介,更具表达性,而且提供了更多的特性,例如:高阶函数,操作符重载, 字符串模板等.而且它与Java可以进行互操作.

Kotlin的特性

  1. Kotlin是一种兼容Java的语言;
  2. Kotlin比Java更安全. 能够静态检测常见的陷阱.如:引用空指针;
  3. Kotlin比Java更简洁,通过支持variable type inference, higher-order functions (closures),extension functions,mixins and first-class delegation等实现;
  4. Kotlin可与Java语言无缝通信.这意味着我们可以在Kotlin代码中使用任何已有的Java 库;同样的Kotlin代码还可以为Java代码所用;
  5. Kotlin在代码中很少需要在代码中指定类型,因为编译器可以在绝大多数情况下推断 出变量或是函数返回值的类型.这样就能获得两个好处:简洁与安全

Kotlin与Java语言的对比

Kotlin语言的解决了Java语言不能解决的问题.Kotlin解决的 问题主要有:

  1. 类型系统控制了空引用的发生.
  2. 没有原始类型
  3. Kotlin中数组是不变的
  4. 相对于Java的SAM-conversions,Kotlin有更加合适的函数类型
  5. 使用没有通配符的site variance
  6. Kotlin 没有检查异常

Kotlin在拓展Java语言的基础上同样抛弃或者说不具备Java的一些特性.这些特性如下所 示:

  1. 检查异常.
  2. 原始类型
  3. 静态成员
  4. 通配符类型
  5. 未私有化字段

Kotlin语言引入的新特征有:

  1. 高性能自定义结构(Lamda表达式+内联函数)
  2. 拓展函数
  3. Null安全
  4. 智能类型转换
  5. 字符串模板
  6. 运算符重载 ……

加固是否支持Kotlin语言

因为我目前研究的是移动应用的程序保护方向.当看到Kotlin语言的时候,我就在想当前的 加固手段能否处理Kotlin语言吗?从原理上来说Koltin语言是基于JVM的语言,也就是说Kotlin 语言最终也会编译成class文件,才能在JVM上运行.而再Android平台上是直接使用dx工具将class 文件转换成dex文件.所以从理论上来讲目前已有的加固手段是可以直接支持Kotlin语言的. 接下来我们通过逆向分析的手段对Kotlin语言做个逆向分析,以便我们更加深入的了解Kotlin 语言.

首先使用Java语言实现一个打印日志的功能.源代码如下所示:

import android.util.Log;

/**
 * Created by ** on 2017/5/27.
 */
public class LoggingSub {
    public static String Flag = "a";

    public static void pintflog(){
        for (int i = 0; i < 10; i++){
            Log.d(Flag, "this is log.d");
            Log.e(Flag, "this is log.e");
            Log.i(Flag, "this is log.i");
            Log.w(Flag, "this is log.w");
            Log.v(Flag, "this is log.v");
        }

    }
}

然后使用IDEA提供的插件直接将Java代码转换成为Kotlin语言,获得的源码如下所示:

import android.util.Log

/**
 * Created by **  on 2017/5/25.
 */
object Logging {
    var Flag = "Flags"
    fun printlog() {
        for (i in 0..5) {
            Log.d(Flag, "this is log.d")
            Log.e(Flag, "this is log.e")
            Log.i(Flag, "this is log.i")
            Log.w(Flag, "this is log.w")
            Log.v(Flag, "this is log.v")
        }

    }
}

然后在APK中的oncreate()对以上的两个方法进行调用,关于调用的代码,这里就不再贴出 来,网上有很多教程.将以上的代码进行打包.最终生成APK.然后对APK进行逆向分析.在逆向 分析过程中着重对以上两个文件分析.

使用Java语言编写的代码的逆向分析结果如下图所示:

logging-jeb-java.jpg

使用Kotlin语言编写的代码的逆向分析结果如下图所示:

logging-jeb-kotlin.jpg

通过分析以上两张图片中的代码,从反编译得到的smali语法的角度来看, Kotlin语言只 是对Java语言做了一定的拓展和封装.例如Kotlin语法在Logging的类中添加了下面的属性:

public static final Logging INSTANCE;

而且Kotlin语言还对类中的属性自动添加了set方法,构造方法如下所示:

public final void setFlag(@NotNnull String args){
    Intrinsics.checkParameterIsNotNull(arg2, "<set-?>");
    Logging.Flag = arg2;
}

在上面的代码中还有一点需要注意,该方法对输入的参数做了非空的检查.调用的方法是 Kotlin中自带的库中的Intrinsics.checkParameterIsNotNull方法.这个方法是Kotlin语 言提供的Jar中的方法,换句话说只需要使用了Kotlin语言,都需要依赖于这个Jar包.这个 Jar的内容如下图所示:

Kotlin-jar.jpg

总之,从逆向结果的分析来看,Kotlin语言就是对Java语言的封装和拓展.当使用Kotlin 语言开发应用程序时,都是将Kotlin文件转换成class,然后将class文件转换成为dex文件. 而对于应用程序加固保护的角度来看,只要是合法的dex文件就可以进行保护. 所以现有的应用加固的技术可以很好的支持对Kotlin语言开发的程序进行保护. 而且我也做了实验,使用现有的加固技术可以对上面的demo APK进行加固保护,也同样证明了现有的加固保护技术能够直接支持Kotlin语言.

写在文章的最后

由于本人能力有限,加之对本文涉及内容的研究时间较短,文章中难免有错误或者遗漏之处. 请大家多多包含,也欢迎大家指正.

Search

    Table of Contents