Re: memory usage/release & GC

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Dec 31, 2010 at 2:02 AM, Peter Lind <peter.e.lind@xxxxxxxxx> wrote:
>
> On Dec 31, 2010 6:20 AM, "Tommy Pham" <tommyhp2@xxxxxxxxx> wrote:
>>
>> Hi folks,
>>
>> With the recent thread about password & security, I wrote a small quick
>> script to generate a random or all possible passwords based on certain
>> parameters for a brute force use. ÂOn a very long running execution for a
>> complex password in length with full use of the keys (94 characters),
>> including upper case, the script seems to consumes more memory (shown in
>> Windows task manager) as time progress. ÂBelow are snippets from the
>> script
>> file that does the workload:
>>
>> while (!$this->isMax())
>> {
>> Â Â Â Âfor ($b = 0; $b <= $this->pwdLength; $b++)
>> Â Â Â Â{
>> Â Â Â Â Â Â Â Âif ($this->counter[$b] < $this->max)
>> Â Â Â Â Â Â Â Â{
>> Â Â Â Â Â Â Â Â Â Â Â Â$this->pwd[$b] =
>> $this->charList[$this->counter[$b]];
>> Â Â Â Â Â Â Â Â Â Â Â Â$this->counter[$b]++;
>> Â Â Â Â Â Â Â Â Â Â Â Âbreak;
>> Â Â Â Â Â Â Â Â}
>> Â Â Â Â Â Â Â Âelse
>> Â Â Â Â Â Â Â Â{
>> Â Â Â Â Â Â Â Â Â Â Â Â$this->counter[$b] = 1;
>> Â Â Â Â Â Â Â Â Â Â Â Â$this->pwd[$b] = $this->charList[0];
>> Â Â Â Â Â Â Â Â}
>> Â Â Â Â}
>> }
>>
>> private function isMax()
>> {
>> Â Â Â Âfor ($a = $this->pwdLength-1; $a>=0; $a--)
>> Â Â Â Â{
>> Â Â Â Â Â Â Â Âif ($this->counter[$a] < $this->max) return false;
>> Â Â Â Â}
>> Â Â Â Âreturn true;
>> }
>>
>> Could someone please tell me why the above code consumes additional memory
>> as time progress for the execution of the while loop? ÂResearching PHP GC
>> on
>> google didn't shed light on problem. ÂGenerating all possible combinations
>> for 20 length with 94 possibilities each, the script easily consumes more
>> than 1GB RAM in few minutes. ÂBTW, gc_enabled() reports on.
>>
>> Thanks,
>> Tommy
>>
>>
>
> Are you storing or throwing away the passwords? Also, lots of code is
> missing from that post, no idea if you've got a memory leak in the rest of
> the code
>
> Regards
> Peter

Hi Peter,

Thanks for the reply.  After I sent the e-mail last night, I did a
little debugging.  As it turns out, xdebug was the culprit.  I gotta
remember to disable xdebug while coding...  Anyway, here's the full
code.  Anyone is welcome to use it.

$timeStart = microtime(true);

//set_time_limit(0);
ini_set('max_execution_time', 0);
ini_set('memory_limit', -1);
class PwdGen
{
	const ALPHA_LOWER = 'abcdefghijklmnopqrstuvwxyz';
	const ALPHA_UPPER = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
	const NUMERIC = '0123456789';
	const SPECIALS = '!@#$%^&*()`~-_=+[]\{}|;:\'",./<>?';
	private $chars;
	private $charList;
	private $max;
	private $pwdLength;
	private $pwdList; // array
	private $pwd;
	private $counter; // array
	private $insertDb = false;

