tft每日頭條

 > 科技

 > php解密技巧

php解密技巧

科技 更新时间:2024-09-29 07:17:00

  實驗樣本 http://www.phpjiami.com/

  

  據說“加密效果同行最高”?

  到 http://www.phpjiami.com/phpjiami.html 随意上傳一個 php 文件,然後下載加密後的文件,這就是我們要解密的文件。

  

  簡單分析一下 先看看加密後的文件

  可以看出這是一個正常的 php 文件,隻不過所有的變量名都是亂碼,還真虧了 php 引擎支持任意字符集的變量名,這個加密後的文件變量名的字節部都在 ASCII 範圍以外,全是 0x80以上的字符。

  我們看到中間有一個 php 代碼段結束标簽 ?,而他的前面還有一個 return $xxx;來結束腳本運行,這說明結束标簽後面的數據都不會被正常輸出,後面極可能是源文件加密後的數據,而前面的 php 代碼隻是用來解密的。

  調試之前的準備 這裡使用的 IDE 是 VSCode(最開始我使用的是 PHPStorm,後來我發現 VSCode的效果更好)。首先,安裝 PHP Debug 插件。

  

  然後,按照 htt文件)(4)" />

  然後,執行 php format.php。

  使用這個方法格式化的 php 文件内容并沒有被損壞,我們可以繼續分析了。

  

  如果,還不行,那就隻能用十六進制編輯器查找 ; 和 } 手動替換了,添加 \r\n 了。

  調試 最前面這兩行我們得先注釋掉,不然出了什麼錯誤的話會莫名其妙的。

  error_reporting(0);

  ini_set("display_errors", 0);

  保存。然後完蛋了,代碼又亂了。

  我們需要一個支持非可顯示字符的編輯器,或者...更改顯示編碼,選擇一個不是多字節的字符集,比如 Western (ISO 8859-1)

  

  現在,開始我們的調試。

  在第一行下斷點。執行 php 2.php運行程序。然後單步調試,一邊執行,一邊注意變量的值,分析函數的執行流程。

  

  使用 VSCode的調試功能,我們可以方便的查看變量的具體内容。

  

  單步調試到這一行,似乎有些不對勁。

  

  php_sapi_name() == 'cli' ? die() : '';

  我們用命令行運行的,所以執行完這一句,肯定程序就結束了。

  那就讓他結束吧,我們把這一行注釋掉,在他下面下斷點。重新運行程序。

  下面這行是就是讀取當前文件,這句話沒有什麼問題。

  $f = file_get_contents(constant('rnfzwpch'));

  然後就又是驗證運行環境。

  if(!isset($_SERVER['HTTP_HOST']) !isset($_SERVER['SERVER_ADDR']) !isset($_SERVER['REMOTE_ADDR'])) {

  die();

  }

  注釋掉,保存,重新運行。

  當然,也可以通過調試控制台,執行類似 $_SERVER['HTTP_HOST'] = '127.0.0.1'; 這類指令,來讓驗證通過。

  

  再看下面的代碼,我想到 exe 反調試了,不得不佩服想這個方法的人。防止下斷點調試的,如果下斷點調試,這裡就超過 100 毫秒了。

  $t = microtime(true) * 1000;eval("");if (microtime(true) * 1000 - $t 100) {

  die();

  }

  我們直接在這條語句之後下斷點,讓他們一連串執行完,這樣就不會超過 100 毫秒了。當然,直接注釋掉是最粗暴的方法。

  下面的 eval我們需要通過“單步進入”來研究,不過結果是對我們的影響不大,當然注釋掉也沒問題。

  

  接下來這個就是校驗數據完整性的了

  !strpos(decode_func(substr($f, -45, -1)), md5(substr($f, 0, -46))) ? $undefined1() : $undefined2;

  這裡的$undefined1和 $undefined2都沒有定義。如果驗證失敗,就會調用 $undefined1會直接 Error退出程序。而如果驗證成功,雖然 $undefined2變量不存在,但是隻是一個 Warning,并沒有太大問題。decode_func就是文件中最後一個函數,專門負責字符串解碼的。

  這個驗證方法就是把文件尾部分解密和前面的文件主體部分的 md5 對比,這次執行肯定又不能通過。

  退出程序,注釋掉,再重新運行。

  $decrypted = str_rot13(@gzuncompress(decode_func(substr($f, -2358, -46))));

  我們找到了這個解碼的關鍵語句了,可以看到解密之後的代碼已經出來了。

  

  到了代碼的最後,終于要執行腳本了。

  $f_varname = '_f_';$decrypted = check_and_decrypt(${$f_varname});

  set_include_path(dirname(${$f_varname}));$base64_encoded_decrypted = base64_encode($decrypted);$eval_string = 'eval(base64_decode($base64_encoded_decrypted));';$result = eval($eval_string);

  set_include_path(dirname(${$f_varname}));return $result;

  折騰了半天,還是 eval語句。如何把内容輸出呢。直接在 $decrypted後面加上一行 file_put_contents就可以了。

  

  成果

  通用解密程序 我們可以繼續分析一下他的解密算法

  

  算法是固定的,隻是其中内聯了一個秘鑰,我們隻要通過字符串函數截取出這個秘鑰就可以了。

  

  最後的解碼程序如下。

  

  這個程序可以解密此網站全部免費加密的代碼。

  使用方法:php decrypt.php 1.php

  總結 php 這種動态解釋語言還想加密?做夢去吧。不過混淆還是有可能的。

  這個代碼中的暗樁挺有意思,算是學到了點知識。

  php 這種東西為什麼要加密?php 的開源社區多麼龐大。

  附錄 代碼賞析

  

  

  

  ,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关科技资讯推荐

热门科技资讯推荐

网友关注

Copyright 2023-2024 - www.tftnews.com All Rights Reserved