推薦15-php異或計算繞過preg_match()

  • 2019 年 10 月 6 日
  • 筆記

原理

以製作免殺馬為例:

在製作免殺馬的過程,根據php的語言特性對字符進行!運算會將字符類型轉為bool類型,而bool類型遇到運算符號時,true會自動轉為數字1,false會自動轉為數字0,如果將bool類型進行計算,並使用chr()函數轉為字符,使用"."進行連接,便可以繞過preg_match匹配。

詳情了解php不同於其他語言部分

但是很多的preg_match會過濾掉".",所以需要使用異或運算進行繞過,很多的免殺馬都是這樣製作的。php對字符進行異或運算是先將字符轉換成ASCII碼然後進行異或運算,並且php能直接對一串字符串進行異或運算,例如"123"^"abc"是"1"與"a"進行異或然後"2"與"b"進行異或,以此類推,在異或結束後就獲得了想要的字符串。

注意點:進行異或運算時要將數字轉換成字符形式,如果數字(int)和字符異或的話,結果只會是數字,例如1^"a"=1,"a"^2=2,將數字轉換成字符串可以使用trim()函數。

拓展:

php特性use of undefined constant,會將沒有引號的字符都自動視為字符串,ASCII碼大於0x7F的都會被當作字符串,由此可知可以簡化異或過程,任何字符與0xff異或都會取相反,這樣就能減少運算量了。

以GET或POST傳入字符繞preg_match為例:

php的eval()函數在執行時如果內部有類似"abc"^"def"的計算式,那麼就先進行計算再執行,我們可以利用再創參數來實現更方便的操作,例如傳入?a=$_GET[b],由於b不受限制就可以任意傳值了,不過

注意1:在測試過程中發現問題,類似phpinfo();的,需要將後面的();放在第個參數的後面,例如url?a={_GET}{b}();&b=phpinfo,也就是?a=${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff}();&%ff=phpinfo,在傳入後實際上為${????^????}{?}();但是到了eval()函數內部就會變成${_GET}{?}();成功執行。

注意2:測試中發現,傳值時對於要計算的部分不能用括號括起來,因為括號也將被識別為傳入的字符串,可以使用{}代替,原因是php的use of undefined constant特性,例如${_GET}{a}這樣的語句php是不會判為錯誤的,因為{}使用來界定變量的,這句話就是會將_GET自動看為字符串,也就是$_GET['a']

Demo

Suctf easyphp

<?php

$hhh = @$_GET['_'];

if (!$hhh){

highlight_file(__FILE__);

}

if(strlen($hhh)>18){

die('One inch long, one inch strong!');

}

if ( preg_match('/[x00- 0-9A-Za-z'"`~_&.,|=[x7F]+/i', $hhh) )

die('Try something else!');

$character_type = count_chars($hhh, 3);

if(strlen($character_type)>12) die("Almost there!");

eval($hhh);

?>

用戶傳入?_=${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff}();&%ff=phpinfo

成功顯示phpinfo頁面

原文鏈接:http://www.cnblogs.com/cimuhuashuimu/p/11546422.html