	public function __construct($pwdLength = 8, $useUpper = true,
$useNumeric = true, $useSpecials = true, $insertDb = true, $specials =
'')
	{
		$this->insertDb = $insertDb;
		$this->pwdLength = intval($pwdLength);
		$this->chars = self::ALPHA_LOWER;
		if ($useUpper) $this->chars .= self::ALPHA_UPPER;
		if ($useNumeric) $this->chars .= self::NUMERIC;
		if ($useSpecials) $this->chars .= empty($specials) ? self::SPECIALS
: $specials;
	}
	private function init()
	{
		$this->charList = str_split($this->chars, 1);
		$this->max = sizeof($this->charList);
		$this->pwd = str_split(str_repeat($this->charList[0], $this->pwdLength), 1);

		$this->pwdList = array(); // array
		$this->counter = array();
		for ($a = 0; $a < $this->pwdLength; $a++)
			$this->counter[$a] = 1;
		$this->counter[$this->pwdLength-1] = 0;
	}
	public function setPasswordLength($pwdLength)
	{
		$this->pwdLength = intval($pwdLength);
	}
	public function setUseChars($useUpper = true, $useNumeric = true,
$useSpecials = true, $specials = '')
	{
		$this->chars = self::ALPHA_LOWER;
		if ($useUpper) $this->chars .= self::ALPHA_UPPER;
		if ($useNumeric) $this->chars .= self::NUMERIC;
		if ($useSpecials) $this->chars .= empty($specials) ? self::SPECIALS
: $specials;
	}
	public function getRandom()
	{
		$this->init();
		for ($a = 0; $a < $this->pwdLength; $a++)
			$this->pwd[$a] = $this->charList[rand(0, $this->max - 1)];
		$pwd = implode('', $this->pwd);
		$output = $this->max.': '.$this->chars.' ('.pow($this->max,
$this->pwdLength).') '.PHP_EOL.$pwd.PHP_EOL;
		return $output;
	}
	public function getAll($continue = true)
	{
		$this->init();
		$sql = 'INSERT INTO `password`(`guid`, `length`, `password`,
`counter`, `date_added`) VALUES (BinUUID(), '.$this->pwdLength.', ?,
?, now())';

		$pwd = '';
		$counter = '';
		$output = $this->max.': '.$this->chars.' ('.pow($this->max,
$this->pwdLength).')'.PHP_EOL;

		if ($this->insertDb)
		{
			$db = new mysqli('127.0.0.1', 'user', 'pass', 'brute_force');
			if (mysqli_connect_errno()) {
			    printf("Connect failed: %s\n", mysqli_connect_error());
			    exit();
			}

			$stmt = $db->prepare($sql);
			if ($stmt === false) {
			    printf("Prepare failed: %s\n", $db->error);
			    $stmt->close();
			    $db->close();
			    exit();
			}
			if ($stmt->bind_param('ss', $pwd, $counter) === false)
	 		{
			    printf("Bind Param failed: %s\n", $stmt->error);
			    $stmt->close();
			    $db->close();
			    exit();
	 		}
		}
		while (!$this->isMax())
		{
			for ($b = $this->pwdLength - 1; $b >= 0; $b--)
			{
				if ($this->counter[$b] < $this->max)
				{
					$this->pwd[$b] = $this->charList[$this->counter[$b]];
					$this->counter[$b]++;
					break;
				}
				else
				{
					$this->counter[$b] = 1;
					$this->pwd[$b] = $this->charList[0];
				}
			}

			$pwd = implode('', $this->pwd);
//			$this->pwdList[] = $pwd;

			if ($this->insertDb)
			{
				//$counter = json_encode($this->counter);
				$counter = '[';
				for ($c = 0; $c < $this->pwdLength; $c++)
				{
					$counter .= sprintf('%02d', $this->counter[$c]);
					if ($c+1 < $this->pwdLength) $counter .= ',';
				}
				$counter .= ']';
				if ($stmt->execute() === false)
				{
				    printf("Execute failed: %s\n", $stmt->error);
				    $stmt->close();
				    $db->close();
				    exit();
				}
			}
//			$output .= $pwd.' ';
//			$output .= implode(':', $this->counter).' ';
//			$output .= PHP_EOL;
		}
		if ($this->insertDb)
		{
			$stmt->close();
			$db->close();
		}
		return $output;
	}
	private function isMax()
	{
		for ($m = 0; $m < $this->pwdLength; $m++)
			if ($this->counter[$m] < $this->max) return false;

		return true;
	}
}
$output = '<pre>';
$pg = new PwdGen();

