php異或計算繞過preg_match()實現(xiàn)原理
2019-09-20
原理
以制作免殺馬為例:
在制作免殺馬的過程,根據(jù)php的語言特性對字符進行!運算會將字符類型轉為bool類型,而bool類型遇到運算符號時,true會自動轉為數(shù)字1,false會自動轉為數(shù)字0,如果將bool類型進行計算,并使用chr()函數(shù)轉為字符,使用"."進行連接,便可以繞過preg_match匹配。
詳情了解php不同于其他語言部分
但是很多的preg_match會過濾掉".",所以需要使用異或運算進行繞過,很多的免殺馬都是這樣制作的。php對字符進行異或運算是先將字符轉換成ASCII碼然后進行異或運算,并且php能直接對一串字符串進行異或運算,例如"123"^"abc"是"1"與"a"進行異或然后"2"與"b"進行異或,以此類推,在異或結束后就獲得了想要的字符串。
注意點:進行異或運算時要將數(shù)字轉換成字符形式,如果數(shù)字(int)和字符異或的話,結果只會是數(shù)字,例如1^"a"=1,"a"^2=2,將數(shù)字轉換成字符串可以使用trim()函數(shù)。
拓展:
php特性use of undefined constant,會將沒有引號的字符都自動視為字符串,ASCII碼大于0x7F的都會被當作字符串,由此可知可以簡化異或過程,任何字符與0xff異或都會取相反,這樣就能減少運算量了。
以GET或POST傳入字符繞preg_match為例:
php的eval()函數(shù)在執(zhí)行時如果內部有類似"abc"^"def"的計算式,那么就先進行計算再執(zhí)行,我們可以利用再創(chuàng)參數(shù)來實現(xiàn)更方便的操作,例如傳入?a=$_GET[b],由于b不受限制就可以任意傳值了,不過
注意1:在測試過程中發(fā)現(xiàn)問題,類似phpinfo();的,需要將后面的();放在第個參數(shù)的后面,例如url?a={_GET}();&b=phpinfo,也就是?a=${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff}();&%ff=phpinfo,在傳入后實際上為${????^????}{?}();但是到了eval()函數(shù)內部就會變成${_GET}{?}();成功執(zhí)行。
注意2:測試中發(fā)現(xiàn),傳值時對于要計算的部分不能用括號括起來,因為括號也將被識別為傳入的字符串,可以使用{}代替,原因是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頁面