去除试用版ioncube_encoder_xxx_64的14天限制

ionCube,一款PHP加密工具。有试用版Encoder,Decoder是免费的。

$ php -c php.ini -f hello.php
Hello World

$ ./ioncube_encoder_xxx_64 hello.php -o hello_enc.php
Error: The Encoder evaluation period has expired.

一个月前还可以试用ionCube Encoder,中间去支持其他逆向工程的活儿,回来再测
就提示试用结束

在"ioncube_encoder_evaluation/EVALUATION-README.txt"中看到

--------------------------------------------------------------------------
* WHAT IS DIFFERENT IN THE EVALUATION VERSION?

All features of the evaluation Encoder are fully functional, however:

1) Encoded files will expire after 36 hours, or sooner if you encode files to
   expire earlier. Files can be encoded again to continue testing.

2) Encoded files contain a PHP comment to show they are encoded by the
   evaluation Encoder. This text does not alter operation of encoded files,
   and is not present in the release version.

* HOW LONG IS THE EVALUATION PERIOD?

The evaluation version will be functional for 14 days.
--------------------------------------------------------------------------

意思是hello_enc.php只有36小时可用,试用版Encoder本身只有14天可用,先剁后者。
strace -v -i -f -ff -o ioncube_encoder_xxx_64.log ./ioncube_encoder_xxx_64 hello.php -o hello_enc.php

在strace日志中看到,用exit_group(101)退出
gdb -q -nx -x /tmp/gdbinit_x64.txt -x "/tmp/ShellPipeCommand.py" -x "/tmp/GetOffset.py" -ex 'display/5i $pc' ./ioncube_encoder_xxx_64

info files
b *0x4046a8
r hello.php -o hello_enc.php

目标ELF没有_start符号,只能用地址设断。命中_start()后增设断点

catch syscall exit_group

(gdb) c
Continuing.
Error: The Encoder evaluation period has expired.

Catchpoint 2 (call to syscall exit_group), 0x00007ffff75ccc99 in _exit () from /lib64/libc.so.6
1: x/5i $pc
=> 0x7ffff75ccc99 <_exit+57>:   cmp    rax,0xfffffffffffff000
   0x7ffff75ccc9f <_exit+63>:   jbe    0x7ffff75ccc80 <_exit+32>
   0x7ffff75ccca1 <_exit+65>:   mov    esi,eax
   0x7ffff75ccca3 <_exit+67>:   neg    esi
   0x7ffff75ccca5 <_exit+69>:   mov    DWORD PTR fs:[r10],esi
(gdb) bt
#0  0x00007ffff75ccc99 in _exit () from /lib64/libc.so.6
#1  0x00007ffff7540cfb in __run_exit_handlers () from /lib64/libc.so.6
#2  0x00007ffff7540d87 in exit () from /lib64/libc.so.6
#3  0x000000000040e13f in ?? ()
#4  0x00000000004116ef in ?? ()
#5  0x00007ffff7529555 in __libc_start_main () from /lib64/libc.so.6
#6  0x00000000004046d1 in ?? ()
...
(gdb) info proc mappings
process 22078
Mapped address spaces:

          Start Addr           End Addr       Size     Offset objfile
            0x400000           0x540000   0x140000        0x0 /home/scz/src/php/ioncube_encoder_xxx_64
...
            0x744000           0x771000    0x2d000        0x0 [heap]
...
      0x7ffff7507000     0x7ffff76cb000   0x1c4000        0x0 /usr/lib64/libc-2.17.so
...

先输出过期提示再退出。"b _exit"断不下来,因为ld-.so抢先提供了符号_exit,
我们需要断libc中的_exit()。

(gdb) info symbol _exit
_exit in section .text of /lib64/ld-linux-x86-64.so.2

从strace日志看,只有一个write(2,x),还可以设断

catch syscall write

不用针对句柄设条件断点。