$dbMax = 25;

if (!empty($_GET['min']) && !empty($_GET['max']))
{
	$min = intval($_GET['min']);
	$max = intval($_GET['max']);
	if ($max > $dbMax) $max = $dbMax;
} else
{
	$min = 4;
	$max = 5;
}

if (!empty($_GET['get']) && $_GET['get'] == 'all')
{
	if (empty($_GET['length']))
	{
		for ($i = $min; $i <= $max; $i++)
		{
			$_POST['length'] = $i;
			$pg->setPasswordLength($i);
			$output .= $pg->getAll();
		}
	}
	else
	{
		$i = intval($_GET['length']);
		$_POST['length'] = $i;
		$pg->setPasswordLength($i);
		$output .= $pg->getAll();
	}
}
else
{
	if (empty($_POST['useUpper'])) $useUpper = false;
	else $useUpper = true;
	if (empty($_POST['useNumeric'])) $useNumeric = false;
	else $useNumeric = true;
	if (empty($_POST['useSpecials'])) $useSpecials = false;
	else $useSpecials = true;
	if (empty($_POST['specials'])) $specials = '';
	else $specials = trim($_POST['specials']);
	$pg->setUseChars($useUpper, $useNumeric, $useSpecials, $specials);

	if (!empty($_POST['length'])) $pg->setPasswordLength(intval($_POST['length']));
	$output .= $pg->getRandom();
}

$lengthList = 'Length: <select size="1" name="length">';
for ($l = 3; $l <= $dbMax; $l++)
	if (!empty($_POST['length']) && $_POST['length'] == $l) $lengthList
.= '<option selected="selected">'.$l.'</option>';
	else $lengthList .= '<option>'.$l.'</option>';
$lengthList .= '</select>';

$htmlForm = '<form method="post" enctype="multipart/form-data">'.PHP_EOL;
$htmlForm .= 'Upper case: <input type="checkbox" checked="checked"
name="useUpper" /> '.PHP_EOL;
$htmlForm .= 'Numbers: <input type="checkbox" checked="checked"
name="useNumeric" /> '.PHP_EOL;
$htmlForm .= 'Specials - symbols: <input type="checkbox"
checked="checked" name="useSpecials" /> '.PHP_EOL;
$htmlForm .= 'Custom: <input name="specials" maxlength="30" size="30"
value="'.$specials.'" /> '.PHP_EOL;
$htmlForm .= $lengthList.PHP_EOL;
$htmlForm .= '<input type="submit" value="Get Random" /></form>'.PHP_EOL;
$htmlForm .= '<form method="get"
enctype="application/x-www-form-urlencoded">'.PHP_EOL;
$htmlForm .= '<input name="get" type="hidden" value="all" /> '.PHP_EOL;
$htmlForm .= $lengthList.PHP_EOL;
$htmlForm .= '<input type="submit" value="Get All" /></form>'.PHP_EOL;

$timeEnd = microtime(true);
$timeExec = $timeEnd - $timeStart;
$output .= PHP_EOL.PHP_EOL.getmypid().' executed: '.$timeExec.PHP_EOL.'</pre>';

echo '<html><body>'.$htmlForm.$output.'</body></html>';


Disclaimer:  The above code is intended for scientific research.
You're responsible for your action.

Happy New Year!!
Tommy

-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php




[Index of Archives]     [PHP Home]     [Apache Users]     [PHP on Windows]     [Kernel Newbies]     [PHP Install]     [PHP Classes]     [Pear]     [Postgresql]     [Postgresql PHP]     [PHP on Windows]     [PHP Database Programming]     [PHP SOAP]

  Powered by Linux