WebShell管理工具冰蝎3.0分析

目的

  • 远程管理功能的实现细节,做到使用工具的过程中知其所以然。
  • 二开

环境准备

  • IDEA
  • tomcat
  • php
  • ASP
  • dnspy
  • 3.0t00ls专版

源码获取

通过使用IDEA自带的java反编译工具反编译冰蝎jar包获得java源码

1
java -cp /home/kali/Tools/idea-IC-212.5457.46/plugins/java-decompiler/lib/java-decompiler.jar  org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler -dgs=true <src.jar> <dest dir>

结构分析

1
2
3
4
5
6
7
8
9
10
net
└── rebeyond
└── behinder
├── core # 远程管理实现、加解密相关
├── dao # webshell连接信息数据管理
├── entity # 文件、webshell、插件类信息
├── payload # asp、jsp、php以及csharp的执行代码
├── resource # 命令控制的dll、shellcode
├── ui # 界面实现
└── utils # 封装的函数处理过程

core目录存放的是项目的核心代码

upload successful

1
2
3
4
5
6
7
8
9
core
├── Constants.java # 客户端版本信息 请求ua 其他常量数据
├── Crypt.java # 加密代码
├── Decrypt.java # 解密代码
├── Params.java # 动态生成class数据
├── PluginResultCallBack.java # 插件相关
├── PluginSubmitCallBack.java # 插件相关
├── PluginTools.java # 插件调用相关
└── ShellService.java # 远程管理

upload successful

ua信息可以修改成自定义的信息。

upload successful

解密jsp返回包用ECB,可以改成其他方式。

