GPCS Tracer v0.1

Discussion in 'PHP' started by xek, 2 Jan 2012.

  1. xek

    xek New Member

    Joined:
    10 Jul 2011
    Messages:
    28
    Likes Received:
    1
    Reputations:
    0
    GPCS Tracer v0.2

    GPCS Tracer v0.2

    Скрипт для трассировки GET, POST, COOKIE, SERVER переменных и некоторых потенциально небезопасных функций.

    - Определяет последовательность обращений к суперглобальным переменным
    - Показывает обратный путь вызова (файл, номер строки, функция)
    - Место, где определена суперглобальная переменная
    - Значение переменной

    Отлавливает функции:
    include()
    require()
    eval()
    preg_replace()
    create_function()
    fopen()
    fwrite()
    fputs()
    fread()
    file()
    readfile()
    fsockopen()
    file_get_contents()
    extract()
    parse_str()


    Опции:
    insert -- добавляет код для трассировки во все php-файлы
    remove -- удаляет код из php-файлов

    Файл трассировки будет называться имя_файла_dbg.txt

    Формат файла:
    Обратный путь вызова (номер строки):функция(аргументы)->[Путь, где определена переменная(номер строки):функция]->Имя суперглобальной переменной: Значение

    Пример:
    Code:
    [index.php(82):()] require (/engine/init.php)
    [engine\init.php(83):()] require (/engine/classes/mysql.php)
    [engine\classes\mysql.php(73):()] include (/engine/classes/mysqli.class.php)
    [engine\init.php(87):()] require (/engine/modules/functions.php)
    index.php(84):require_once(\engine\init.php)->[engine\init.php(151):()]:$_REQUEST['category']:
    index.php(84):require_once(\engine\init.php)->[engine\init.php(292):()]:$_GET['do']:
    
    Code:
    <?php
    
    // coded by _xtc
    
    class GPCS_Tracer
    {
    	public $dirs = array ();
    	public $files = array ();
    	public $delim = '\\';
    	public $filetype = 'php';
    	public $self = '';
    	public $mode = '';
    	
    	public function showInfo()
    	{
    		echo '**************************' . "\r\n";
    		echo '*                        *' . "\r\n"; 
    		echo '*    GPCS Tracer v0.2    *' . "\r\n";
    		echo '*                        *' . "\r\n";
    		echo '******** [coded by _xtc] *' . "\r\n\r\n";
    	}
    	
    	public function getAllDirs($currDir = '') {
    		if (!$currDir) { 
    			$currDir = getcwd();
    			$this->dirs[] = $currDir;
    		}
    		$files = scandir($currDir);
    		
    		foreach ($files as $file) {
    			if (is_dir($currDir . $this->delim . $file) && $file != '.' && $file != '..') {
    				$this->dirs[] = $currDir . $this->delim . $file;
    				$this->getAllDirs($currDir . $this->delim . $file);
    			}
    		}
    	}
    	
    	public function getAllFiles() {
    		foreach ($this->dirs as $dir) {
    			$files = scandir($dir);
    			
    			foreach ($files as $file) {
    				$fileExt = pathinfo($file);
    				if (!isset($fileExt['extension'])) continue;
    				
    				if (is_file($dir . $this->delim . $file) && 
    					$file != $this->self && 
    					$fileExt['extension'] == $this->filetype) 
    					
    					$this->files[] = $dir . $this->delim . $file;
    			}
    		}
    	}
    	
    	public function includeCode() {
    		$code = "<?php
    				//### included code ###
    				if (!function_exists('__dbg')) {
    					function __dbg(\$param, \$_file_, \$_line_, \$_func_) {
    						\$dbg = debug_backtrace();
    						\$dbg = array_reverse(\$dbg);
    						\$paramVal = ''; \$backtrace = ''; \$args = '';
    						foreach (\$dbg as \$value) {
    							if (\$value['function'] == '__dbg') continue;
    							\$args = '';
    							foreach (\$value['args'] as \$arg) {
    								\$arg = preg_replace('/' . preg_quote(getcwd()) . '/', '', \$arg);
    								\$args .= \$arg . ',';
    							}
    							\$args = rtrim(\$args, ',');
    							\$file = preg_replace('/' . preg_quote(getcwd()) . '/', '', \$value['file']);
    							\$file = ltrim(\$file, '\\\\');
    							\$backtrace .= \$file . '(' . \$value['line'] . ')' . ':' . \$value['function'] . '(' . \$args . ')' . '->';
    						}
    						@eval('\$paramVal = ' . \$param . ';');
    						\$_file_ = preg_replace('/' . preg_quote(getcwd()) . '/', '', \$_file_);
    						\$_file_ = ltrim(\$_file_, '\\\\');
    						\$backtrace .= '[' . \$_file_ . '(' . \$_line_ . ')' . ':' . \$_func_ . '()]';
    						\$backtrace = \$backtrace . ':' . \$param . ':' . \$paramVal;
    						\$fname = pathinfo(\$_SERVER['SCRIPT_NAME']);
    						\$filename = getcwd() . '\\\\' . \$fname['filename'] . '_dbg.txt';
    						\$handle = fopen(\$filename, 'a+');
    						\$content = file_get_contents(\$filename);
    						if (strpos(\$content, \$backtrace) !== false) return;
    						fwrite(\$handle, \$backtrace . \"\\r\\n\");
    						fclose(\$handle);
    						return \$param;
    					}
    					function __dbg_func(\$func, \$param, \$_file_, \$_line_, \$_func_) {
    						\$_file_ = preg_replace('/' . preg_quote(getcwd()) . '/', '', \$_file_);
    						\$_file_ = ltrim(\$_file_, '\\\\');
    						if (\$func == 'include' || \$func == 'require') {
    							\$param = preg_replace('/' . preg_quote(getcwd()) . '/', '', \$param);
    						}
    						\$backtrace = '[' . \$_file_ . '(' . \$_line_ . '):' . \$_func_ . '()] ' . \$func . ' (' . \$param . ')';
    						\$fname = pathinfo(\$_SERVER['SCRIPT_NAME']);
    						\$filename = getcwd() . '\\\\' . \$fname['filename'] . '_dbg.txt';
    						\$handle = fopen(\$filename, 'a+');
    						fwrite(\$handle, \$backtrace . \"\\r\\n\");
    						fclose(\$handle);
    					}
    				}
    				//### end code ###?>\r\n";
    		$patterns = array ('/(\r?\n.*?)(\$_GET(?:\[[^\]]+\])?)(.*?\r?\n)/', 
    						   '/(\r?\n.*?)?(\$_POST(?:\[[^\]]+\])?)(.*?\r?\n)/', 
    						   '/(\r?\n.*?)(\$_COOKIE(?:\[[^\]]+\])?)(.*?\r?\n)/', 
    						   '/(\r?\n.*?)(\$_REQUEST(?:\[[^\]]+\])?)(.*?\r?\n)/',
    						   '/(\r?\n.*?)(\$_SERVER(?:\[[^\]]+\])?)(.*?\r?\n)/');
    						   
    		$patternsFunc = array ('/(\r?\n\s*include(?:_once)?\s*)([^\n]+)(;.*?\r?\n)/', 
    							   '/(\r?\n\s*require(?:_once)?\s*)([^\n]+)(;.*?\r?\n)/',
    							   '/(\r?\n\s*eval\s*\([^\n]+;.*?\r?\n)/', 
    							   '/(\r?\n\s*preg_replace\s*\([^\n]+;.*?\r?\n)/', 
    							   '/(\r?\n\s*create_function\s*\([^\n]+;.*?\r?\n)/', 
    							   '/(\r?\n\s*fopen\s*\([^\n]+;.*?\r?\n)/', 
    							   '/(\r?\n\s*fwrite\s*\([^\n]+;.*?\r?\n)/', 
    							   '/(\r?\n\s*fputs\s*\([^\n]+;.*?\r?\n)/', 
    							   '/(\r?\n\s*fread\s*\([^\n]+;.*?\r?\n)/', 
    							   '/(\r?\n\s*file\s*\([^\n]+;.*?\r?\n)/', 
    							   '/(\r?\n\s*readfile\s*\([^\n]+;.*?\r?\n)/', 
    							   '/(\r?\n\s*fsockopen\s*\([^\n]+;.*?\r?\n)/',
    							   '/(\r?\n\s*file_get_contents\s*\([^\n]+;.*?\r?\n)/',
    							   '/(\r?\n\s*extract\s*\([^\n]+;.*?\r?\n)/', 
    							   '/(\r?\n\s*parse_str\s*\([^\n]+;.*?\r?\n)/',
    							   );
    		$replaceFunc = array ("\r\n" . "__dbg_func('include', $2, __FILE__, __LINE__, __FUNCTION__);$1$2$3", 
    							  "\r\n" . "__dbg_func('require', $2, __FILE__, __LINE__, __FUNCTION__);$1$2$3", 
    							  "\r\n" . "__dbg_func('eval', '', __FILE__, __LINE__, __FUNCTION__);$1", 
    							  "\r\n" . "__dbg_func('preg_replace', '', __FILE__, __LINE__, __FUNCTION__);$1", 
    							  "\r\n" . "__dbg_func('create_function', '', __FILE__, __LINE__, __FUNCTION__);$1", 
    							  "\r\n" . "__dbg_func('fopen', '', __FILE__, __LINE__, __FUNCTION__);$1",
    							  "\r\n" . "__dbg_func('fwrite', '', __FILE__, __LINE__, __FUNCTION__);$1", 
    							  "\r\n" . "__dbg_func('fputs', '', __FILE__, __LINE__, __FUNCTION__);$1",
    							  "\r\n" . "__dbg_func('fread', '', __FILE__, __LINE__, __FUNCTION__);$1",
    							  "\r\n" . "__dbg_func('file', '', __FILE__, __LINE__, __FUNCTION__);$1",
    							  "\r\n" . "__dbg_func('readfile', '', __FILE__, __LINE__, __FUNCTION__);$1",
    							  "\r\n" . "__dbg_func('fsockopen', '', __FILE__, __LINE__, __FUNCTION__);$1",
    							  "\r\n" . "__dbg_func('file_get_contents', '', __FILE__, __LINE__, __FUNCTION__);$1",
    							  "\r\n" . "__dbg_func('extract', '', __FILE__, __LINE__, __FUNCTION__);$1",
    							  "\r\n" . "__dbg_func('parse_str', '', __FILE__, __LINE__, __FUNCTION__);$1");
    					
    		foreach ($this->files as $file) {
    			$content = file_get_contents($file);
    			if (!$content) continue;
    			
    			if ($this->mode == 'insert') 
    				if (strpos($content, '### included code ###')) continue;
    			
    			if ($this->mode == 'insert') {
    				$code = preg_replace('/\t/', '', $code);
    
    				$content = preg_replace($patterns, "\r\n" . '__dbg("\\\\$2", __FILE__, __LINE__, __FUNCTION__);$1$2$3', $content);
    				$content = preg_replace($patternsFunc, $replaceFunc, $content);
    				$content = $code . $content;
    			} elseif ($this->mode == 'remove') {
    				$content = preg_replace('/<\?php\s+\/\/### included code ###[^#]+### end code ###\?>\r\n/', '', $content);
    				
    				$content = preg_replace('/\r\n__dbg[^\n]+\);/', '', $content);
    				$content = preg_replace('/\r\n__dbg_func[^\n]+\);/', '', $content);
    			}
    			$handle = fopen($file, 'w+');
    			fwrite($handle, $content);
    			fclose($handle);
    		}
    	}
    	
    	public function getParam($argv) {
    		if (!isset($argv[1])) $argv[1] = '';
    		
    		switch ($argv[1]) {
    			case 'insert': { $this->mode = 'insert'; echo "[+] Inserting code...\r\n";break; }
    			case 'remove': $this->mode = 'remove'; echo "[-] Removing code...\r\n"; break;
    			default: echo 'php ' . $argv[0] . " insert or remove\r\n"; die;
    		}
    	}
    	
    	public function __construct($argv) {
    		$this->self = $argv[0];
    
    		$this->showInfo();
    		$this->getParam($argv);
    		$this->getAllDirs();
    		$this->getAllFiles();
    		$this->includeCode();
    		echo "[!] Done\r\n";
    	}
    }
    
    $GPCS_Tracer = new GPCS_Tracer($argv);
    ?>
     
    #1 xek, 2 Jan 2012
    Last edited: 4 Jan 2012
    1 person likes this.