php源代码保护——PHP加密方案分析解密还原
前言
php是一種解釋型腳本語言.
與編譯型語言不同,php源代碼不是直接翻譯成機器語言.而是翻譯成中間代碼(OPCODE) ,再由解釋器(ZEND引擎)對中間代碼進行解釋運行 .
在php源代碼的保護在原理可以分為3大類.
- 源代碼混淆(編碼)
- OPCODE混淆(編碼)
- 修改解釋引擎(虛擬機)
在部署上可以分為2大類.
- 無擴展
- 有擴展
下面分析下各種加密方案的實現方法
PHP 加密方案分析
無擴展方案
源代碼混淆
無擴展的加密在一些小開發(fā)者比較常見。
這種源代碼保護方式侵入性小,無需對服務器做額外的配置,兼容性較強。
這種情況混淆后的源代碼還原非常簡單,可完全還原出源代碼。 有時連注釋都會保留 (x 我覺得這種混淆都不能稱之為加密
基本流程 壓縮代碼->混淆變量函數類名->使用簡單函數和方法進行編碼加密 例:base64 異或
【點擊查看資料】或私信回復“資料”獲取
手工解密
看到這種的php不要慌 這種處理后的文件 解密流程的變量和函數名使用了大量的非打印字符 按照正常的流程就可以
ctrl+alt+l 快捷鍵 格式化代碼 (這里使用的PhpStorm 其他IDE 格式化遇到特殊符號可能出問題 這里提前調整好了文件編碼)
這里有一個php的特性 php中的base64遇到非base64表中字符會直接忽略 不會影響解碼
注: PHP7 遇到空字符可能會拋出error 可以使用php5.6執(zhí)行 (這里有一個兼容性問題 )
遇到這種加密最簡單的方法就是找文件中最后一步執(zhí)行的函數 直接把內容打印出來
這種編碼方法最后一步肯定要使用eval執(zhí)行還原后的php代碼 所以打印最后一個函數基本上php代碼就會全部出來 (x 前面操作一大頓毫無卵用
注: 有保護方案也使用了call_user_func或call_user_func_array間接調用eval
成功還原源代碼 <?php phpinfo();?>
自動化通用解密
PHP提供了強大的擴展功能 可以直接通過編寫php擴展hook eval相關函數 獲取執(zhí)行的源代碼
HOOK php zend引擎的 zend_compile_string zend_include_or_eval 函數達到目的
這里演示的是 hook zend_compile_string 函數
成功還原源代碼
PHP擴展方案
源代碼混淆
使用php擴展的代碼混淆和無擴展代碼混淆比較相似,只不過是把代碼還原過程從php代碼轉到了php擴展。
同樣是使用aes des 異或等加密方法直接加密php代碼,HOOK翻譯php的函數在翻譯PHP文件前對文件進行解密操作。這種方案也可以完全還原出源代碼。在無其他混淆和壓縮時甚至還會保留注釋。
手工解密
這里以beast為例.
首先在php的擴展目錄下找到beast.so
beast的加密方案會把加密key編譯進擴展中. 我們只需要尋找key就可以完成解密
beast由于是開源項目.有現成的符號表和源碼這使得反編譯尋找key變得非常簡單.
但這樣有點太簡單了. 所以這里演示的是在沒有源碼的情況下使用IDA分析解密流程.
首先在導入表找到zend_compile_file
這個函數會將php文件翻譯成opcode
因此大部分php加密擴展都需要hook這個函數達到攔截php文件載入和替換php文件的功能
繼續(xù)跟入
發(fā)現有兩個函數
一般在這種php加密擴展設計時會對這個函數有兩次操作:
一個是在啟動時hook 這個函數,一個是在停止時恢復這個函數。
繼續(xù)跟入啟動hook
顯然文件處理邏輯在cgi_compile_file內
跟蹤文件句柄
decrypt_file函數的參數存在文件句柄 所以這個函數應該就是文件解密函數
根據代碼可以看出beast 加密文件的結構
| encrypt_file_header_sign 文件頭標記(不固定 可修改)| reallen文件長度 int 4字節(jié) | expire 到期時間 int 4字節(jié)| entype 加密方式 int 4字節(jié)| 加密后文件|
分析文件頭發(fā)現該文件加密方式為 02
跟入beast_get_encrypt_algo
2對應的是 aes_handler_ops
使用了AES 128 ECB加密模式
直接提取key參數內容
長度剛好16位
到這一步就成功拿到了加密秘鑰
使用拿到的KEY就可以解密PHP文件
?
自動化通用解密
編寫php擴展 HOOK zend_compile_file函數
beast的加密不會對php文件做額外的操作 解密文件與加密前原文件完全一致
php注釋和原格式都會保留
注意: 這里擴展加載順序問題 建議直接修改php源碼
Zendzend_language_scanner.c
ZEND_API zend_op_array *compile_file
opcode
php會將源代碼翻譯成類似匯編的二進制中間操作碼再交給zend引擎執(zhí)行。
之前的介紹的都是編譯之前對php源代碼的直接操作。這里是對opcode的操作,跳過翻譯過程,直接把現成的opcode交給zend引擎執(zhí)行(不同版本PHP引擎編譯出的opcode可能會有兼容性問題)。
這種php代碼防護方法 只能hook zend_execute 拿到opcode。 不可能直接得到原本的源碼,只能通過反編譯盡可能的還原源代碼。
大部分商業(yè)php保護方案都使用這種可靠的方案為基礎 _ZendGuard(zend) _SourceGuardian(SG) IonCube (IC) Swoole Compiler
上面的方案有的還對zend引擎進行了魔改,使翻譯出的opcode只能在修改后的引擎執(zhí)行,進一步增強了安全性。
還原代碼
hook zend_execute 拿到opcode
使用對應版本的php操作碼反推php代碼
太菜了不會反編譯)
私信回復“資料”獲取以下:
1、200多本網絡安全系列電子書
2、全套工具包
3、100份src源碼技術文檔
4、網絡安全基礎入門、Linux、web安全、攻防方面的視頻
5、 網絡安全學習路線
6、ctf奪旗賽解析
附錄
PHP擴展編譯?
docker run -it --rm -v /mnt/hgfs/tmpssd/php-eval-hook/:/ext/ php:5.6 /bin/bash apt-get update apt install libtool phpizephpize 生成Makefile
./configure --enable-evalhook
配置編譯選項 啟用擴展
最后執(zhí)行make 編譯擴展
編譯好的擴展會放在./modules/ 目錄下
使用擴展
php -d extension=擴展位置 -f 文件
./configure --enable-evalhook配置編譯選項 啟用擴展
最后執(zhí)行make 編譯擴展
編譯好的擴展會放在./modules/ 目錄下
使用擴展
可以重復使用-d extension 加載多個擴展
總結
在選用PHP源碼保護方案時 盡量選擇opcode或虛擬機方案
源代碼混淆類只能對源代碼獲取和閱讀增加一點困難 在加密擴展可被攻擊者獲取到時并不能起到保護作用
總結
以上是生活随笔為你收集整理的php源代码保护——PHP加密方案分析解密还原的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何提取D-Link解密密钥
- 下一篇: 【安全漏洞】CVE-2021-32682