Xcache баг-трекер декомпилятора

Статус
В этой теме нельзя размещать новые ответы.
2) частично. Этим я пока занялся, несмотря на описание всего что только можно, нет интересующихся, то пока исходники не выкладываю, только готовое решение (делать никто не хочет, а вот опарыши с троянами и прочим барахлом замечены, поэтому исходники по запросу и только тем кто реально хочет этим заниматься и может помочь).
3) Скрипт для реверса есть в стандартной поставки кеша, прочти первое сообщение. Если знаешь php то можешь начать его капать. Это обычный скрипт на пехе.
И тут крайне нужна помощь любая. Так как есть проблемы в сложных конструкциях. Нужно до ума доводить.
4) Нет нельзя
 
Небольшая вариация на тему декомпиляции.

Ниже сборка для декомпиляции байткода bcompiler из PHP DevelStudio



Огромная благодарность sidxx55 за терпение и проделанный труд.
 
PHP:
while ($elem == '' && count($parts)) { }
Пофиксил обработку данной конструкции. На самом деле, там не столько баг обработки while (хотя эту обработку тоже патчить пришлось), сколько недоработка в логике recognizeAndDecompileClosedBlocks, из-за которой для данного примера некоректно определялся конец блока по ['jmpins'] (некоректно относительно практически идентичной по опкодам конструкции - if ($elem == '' && count($parts)) { } ).
PHP:
for ($i = $starti; $i <= $range[1]; ) {
if (!empty($opcodes[$i]['jmpins']) || !empty($opcodes[$i]['jmpouts'])) {
$blockFirst = $i;
заменить на
PHP:
for ($i = $starti; $i <= $range[1]; ) {
if ((!empty($opcodes[$i]['jmpins']) && $i > $starti) || !empty($opcodes[$i]['jmpouts'])) { // << строка 1176 (фиксим логику =) )
$blockFirst = $i;
и в обработчике while
PHP:
&& $lastOp['opcode'] == XC_JMP && !empty($lastOp['jmpouts'])
&& $lastOp['jmpouts'][0] == $range[0]) {
$this->removeJmpInfo($EX, $firstJmp);
заменить на
PHP:
&& $lastOp['opcode'] == XC_JMP && !empty($lastOp['jmpouts'])
&& $lastOp['jmpouts'][0] < $range[0]) { // << строка 1115 (здесь достаточно зафиксировать переход по коду назад, а не вперед, как в конструкции if() )
$this->removeJmpInfo($EX, $firstJmp);
[/spoil]
Так же поправил обработчики опкодов XC_ISSET_ISEMPTY_DIM_OBJ и XC_ISSET_ISEMPTY_PROP_OBJ, добавив преобразование объекта в строку:
[spoil]
PHP:
$rvalue = $container . "->" . unquoteVariableName($dim);
меняем на
PHP:
$rvalue = str($container) . "->" . unquoteVariableName($dim); // << строка 1697 (конструкции вида $controller->$prop; )
и
PHP:
$rvalue = $container . '[' . str($dim) .']';
на
PHP:
$rvalue = str($container) . '[' . str($dim) .']'; // << строка 1700  (конструкции вида $_SERVER['PHP_SELF'] )
Надеюсь эта информация актуальна, потому что хайды в этой теме я не вижу. И спасибо за замечательный инструмент =)
 
внес в класс все патчи на на эту дату с подписями тех кто их делал, благодарю тех кто в этом участвует, в хайдах правок нет правки открытые
вот что у нас получилось на этот день
кстати dima2k почему то wile не сработал может я его не туда засунул,;), внутри функции он попрежнеу не хочет работать а отдельно работает, IF работает в 2 случаях как отдельно так и внутри функций
 

Вложения

  • Decompiler.class09012013.rar
    15,1 KB · Просмотры: 32
  • Decompiler.class10012013.rar
    15 KB · Просмотры: 31
внес в класс все патчи на на эту дату с подписями тех кто их делал, благодарю тех кто в этом участвует, в хайдах правок нет правки открытые
вот что у нас получилось на этот день
кстати dima2k почему то wile не сработал может я его не туда засунул,;), внутри функции он попрежнеу не хочет работать а отдельно работает, IF работает в 2 случаях как отдельно так и внутри функций
Не туда. Сейчас засунуто в
PHP:
 // {{{ do/while
if ($lastOp['opcode'] == XC_JMPNZ && !empty($lastOp['jmpouts'])
&& $lastOp['jmpouts'][0] < $range[0]) { //dima2k fix
, а надо ниже, в
PHP:
// {{{ while
if (isset($firstJmpOp)
&& $firstJmpOp['opcode'] == XC_JMPZ
&& $firstJmpOp['jmpouts'][0] > $range[1]
&& $lastOp['opcode'] == XC_JMP && !empty($lastOp['jmpouts'])
&& $lastOp['jmpouts'][0] < $range[0]) {  //dima2k fix
а измененный вернуть в первоначальный вид:
PHP:
 // {{{ do/while
if ($lastOp['opcode'] == XC_JMPNZ && !empty($lastOp['jmpouts'])
&& $lastOp['jmpouts'][0] == $range[0]) {
 
нужна правка именно в этой конструкции внутри функции, я поправился, попробуй у себя
PHP:
function readMailboxParent($haystack, $needle) {
    if ($needle == '') {
        $ret = '';
    } else {
        $parts = explode($needle, $haystack);
        $elem = array_pop($parts);
/////////////////////////////////////////////////////////////
        while ($elem == '' && count($parts)) {
            $elem = array_pop($parts);
        }
        $ret = join($needle, $parts);
    }
    return( $ret );
}
последний атач правильный как ты говоришь, но внутри функции (function readMailboxParen) не работает
тут все нормально проверь атач
PHP:
        // {{{ do/while
        if ($lastOp['opcode'] == XC_JMPNZ && !empty($lastOp['jmpouts'])
        && $lastOp['jmpouts'][0] == $range[0]) {
            $this->removeJmpInfo($EX, $range[1]);
UPD: архив был обновлен качайте версию по датам сверху 10012013, dima2k пофиксил баг, возможно и сам его опишет
 
Наконец доделал два серйозных фикса.
1. Не обрабатывалась конструкция вида
PHP:
if(0){
        echo 'false';
} else {
        echo 'test';
        if(1) {
                echo 'true';
        }
}
вместо этого декомпилятор выводил:
PHP:
if (0) {
        echo 'false';
}
else if (1) {
        echo 'true';
}
Фикс:
Строки 888-900
PHP:
        $isElseIf = true;
        // search for else if
        $range[0] = $ifRange[1] + 1;
        for ($i = $ifRange[1] + 1; $i <= $range[1]; ++$i) {
          // find first jmpout
          if (!empty($opcodes[$i]['jmpouts'])) {
            if ($this->isIfCondition($EX, array($i, $range[1]))) {
              $this->dasmBasicBlock($EX, array($range[0], $i));
              $range[0] = $i;
            }
            break;
          }
        }
Меняем на:
PHP:
        // search for else if
        $range[0] = $ifRange[1] + 1;
        for ($i = $ifRange[1] + 1; $i <= $range[1]; ++$i) {
          $this->dasmBasicBlock($EX, array($i, $i));
          if (isset($EX['opcodes'][$i]['php'])) break;
          $isElseIf = true;
          // find first jmpout
          if (!empty($opcodes[$i]['jmpouts'])) {
            if ($this->isIfCondition($EX, array($i, $range[1]))) {
              $this->dasmBasicBlock($EX, array($range[0], $i));
              $range[0] = $i;
            }
            break;
          }
        }
[/spoil]
Второй серйозный баг - некорректно обрабатывались конструкции вида:
PHP:
$this->error .= "\n" . $this->backends[$bnum]->error; //тут не отображается все с this, только .= 'error'
Вот фикс:
[spoil]
В строках 2147-2154 было:
PHP:
        else if (isset($this->binops[$opc])) { // {{{
          $this->usedOps[$opc] = true;
          $op1val = $this->getOpVal($op1, $EX);
          $op2val = $this->getOpVal($op2, $EX);
          $rvalue = new Decompiler_Binop($this, $op1val, $opc, $op2val);
          $resvar = $rvalue;
          // }}}
        }
Станет:
PHP:
        else if (isset($this->binops[$opc])) { // {{{
          $this->usedOps[$opc] = true;
          $op1val = $this->getOpVal($op1, $EX);
          $op2val = $this->getOpVal($op2, $EX);
          if (!isset($op1val)) {
            $op1val = '$this';
          }
          if ($opcodes[$i+1]['opcode'] == XC_OP_DATA) {
            ++ $i;
            if ($opcodes[$i]['op2']['op_type'] == 4) {
              $lvalue = str($op1val) . '[' . str($op2val) .']';
            }
            else {
              $lvalue = str($op1val) . "->" . unquoteVariableName($op2val);
            }
            $rvalue = $this->getOpVal($opcodes[$i]['op1'], $EX);
            $op1val = $lvalue;
            $op2val = $rvalue;
          }
          $rvalue = new Decompiler_Binop($this, $op1val, $opc, $op2val);
          $resvar = $rvalue;
          // }}}
        }
После этого тестовые примеры отрабатываются нормально.
Жду новых багрепортов =)
 
Их есть ;) у нас вот пример обработки конструкций CASE, как я понял числа пишутся без кавычек, а слова в кавычках, но из под бинарника Зенда обрабатывается без кавычек 1 значение, в остальных значенях CASE ошибка ОФсета (бинарный файл архива 1 поста 53.php )
PHP:
<?php
  function error($code)
    {
        echo 'LICENSE ERROR: ' . "\n";
 
        switch ($code) {
        case KC_NO_KEY:
            exit('Specified key file not found: ' . $this->keyFile);
            break;
 
        case KC_NO_KEY:
            exit('Format of specified key file is incorrect.');
            break;
 
        case KC_NO_KEY:
            exit('Incorrect signature of key file.');
            break;
 
        case KC_NO_KEY:
            exit('Key expired: expiration date = ' . date('Y-m-d H:i:s', $this->key['until']) . '.');
            break;
 
        case KC_NO_KEY:
            exit('Incorrect system partitions, check linux distributive.');
            break;
 
        default:
            exit('Unknown error.');
            break;
        }
    }
 
    ?>
дальше вместо VAR печатает PUBLIC в классах
PHP:
    class Engine {
    var $config;
    var $db;
    var $settings;
    var $lang;
    var $smarty;
    var $page;
    var $user;
    var $rubrics;
    var $templates;
//////////////////
class Engine
{
    public $config;
    public $db;
    public $settings;
    public $lang;
    public $smarty;
    public $page;
    public $user;
проблема с глобалами (обвал)
PHP:
<?php
class Engine {
 
    function getPageInfo(&$page) {
        global $rubrics; ////////// тут
            if (isset($rubrics[$page["position"]][$page["id_category"]]["categories"])) {
                $page["categories"]=$rubrics[$page["position"]][$page["id_category"]]["categories"];
            } else {
                $page["categories"]=0;
            }
            if (isset($rubrics[$page["position"]][$page["id_category"]]["level"])) {
                $page["level"]=$rubrics[$page["position"]][$page["id_category"]]["level"];
            }
            return true;
    }
}
   
?>
 

Вложения

  • Decompiler.class13012013.rar
    15,2 KB · Просмотры: 22
Буду постить каждый фикс по очереди:
Их есть ;) у нас вот пример обработки конструкций CASE, как я понял числа пишутся без кавычек, а слова в кавычках, но из под бинарника Зенда обрабатывается без кавычек 1 значение, в остальных значенях CASE ошибка ОФсета (бинарный файл архива 1 поста 53.php )
Строки 1044-1047:
PHP:
if ($caseOp['opcode'] == XC_CASE) {
echo 'case ';
echo str($this->getOpVal($caseOp['op2'], $EX), $EX);
echo ':', PHP_EOL;
меняем на:
PHP:
if ($caseOp['opcode'] == XC_CASE) {
if ($opcodes[$caseFirst - 1]["opcode"] == XC_FETCH_CONSTANT) {
if ($opcodes[$caseFirst - 1]['op1']['op_type'] == XC_IS_UNUSED) {
$resvar = $this->stripNamespace($opcodes[$caseFirst - 1]['op2']['constant']);
}
else if ($opcodes[$caseFirst - 1]['op1']['op_type'] == XC_IS_CONST) {
$resvar = $this->stripNamespace($opcodes[$caseFirst - 1]['op1']['constant']);
}
else {
$resvar = $this->getOpVal($opcodes[$caseFirst - 1]['op1'], $EX);
}
}
else {
$resvar = $this->getOpVal($caseOp['op2'], $EX);
}
echo 'case ';
echo str($resvar, $EX);
echo ':', PHP_EOL;
Почему то с этого компьютер при вставке кода не сохраняется форматирование отступов, ну да ладно =) Приложил пофиксеный с красивыми отступами
 

Вложения

  • Decompiler.class09012013-fix-case.zip
    15,4 KB · Просмотры: 29
Статус
В этой теме нельзя размещать новые ответы.
Назад
Сверху