(gdb) bt
#0  0x00007ffff75f6a90 in __write_nocancel () from /lib64/libc.so.6
#1  0x00007ffff75812f3 in _IO_new_file_write () from /lib64/libc.so.6
#2  0x00007ffff7581b90 in __GI__IO_file_xsputn () from /lib64/libc.so.6
#3  0x00007ffff757605b in fputs () from /lib64/libc.so.6
#4  0x000000000040d1e2 in ?? ()
#5  0x000000000040e01c in ?? ()
#6  0x00000000004116d5 in ?? ()
#7  0x00007ffff7529555 in __libc_start_main () from /lib64/libc.so.6
#8  0x00000000004046d1 in ?? ()
...
(gdb) i r rdi
rdi            0x2      2
(gdb) x/s *(char**)0x744ca0
0x76cb50:       "Error: The Encoder evaluation period has expired.\n"

过期提示被加密混淆后存放在ELF中,strings直接找不到,一种简单的反静态分析手
段。

通过前述两组调用栈回溯在IDA中定位位于main()中的关键调用:

(gdb) x/1i 0x410eb7
   0x410eb7:    call   0x4de4d0
(gdb) x/7i 0x4de6b4
   0x4de6b4:    jne    0x4de6c4
   0x4de6b6:    add    rsp,0x88
   0x4de6bd:    pop    rbx
   0x4de6be:    pop    rbp
   0x4de6bf:    pop    r12
   0x4de6c1:    pop    r13
   0x4de6c3:    ret

凭经验判断0x4de4d0处的函数在做过期检查,该函数中有肉眼可见的MD5特征常量,
但我未细究函数代码逻辑;0x4de6c3是其返回点,在返回点处让eax恒为0,应该能避
免过期退出。
gdb -q -nx -x /tmp/gdbinit_x64.txt -x "/tmp/ShellPipeCommand.py" -x "/tmp/GetOffset.py" -ex 'display/5i $pc' ./ioncube_encoder_xxx_64

b *0x4de6c3
commands $bpnum
    silent
    set $eax=0
    c
end
r hello.php -o hello_enc.php

测试经ionCube加密过的hello_enc.php,无误。

$ php -c php.ini -f hello_enc.php
Hello World

静态Patch试用版ioncube_encoder_xxx_64

$ rasm2 -a x86 -b 64 -s intel -o 0x4de6b4 "xor eax,eax"
31c0

$ rasm2 -a x86 -b 64 -s intel -o 0x4de6b4 -D 31c0
0x004de6b4   2                     31c0  xor eax, eax

$ fc /b old new
000DE6B4: 75 31
000DE6B5: 0E C0

$ ./ioncube_encoder_xxx_64_scz some.php -o some_enc.php

如有类似需求,理解逆向思路后自行Patch相应版本Encoder,切勿直接照搬。

标签: PHP, 安全

相关文章

如何在PHP框架Workerman中实现异步任务处理

在现代Web应用中,处理繁重的业务逻辑时,避免主业务流程被长时间阻塞是非常重要的。Workerman是一个高性能的PHP Socket框架,支持异步任务处理,可以有效地解决这一问题。本文将详细介...

PHP中使用CURL下载远程超大文件的方法

在使用PHP进行开发时,我们经常需要从远程服务器下载文件。当文件体积较大时,普通的文件操作和cURL方法可能会因为内存限制或执行时间限制而失败。本文将介绍如何使用PHP中的cURL扩展来高效地下...

PHP命名空间使用详解

在 PHP 中,命名空间(Namespace)是一种将相关的类、函数和常量组织到一个逻辑分组中的方式。它有助于避免命名冲突,并提高代码的可维护性和可扩展性。一、命名空间的定义使用 namespa...

复习一下PHP中的类和对象

面向对象编程(OOP)是一种编程范式,它通过类和对象的概念来组织代码。PHP 作为一种广泛使用的服务器端脚本语言,从 PHP 5 开始就全面支持面向对象编程。本文将深入探讨 PHP 中类和对象的...

图片Base64编码

CSR生成

图片无损放大

图片占位符

Excel拆分文件