diff --git a/php/meterpreter/ext_server_stdapi.php b/php/meterpreter/ext_server_stdapi.php index a88aef54..308f7351 100644 --- a/php/meterpreter/ext_server_stdapi.php +++ b/php/meterpreter/ext_server_stdapi.php @@ -18,8 +18,15 @@ define("TLV_TYPE_DIRECTORY_PATH", TLV_META_TYPE_STRING | 1200); define("TLV_TYPE_FILE_NAME", TLV_META_TYPE_STRING | 1201); define("TLV_TYPE_FILE_PATH", TLV_META_TYPE_STRING | 1202); define("TLV_TYPE_FILE_MODE", TLV_META_TYPE_STRING | 1203); +define("TLV_TYPE_FILE_SIZE", TLV_META_TYPE_UINT | 1204); + define("TLV_TYPE_STAT_BUF", TLV_META_TYPE_COMPLEX | 1220); +define("TLV_TYPE_SEARCH_RECURSE", TLV_META_TYPE_BOOL | 1230); +define("TLV_TYPE_SEARCH_GLOB", TLV_META_TYPE_STRING | 1231); +define("TLV_TYPE_SEARCH_ROOT", TLV_META_TYPE_STRING | 1232); +define("TLV_TYPE_SEARCH_RESULTS", TLV_META_TYPE_GROUP | 1233); + ## # Net ## @@ -147,6 +154,105 @@ define("TLV_TYPE_POWER_REASON", TLV_META_TYPE_UINT | 4101); # eval'd twice my_print("Evaling stdapi"); +## +# Search Helpers +## + +# Stolen from user comments in http://us2.php.net/manual/en/function.glob.php +# The recursiveness was busted, fixed it by adding the path to the filename +# when checking whether we're looking at a directory. +# Used by stdapi_fs_search +/**#@+ + * Extra GLOB constant for safe_glob() + */ +define('GLOB_NODIR',256); +define('GLOB_PATH',512); +define('GLOB_NODOTS',1024); +define('GLOB_RECURSE',2048); +/**#@-*/ +/** + * A safe empowered glob(). + * + * Function glob() is prohibited on some server (probably in safe mode) + * (Message "Warning: glob() has been disabled for security reasons in + * (script) on line (line)") for security reasons as stated on: + * http://seclists.org/fulldisclosure/2005/Sep/0001.html + * + * safe_glob() intends to replace glob() using readdir() & fnmatch() instead. + * Supported flags: GLOB_MARK, GLOB_NOSORT, GLOB_ONLYDIR + * Additional flags: GLOB_NODIR, GLOB_PATH, GLOB_NODOTS, GLOB_RECURSE + * (not original glob() flags) + * @author BigueNique AT yahoo DOT ca + * @updates + * - 080324 Added support for additional flags: GLOB_NODIR, GLOB_PATH, + * GLOB_NODOTS, GLOB_RECURSE + */ +if (!function_exists('safe_glob')) { +function safe_glob($pattern, $flags=0) { + $split=explode('/',str_replace('\\','/',$pattern)); + $mask=array_pop($split); + $path=implode('/',$split); + if (($dir=opendir($path))!==false) { + $glob=array(); + while (($file=readdir($dir))!==false) { + // Recurse subdirectories (GLOB_RECURSE) + if( ($flags&GLOB_RECURSE) && is_dir($path."/".$file) && (!in_array($file,array('.','..'))) ) { + $glob = array_merge($glob, array_prepend(safe_glob($path.'/'.$file.'/'.$mask, $flags), + ($flags&GLOB_PATH?'':$file.'/'))); + } + // Match file mask + if (fnmatch($mask,$file)) { + if ( ( (!($flags&GLOB_ONLYDIR)) || is_dir("$path/$file") ) + && ( (!($flags&GLOB_NODIR)) || (!is_dir($path.'/'.$file)) ) + && ( (!($flags&GLOB_NODOTS)) || (!in_array($file,array('.','..'))) ) ) + $glob[] = ($flags&GLOB_PATH?$path.'/':'') . $file . ($flags&GLOB_MARK?'/':''); + } + } + closedir($dir); + if (!($flags&GLOB_NOSORT)) sort($glob); + return $glob; + } else { + return false; + } +} +} +/** + * A better "fnmatch" alternative for windows that converts a fnmatch + * pattern into a preg one. It should work on PHP >= 4.0.0. + * @author soywiz at php dot net + * @since 17-Jul-2006 10:12 + */ +if (!function_exists('fnmatch')) { +function fnmatch($pattern, $string) { + return @preg_match('/^' . strtr(addcslashes($pattern, '\\/.+^$(){}=!<>|'), array('*' => '.*', '?' => '.?')) . '$/i', $string); +} +} + +/** + * Prepends $string to each element of $array + * If $deep is true, will indeed also apply to sub-arrays + * @author BigueNique AT yahoo DOT ca + * @since 080324 + */ +if (!function_exists('array_prepend')) { +function array_prepend($array, $string, $deep=false) { + if(empty($array)||empty($string)) return $array; + foreach($array as $key => $element) + if(is_array($element)) + if($deep) + $array[$key] = array_prepend($element,$string,$deep); + else + trigger_error('array_prepend: array element',E_USER_WARNING); + else + $array[$key] = $string.$element; + return $array; + +} +} + + +## END Search Helpers + if (!function_exists('cononicalize_path')) { function cononicalize_path($path) { $path = str_replace(array("/", "\\"), DIRECTORY_SEPARATOR, $path); @@ -282,6 +388,40 @@ function stdapi_fs_delete_file($req, &$pkt) { } } +if (!function_exists('stdapi_fs_search')) { +function stdapi_fs_search($req, &$pkt) { + my_print("doing search"); + + $root_tlv = packet_get_tlv($req, TLV_TYPE_SEARCH_ROOT); + $root = cononicalize_path($root_tlv['value']); + $glob_tlv = packet_get_tlv($req, TLV_TYPE_SEARCH_GLOB); + $glob = cononicalize_path($glob_tlv['value']); + $recurse_tlv = packet_get_tlv($req, TLV_TYPE_SEARCH_RECURSE); + $recurse = $recurse_tlv['value']; + + my_print("glob: $glob, root: $root, recurse: $recurse"); + $flags = GLOB_PATH; + if ($recurse) { + $flags |= GLOB_RECURSE; + } + $files = safe_glob($root ."/". $glob, $flags); + if ($files and is_array($files)) { + dump_array($files); + foreach ($files as $file) { + $file_tlvs = ""; + $s = stat($file); + $p = dirname($file); + $f = basename($file); + $file_tlvs .= tlv_pack(create_tlv(TLV_TYPE_FILE_PATH, $p)); + $file_tlvs .= tlv_pack(create_tlv(TLV_TYPE_FILE_NAME, $f)); + $file_tlvs .= tlv_pack(create_tlv(TLV_TYPE_FILE_SIZE, $s['size'])); + packet_add_tlv($pkt, create_tlv(TLV_TYPE_SEARCH_RESULTS, $file_tlvs)); + } + } + return ERROR_SUCCESS; +} +} + # Sys Config # works