Here's your deobfuscated file, note that I do not give guarantees, there was some manual work done and I may have removed important lines, more on that below:
<?
if (isset($_SESSION['id'])) {
header('Location: ../');
exit();
}
$message = '';
if (isset($_GET['data']) && isset($_GET['a'])) {
$id = check($_GET['a'], "int");
$STH = $pdo->prepare("SELECT `id`, `login`, `email` FROM `users` WHERE `id`=:id LIMIT 1");
$STH->setFetchMode(PDO::FETCH_OBJ);
$STH->execute(array(
':id' => $id
));
$row = $STH->fetch();
if (empty($row->id)) {
show_error_page();
}
if ($_GET['data'] != md5($row->id . $conf->code . $row->email . date("Y-m-d"))) {
$message = '<p class=\'text-danger\'>' . $messages['Link_not_active'] . '</p>';
} else {
$password = crate_pass(7, 1);
$password2 = convert_password($password, $conf->salt);
$STH = $pdo->prepare("UPDATE `users` SET `password`=:password WHERE `id`=:id LIMIT 1");
if ($STH->execute(array(
':password' => $password2,
':id' => $id
)) == '1') {
include_once "inc/notifications.php";
$letter = recovery_letter($conf->name, $row->login, $password);
sendmail($row->email, $letter['subject'], $letter['message'], $pdo);
$message = '<p class=\'text-success\'>' . $messages['Recovery_pass1'] . $row->email . $messages['Recovery_pass2'] . '</p>';
write_log("User reinstated pass #" . $row->email);
} else {
$message = '<p class=\'text-danger\'>' . $messages['Error_page'] . '</p>';
}
}
}
$tpl->load_template('elements/title.tpl');
$tpl->set("{title}", $page->title);
$tpl->set("{name}", $conf->name);
$tpl->compile('title');
$tpl->clear();
$tpl->load_template('head.tpl');
$tpl->set("{title}", $tpl->result['title']);
$tpl->set("{site_name}", $conf->name);
$tpl->set("{image}", $page->image);
$tpl->set("{robots}", $page->robots);
$tpl->set("{type}", $page->kind);
$tpl->set("{description}", $page->description);
$tpl->set("{keywords}", $page->keywords);
$tpl->set("{url}", $page->full_url);
$tpl->set("{other}", '');
$tpl->set("{token}", $token);
$tpl->set("{cache}", $conf->cache);
$tpl->set("{template}", $conf->template);
$tpl->set("{site_host}", $site_host);
$tpl->compile('content');
$tpl->clear();
$menu = $tpl->get_menu($pdo);
$nav = array(
$PI->to_nav('main', 0, 0),
$PI->to_nav('recovery', 1, 0)
);
$nav = $tpl->get_nav($nav, 'elements/nav_li.tpl');
include_once "inc/not_authorized.php";
$tpl->load_template('/index/recovery.tpl');
$tpl->set("{site_host}", $site_host);
$tpl->set("{template}", $conf->template);
$tpl->set("{message}", $message);
$tpl->compile('content');
$tpl->clear();
I wrote a small Python script to get rid of the annoying round()
calls. It simply uses a regex to find all non-nested round(...)
calls, dumps a small PHP script, runs PHP on it and retrieves the output because I didn't trust Python's round
to be perfectly equal in corner cases.
The script:
#!/usr/bin/python
import subprocess
import re
import sys
def php_eval(code):
code = "<?php echo(" + code + "); ?>"
open("/tmp/eval","w").write(code)
return subprocess.check_output(["php","/tmp/eval"]).decode("ascii")
def deob(fname):
obf = open(fname,"r").read()
# while True:
# m = re.search(r'\[round.+?\]',obf)
# if m:
# s = m.group(0)
# print("Matched %s" % s)
# repl = php_eval(s[1:-1])
# print("Replacing %s with %s" % (s,repl))
# obf = obf.replace(s,"["+repl+"]")
# else:
# break
# while True:
# m = re.search(r'\$GLOBALS\[\'_174350175_\'\]\[\d+?\]',obf)
# if m:
# s = m.group(0)
# obf = obf.replace(s,"round")
# else:
# break
while True:
m = re.search(r'round\([^\(]+?\)',obf)
if m:
s = m.group(0)
repl = php_eval(s)
print("Replacing %s with %s" % (s,repl))
obf = obf.replace(s,repl)
else:
break
return obf
plain = deob(sys.argv[1])
open(sys.argv[2],"w").write(plain)
Then I threw the code into a PHP beautifier: http://www.phpformatter.com/
Then the manual part.
There are some patterns the obfuscator creates:
while (3171 - 3171)
bin2hex($seneiuhtrbbit, $likgfowocfbgko, $_SESSION);
while loops that never execute.
if ((3165 ^ 3165) && preg_split($seneiuhtrbbit))
fgetss($pdo, $nav);
if clauses that never execute because the 1st part evaluates to false already.
(3253 - 3253 + 3158 - 3158) ? strnatcmp($pdo, $letter, $password) : mt_rand(806, 3253);
ternary operator usage that effectively is a nop (condition evaluates to false, making it call mt_rand
)
And some others. I removed those manually, which gives the above script.
If you want to deobfuscate the route.php
, you may want to uncomment the blocks in above script, as it adds another layer of rounds
but I didn't continue. You would also need to text-replace the function calls back in from the 2nd GLOBAL array.