ShellService实现远程管理功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
public class ShellService {
public String currentUrl;
public String currentPassword;
public String currentKey;
public String currentType;
public Map<String, String> currentHeaders;
public int encryptType;
public int beginIndex;
public int endIndex;
public JSONObject shellEntity;
public static int BUFFSIZE = 46080;
public static Map<String, Object> currentProxy;

public ShellService(JSONObject shellEntity); // 初始化类
private void initHeaders(); // 初始化请求头

private String getReferer(); // 生成refer信息
private String getCurrentUserAgent(); // 从Constants里面随机选择一个UA

public static void setProxy(Map<String, Object> proxy); // 赋值代理信息

public static Map<String, Object> getProxy(Map<String, Object> proxy); // 获取代理信息

public JSONObject getShellEntity(); // 获取当前shell实体信息

private void mergeCookie(Map<String, String> headers, String cookie); // 合并用户设置的cookie

private void mergeHeaders(Map<String, String> headers, String headerTxt); // 合并用户设置的请求头

private String formatHeaderName(String beforeName); // 格式化header数据

public boolean doConnect() throws Exception; // 连接WebShell

public String eval(String sourceCode) throws Exception; // 执行用户输入的代码

public JSONObject runCmd(String cmd, String path) throws Exception; // 命令执行

public JSONObject createBShell(String target, String localPort) throws Exception; // 创建本地监听后门

public JSONObject sendBShellCommand(String target, String action, String actionParams) throws Exception; // 发送后门命令

public JSONObject submitPluginTask(String taskID, String payloadPath, Map<String, String> pluginParams) throws Exception; // 提交插件任务

public JSONObject getPluginTaskResult(String taskID) throws Exception; // 获取插件任务结果

public JSONObject loadJar(String libPath) throws Exception; // 直接加载jar包

public JSONObject createRealCMD(String bashPath) throws Exception; // 创建交互式cmd进程

public JSONObject stopRealCMD() throws Exception; // 停止交互式cmd进程

public JSONObject readRealCMD() throws Exception; // 读取交互式cmd进程输出

public JSONObject writeRealCMD(String cmd) throws Exception; // 发送命令到交互式cmd进程

public JSONObject listFiles(String path) throws Exception; // 列举路径下文件

public JSONObject getTimeStamp(String path) throws Exception; // 获取文件时间戳

public JSONObject updateTimeStamp(String path, String createTimeStamp, String modifyTimeStamp, String accessTimeStamp) throws Exception; // 更新文件的创建、修改、访问时间

public JSONObject updateModifyTimeStamp(String path, String modifyTimeStamp) throws Exception; // 更新文件的修改时间

public JSONObject deleteFile(String path) throws Exception; // 删除文件

public JSONObject showFile(String path, String charset) throws Exception; // 查看文件

public JSONObject renameFile(String oldName, String newName) throws Exception; // 重命名文件

public JSONObject createFile(String fileName) throws Exception;// 创建文件

public JSONObject createDirectory(String dirName) throws Exception; // 创建目录

public void downloadFile(String remotePath, String localPath) throws Exception; // 下载文件

public JSONObject execSQL(String type, String host, String port, String user, String pass, String database, String sql) throws Exception; // 执行SQL语句

public JSONObject uploadFile(String remotePath, byte[] fileContent, boolean useBlock) throws Exception; // 可选择阻塞、非阻塞模式的上传文件

public JSONObject uploadFile(String remotePath, byte[] fileContent) throws Exception; // 上传文件

public JSONObject appendFile(String remotePath, byte[] fileContent) throws Exception; // 追加文件

public boolean createRemotePortMap(String targetIP, String targetPort, String remoteIP, String remotePort) throws Exception; // 创建远程端口转发

public boolean createRemoteSocks(String targetIP, String targetPort, String remoteIP, String remotePort) throws Exception; // 创建远程流量转发

public boolean createVPSSocks(String remoteIP, String remotePort) throws Exception; // 开启转发VPS流量

public JSONObject stopVPSSocks() throws Exception; // 停止转发VPS流量

public boolean createPortMap(String targetIP, String targetPort, String socketHash) throws Exception; // 创建端口转发

public byte[] readPortMapData(String targetIP, String targetPort, String socketHash) throws Exception; // 读取端口转发来的数据

public boolean writePortMapData(byte[] proxyData, String targetIP, String targetPort, String socketHash) throws Exception; // 发送端口转发数据

public boolean closeLocalPortMap(String targetIP, String targetPort) throws Exception; // 关闭本地端口转发

public boolean closeLocalPortMapWorker(String socketHash) throws Exception; // 关闭本地端口转发线程

public boolean closeRemotePortMap() throws Exception; // 关闭远程端口转发

public byte[] readProxyData(String socketHash) throws Exception; // 读取代理过来的数据

public boolean writeProxyData(byte[] proxyData, String socketHash) throws Exception; // 通过代理发送数据

public boolean closeProxy(String socketHash) throws Exception; // 关闭代理

public boolean openProxy(String destHost, String destPort, String socketHash) throws Exception; // 打开代理

public boolean openProxyAsyc(String destHost, String destPort, String socketHash) throws Exception; // 异步打开代理

public JSONObject echo(String content) throws Exception; // 探测连接是否成功

public String getBasicInfo(String whatever) throws Exception; // 获取主机基本信息

private void showErrorMessage(String title, String msg); // 弹窗显示错误信息

public void keepAlive() throws Exception;

public JSONObject connectBack(String type, String ip, String port) throws Exception;

public JSONObject loadNativeLibrary(String libraryPath) throws Exception;

public JSONObject executePayload(String uploadLibPath, String payload) throws Exception;

public JSONObject loadLibraryAndexecutePayload(String fileContent, String payload) throws Exception;

public JSONObject loadLibraryAndfreeFile(String fileContent, String filePath) throws Exception;

public JSONObject freeFile(String uploadLibPath, String filePath) throws Exception;

public JSONObject loadLibraryAndAntiAgent(String fileContent) throws Exception;

public JSONObject antiAgent(String uploadLibPath) throws Exception;

public JSONObject loadLibraryAndtest() throws Exception; // 加载DLL测试

public JSONObject injectMemShell(String type, String libPath, String path, String password, boolean isAntiAgent) throws Exception; // 注入内存马

public JSONObject createReversePortMap(String listenPort) throws Exception;

public byte[] readReversePortMapData(String socketHash) throws Exception;

public boolean writeReversePortMapData(byte[] proxyData, String socketHash) throws Exception;

public JSONObject listReversePortMap() throws Exception; // 查看反向端口列表

public JSONObject stopReversePortMap(String listenPort) throws Exception; // 停止反向端口连接

public JSONObject closeReversePortMap(String socketHash) throws Exception; // 关闭反向端口映射
}

启动流程

graph TD
id1[net.rebeyond.behinder.ui.Launcher.main]
id2[net.rebeyond.behinder.ui.Main.start]
id3[FXMLLoader.load Main.fxml]
id4[new ShellManager]
id5[initCatagoryList]
id6[initShellList]
id7[initToolbar]
id8[initBottomBar]
id9[loadProxy]
id1 --> id2
id2 --> id3
id3 --> id4
id4 --> id5
id5 --> id6
id6 --> id7
id7 --> id8
id8 --> id9

功能实现分析

Shell管理

MainController

