-
-
Save divinity76/544d7cadd3e88e057ea3504cb8b3bf7e to your computer and use it in GitHub Desktop.
<?php | |
declare(strict_types = 1); | |
// header ( "content-type: text/plain;charset=utf8" ); | |
// https://github.com/divinity76/hhb_.inc.php/blob/master/hhb_.inc.php | |
require_once ('hhb_.inc.php'); | |
function loginGmail(string $username, string $password, string $recoveryEmailChallengeAnswer) : \hhb_curl | |
{ | |
$hc = new hhb_curl('', true); | |
$hc->setopt_array(array( | |
CURLOPT_TIMEOUT => 20, // i just have a shitty connection :( | |
CURLOPT_CONNECTTIMEOUT => 10 | |
)); | |
if (0) { | |
$hc->setopt_array(array( | |
CURLOPT_USERAGENT => 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) CriOS/56.0.2924.75 Mobile/14E5239e Safari/602.1' | |
)); | |
} | |
$html = $hc->exec('https://accounts.google.com/signin')->getStdOut(); | |
//hhb_var_dump ( $hc->getStdErr (), $hc->getStdOut (), $inputs ) & die(); | |
$domd = @DOMDocument::loadHTML($html); | |
$inputs = getDOMDocumentFormInputs($domd, true, false)['gaia_loginform']; | |
//hhb_var_dump ( $hc->getStdErr (), $hc->getStdOut (), $inputs ) & die(); | |
$loginUrl = $domd->getElementById("gaia_loginform")->getAttribute("action"); | |
$inputs['Email'] = $username; | |
$html = $hc->setopt_array(array( | |
CURLOPT_POST => 1, | |
CURLOPT_POSTFIELDS => http_build_query($inputs), | |
CURLOPT_URL => $loginUrl | |
))->exec()->getStdOut(); | |
//hhb_var_dump ( $hc->getStdErr (), $hc->getStdOut (), $inputs ) & die(); | |
// without this next GET, login will block you for "not running javascript".. luckily v seems to only be a random number. | |
$hc->setopt_array(array( | |
CURLOPT_HTTPGET => 1, | |
CURLOPT_URL => 'https://accounts.youtube.com/accounts/CheckConnection?pmpo=https%3A%2F%2Faccounts.google.com&' . http_build_query( | |
array( | |
'v' => rand(),// ??? | |
'timestamp' => ((int)(microtime(true) * 1000)), | |
) | |
), | |
))->exec(); | |
//hhb_var_dump ( $hc->getStdErr (), $hc->getStdOut (), $inputs ) & die(); | |
$domd = @DOMDocument::loadHTML($html); | |
$inputs = getDOMDocumentFormInputs($domd, true, false)['gaia_loginform']; | |
// hhb_var_dump ( $hc->getStdErr (), $hc->getStdOut (), $inputs ); | |
$loginUrl = $domd->getElementById("gaia_loginform")->getAttribute("action"); | |
$inputs['Passwd'] = $password; | |
{ | |
// a couple of missing ones added by javascript... | |
$inputs['continue'] = 'https://accounts.google.com/ManageAccount'; | |
$inputs['checkedDomains'] = 'youtube'; | |
$inputs['checkConnection'] = 'youtube:356:1'; | |
$inputs['rip'] = 1; | |
$inputs['pstMsg'] = 1; | |
$inputs['rmShown'] = 1; | |
$inputs['bgresponse'] = 'my_massive_dong';//bgresponse MUST exist, MUST have content, and the content CAN NOT include the phrase "js_disabled" | |
} | |
try { | |
$starttime = microtime(true); | |
$html = $hc->setopt_array(array( | |
CURLOPT_POST => 1, | |
CURLOPT_POSTFIELDS => http_build_query($inputs), | |
CURLOPT_URL => $loginUrl | |
))->exec()->getStdOut(); | |
//hhb_var_dump($hc->getStdErr(), $hc->getStdOut(), $inputs) & die(); | |
} | |
finally { | |
// hhb_var_dump ( $hc->getStdErr (), $hc->getStdOut (), $inputs, (microtime ( true ) - $starttime) ) & die (); | |
} | |
$loginErrorText = ''; | |
$domd = @DOMDocument::loadHTML($html); | |
$xp = new DOMXPath($domd); | |
$refresh = $xp->query("//meta[@http-equiv='refresh']"); | |
if (!$refresh->length) { | |
hhb_var_dump($hc->getStdErr(), $hc->getStdOut(), $inputs);; | |
throw new \RuntimeException("login failed - google did not try to redirect us after sending password!"); | |
} | |
$refresh = $refresh->item(0); | |
$content = $refresh->getAttribute("content"); | |
if (false === stripos($content, 'accounts.google.com/ManageAccount')) { | |
throw new \RuntimeException("login failed - google did not try to redirect us to account management page after sending password!"); | |
} | |
$nextUrl; | |
if (!preg_match('/(https\:\/\/[^\;]+)/', $content, $nextUrl)) { | |
throw new \LogicException("wtf??? should never happen"); | |
} | |
//hhb_var_dump($nextUrl) & die(); | |
$nextUrl = $nextUrl[1]; | |
$html = $hc->setopt_array(array( | |
CURLOPT_URL => $nextUrl, | |
CURLOPT_HTTPGET => 1, | |
))->exec()->getStdOut(); | |
// TODO: some way to verify that we're actually logged in now. | |
//hhb_var_dump($hc->getStdErr(), $hc->getStdOut(), $inputs, (microtime(true) - $starttime)) & die(); | |
$html = $hc->setopt_array(array( | |
CURLOPT_URL => 'https://gmail.com', | |
CURLOPT_HTTPGET => 1, | |
))->exec()->getStdOut(); | |
//hhb_var_dump($hc->getStdErr(), $hc->getStdOut(), $inputs, (microtime(true) - $starttime)) & die(); | |
$domd = @DOMDocument::loadHTML($html); | |
$xp = new DOMXPath($domd); | |
$authChallenge = $domd->getElementById("challengePickerList"); | |
if (null !== $authChallenge) { | |
// gotdammit... got an auth challenge page, asking you to choose a challenge | |
$loginErrorText .= ' - got an auth challenge page, asking you to choose a challenge: ' . trim($authChallenge->textContent); | |
// TODO: automatically select "provide recovery email" here instead of throwing a login error exception. | |
} else { | |
if (false !== stripos($html, 'Enter recovery email') && null !== ($authChallenge = $domd->getElementById("challenge"))) { | |
// got an auth challenge for providing recovery email.. | |
// luckily, we can automatically recover from this. | |
$inputs = getDOMDocumentFormInputs($domd, true, false)['challenge']; | |
assert(array_key_exists('email', $inputs)); | |
$inputs['email'] = $recoveryEmailChallengeAnswer; | |
$url = $authChallenge->getAttribute("action"); | |
if (!parse_url($url, PHP_URL_HOST)) { | |
$url = 'https://' . parse_url($hc->getinfo(CURLINFO_EFFECTIVE_URL), PHP_URL_HOST) . $url; | |
} | |
$html = $hc->setopt_array(array( | |
CURLOPT_POST => 1, | |
CURLOPT_POSTFIELDS => http_build_query($inputs), | |
CURLOPT_URL => $url | |
))->exec()->getStdOut(); | |
$domd = @DOMDocument::loadHTML($html); | |
$xp = new DOMXPath($domd); | |
// TODO: detect incorrect recovery email supplied error here. | |
} | |
} | |
unset($authChallenge); | |
if (!empty($loginErrorText)) { | |
throw new \RuntimeException('errors loggin in: ' . $loginErrorText); | |
} else { | |
// logged in! :D | |
} | |
// now we need to enable HTML view, it's a <form> POST request, but we can't use getDOMDocumentFormInputs (bug?) | |
if (0) { | |
foreach ($xp->query("//form") as $form) { | |
hhb_var_dump($domd->saveHTML($form)); | |
} | |
die(); | |
} | |
$res = $xp->query('//form[@id="null" and contains(@action,"zy=d")]'); | |
if ($res->length !== 1) { | |
$str = 'failed to find HTML version request form!'; | |
hhb_var_dump($str, $hc->getStdErr(), $hc->getStdOut(), $inputs); // & die (); | |
throw new \RuntimeException($str); | |
} | |
$form = $res->item(0); | |
$url = $form->getAttribute("action"); | |
if (!parse_url($url, PHP_URL_HOST)) { | |
$url = $hc->getinfo(CURLINFO_EFFECTIVE_URL) . $url; | |
} | |
// hhb_var_dump ( $url ) & die (); | |
$inputs = []; | |
foreach ($form->getElementsByTagName("input") as $input) { | |
$name = $input->getAttribute("name"); | |
if (empty($name)) { | |
continue; | |
} | |
$inputs[$name] = $input->getAttribute("value"); | |
} | |
//hhb_var_dump($inputs) & die(); | |
$html = $hc->setopt_array(array( | |
CURLOPT_POST => 1, | |
CURLOPT_POSTFIELDS => http_build_query($inputs), | |
CURLOPT_URL => $url | |
))->exec()->getStdOut(); | |
//hhb_var_dump($hc->getStdErr(), $hc->getStdOut(), $inputs); // & die (); | |
return $hc; | |
} | |
function rightTrim($str, $needle, $caseSensitive = true) { | |
$strPosFunction = $caseSensitive ? "strpos" : "stripos"; | |
if ($strPosFunction ( $str, $needle, strlen ( $str ) - strlen ( $needle ) ) !== false) { | |
$str = substr ( $str, 0, - strlen ( $needle ) ); | |
} | |
return $str; | |
} | |
function getDOMDocumentFormInputs(\DOMDocument $domd, bool $getOnlyFirstMatches = false, bool $getElements = true): array { | |
// :DOMNodeList? | |
if (! $getOnlyFirstMatches && ! $getElements) { | |
throw new \InvalidArgumentException ( '!$getElements is currently only implemented for $getOnlyFirstMatches (cus im lazy and nobody has written the code yet)' ); | |
} | |
$forms = $domd->getElementsByTagName ( 'form' ); | |
$parsedForms = array (); | |
$isDescendantOf = function (\DOMNode $decendant, \DOMNode $ele): bool { | |
$parent = $decendant; | |
while ( NULL !== ($parent = $parent->parentNode) ) { | |
if ($parent === $ele) { | |
return true; | |
} | |
} | |
return false; | |
}; | |
// i can't use array_merge on DOMNodeLists :( | |
$merged = function () use (&$domd): array { | |
$ret = array (); | |
foreach ( $domd->getElementsByTagName ( "input" ) as $input ) { | |
$ret [] = $input; | |
} | |
foreach ( $domd->getElementsByTagName ( "textarea" ) as $textarea ) { | |
$ret [] = $textarea; | |
} | |
foreach ( $domd->getElementsByTagName ( "button" ) as $button ) { | |
$ret [] = $button; | |
} | |
return $ret; | |
}; | |
$merged = $merged (); | |
foreach ( $forms as $form ) { | |
$inputs = function () use (&$domd, &$form, &$isDescendantOf, &$merged): array { | |
$ret = array (); | |
foreach ( $merged as $input ) { | |
// hhb_var_dump ( $input->getAttribute ( "name" ), $input->getAttribute ( "id" ) ); | |
if ($input->hasAttribute ( "disabled" )) { | |
// ignore disabled elements? | |
continue; | |
} | |
$name = $input->getAttribute ( "name" ); | |
if ($name === '') { | |
// echo "inputs with no name are ignored when submitted by mainstream browsers (presumably because of specs)... follow suite?", PHP_EOL; | |
continue; | |
} | |
if (! $isDescendantOf ( $input, $form ) && $form->getAttribute ( "id" ) !== '' && $input->getAttribute ( "form" ) !== $form->getAttribute ( "id" )) { | |
// echo "this input does not belong to this form.", PHP_EOL; | |
continue; | |
} | |
if (! array_key_exists ( $name, $ret )) { | |
$ret [$name] = array ( | |
$input | |
); | |
} else { | |
$ret [$name] [] = $input; | |
} | |
} | |
return $ret; | |
}; | |
$inputs = $inputs (); // sorry about that, Eclipse gets unstable on IIFE syntax. | |
$hasName = true; | |
$name = $form->getAttribute ( "id" ); | |
if ($name === '') { | |
$name = $form->getAttribute ( "name" ); | |
if ($name === '') { | |
$hasName = false; | |
} | |
} | |
if (! $hasName) { | |
$parsedForms [] = array ( | |
$inputs | |
); | |
} else { | |
if (! array_key_exists ( $name, $parsedForms )) { | |
$parsedForms [$name] = array ( | |
$inputs | |
); | |
} else { | |
$parsedForms [$name] [] = $tmp; | |
} | |
} | |
} | |
unset ( $form, $tmp, $hasName, $name, $i, $input ); | |
if ($getOnlyFirstMatches) { | |
foreach ( $parsedForms as $key => $val ) { | |
$parsedForms [$key] = $val [0]; | |
} | |
unset ( $key, $val ); | |
foreach ( $parsedForms as $key1 => $val1 ) { | |
foreach ( $val1 as $key2 => $val2 ) { | |
$parsedForms [$key1] [$key2] = $val2 [0]; | |
} | |
} | |
} | |
if ($getElements) { | |
return $parsedForms; | |
} | |
$ret = array (); | |
foreach ( $parsedForms as $formName => $arr ) { | |
$ret [$formName] = array (); | |
foreach ( $arr as $ele ) { | |
$ret [$formName] [$ele->getAttribute ( "name" )] = $ele->getAttribute ( "value" ); | |
} | |
} | |
return $ret; | |
} |
$test = loginGmail('xxx@xxx.net', 'sumdumpassword', 'recovery@xxx.com');
var_dump($test->getStdOut());
not working bro
@manusia21 and @jamenlang and @eray989 - google made it harder to log in, was difficult but now the code is updated and working ( 2019-02-08 ) - also @jamenlang's code is correct, but note that it requres hhb_curl from https://github.com/divinity76/hhb_.inc.php/blob/master/hhb_.inc.php
not working sir
how to use?
call email | pass
not working sir
login failed - google did not try to redirect us after sending password!
Not work
You're trying to log into a browser or app where we can't protect your account.
Use a different browser.
@sutorrinaldi @Nzt2 Google changed the login system again,
i can probably fix it for $50, but since i don't need it myself now, i won't waste time updating it for free.
@sutorrinaldi @Nzt2 Google changed the login system again,
i can probably fix it for $50, but since i don't need it myself now, i won't waste time updating it for free.
can you write me telegram or skype i can pay you if you can fix problem ? cryptr.org@gmail.com
Please add usage example