graph TD
loadContextMenu -->  新增
新增 --> shellManager.addShell
loadContextMenu -->  更新
更新 --> shellManager.updateShell
loadContextMenu -->  删除
删除 --> shellManager.deleteShell
loadContextMenu -->  打开
打开 --> 加载MainWindow.fxml
加载MainWindow.fxml --> 加载Tabs页面
加载MainWindow.fxml --> currentShellService.getBasicInfo
加载MainWindow.fxml --> shellManager.setShellStatus

远程管理

命令执行

CmdViewController

graph TD
onCMDKeyPressed --> addHistory
addHistory --> currentShellService.runCmd

文件管理

FileManagerViewController

graph TD
loadContextMenu --> 刷新
刷新 --> currentShellService.listFiles
loadContextMenu --> 打开
打开 --> |文件|currentShellService.showFile
打开 --> |目录|currentShellService.listFiles
loadContextMenu --> 删除
删除 --> currentShellService.deleteFile
graph TD
loadContextMenu --> 重命名
重命名 --> currentShellService.renameFile
loadContextMenu --> 下载
下载 --> currentShellService.downloadFile
loadContextMenu --> 上传
上传 --> currentShellService.uploadFile
graph TD
loadContextMenu --> 新建文件夹
新建文件夹 --> currentShellService.createDirectory
loadContextMenu --> 修改时间戳
修改时间戳 --> currentShellService.updateTimeStamp
loadContextMenu --> 克隆时间戳未实现

数据库管理

DatabaseViewController

graph TD
initDatabaseView --> initDatabaseType
initDatabaseType --> loadContextMenu
loadContextMenu --> loadTreeContextMenu
loadContextMenu --> loadTableContextMenu
loadTreeContextMenu --> 查询前10条
查询前10条 --> executeSQL
loadTreeContextMenu --> 查询全部
查询全部 --> executeSQL
loadTreeContextMenu --> 导出当前表
导出当前表 --> executeSQL
loadTableContextMenu --> 复制单元格
loadTableContextMenu --> 复制整行
loadTableContextMenu --> 导出全部查询结果

交互式命令执行

RealCmdViewController

graph TD
initRealCmdView --> initCmdQueue
initCmdQueue --> createRealCmd
createRealCmd --> initWorkers
createRealCmd --> currentShellService.readRealCMD
initWorkers --> currentShellService.writeRealCMD

流量加密分析

Utils、Crypt

graph TD
getData --> |jsp|Encrypt
getData --> |php|EncryptForPhp
getData --> |aspx|EncryptForCSharp
getData --> |asp|EncryptForAsp
Encrypt --> AES/ECB/PKCS5Padding
EncryptForPhp --> AES/CBC/PKCS5Padding
EncryptForCSharp --> AES/CBC/PKCS5Padding
EncryptForAsp --> 循环异或

攻击载荷分析

ShellService、payload

BasicInfo

graph TD
ShellService.getBasicInfo --> BasicInfo
BasicInfo --> |jsp|Java
Java --> System.getenv
Java --> System.getProperties
Java --> getAbsolutePath
Java --> File.listRoots
BasicInfo --> |php|Php
Php --> phpinfo
Php --> driveList
Php --> getcwd
graph TD
ShellService.getBasicInfo --> BasicInfo
BasicInfo --> |asp|Asp
Asp --> Server.MapPath
Asp --> envlist
Asp --> GetWS
BasicInfo --> |aspx|CSharp
CSharp --> Environment.GetLogicalDrives
CSharp --> Environment.GetEnvironmentVariables 

BShell

graph TD
ShellService.createBShell --> BShell
BShell --> |jsp|Java
Java --> Create
Create --> createBShell
createBShell --> serverSocketChannel.accept
serverSocketChannel.accept --> Session.setAttribute
graph TD
ShellService.sendBShellCommand --> BShell
BShell --> |jsp|Java
Java --> doWork
doWork --> listFile

Cmd

graph TD
ShellService.runCmd --> |jsp|Java
Java --> RunCMD
RunCMD --> |linux|/bin/sh
RunCMD --> |windows|cmd.exe
ShellService.runCmd --> |php|Php
Php --> system
Php --> proc_open
Php --> passthru
Php --> shell_exec
Php --> exec
graph TD
ShellService.runCmd --> |asp|Asp
Asp --> WScript.shell
Asp --> WScript.shell.1
Asp --> shell.application
Asp --> shell.application.1
ShellService.runCmd --> |aspx|CSharp
CSharp --> execCMD
execCMD --> cmd.exe

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!