Need advise on dynamic reversing encrypted php file

Hi folks.
I have some software which is delivered as enctypted php scripts. The encryption which is used is ioncube. So my strategy is to let the software run (it runs as a network service), while i will use R2 debugger to get right into memory\code and do my investigations.
So as i understand the process, php interpreter generates some binary whith is then loaded in memory region with X permissions and passes controll to it. Is it correct?
If yes, i cannot figure out how to locate the memory space i need.
If i attach to the runing process i see the following memory mappings:

[0x7f18e6909dd7]> dm= ~!so
map 4.1M - 0x000056257a70c000 |#-----------------------------| 0x000056257ab25000 r-x /usr/bin/php7.2
map 484K - 0x000056257ad24000 |#-----------------------------| 0x000056257ad9d000 r-- /usr/bin/php7.2
map 108K - 0x000056257ad9d000 |#-----------------------------| 0x000056257adb8000 rw- /usr/bin/php7.2
map 116K - 0x000056257adb8000 |#-----------------------------| 0x000056257add5000 rw- unk0
map 2.7M - 0x000056257c811000 |#-----------------------------| 0x000056257cac2000 rw- [heap]
map 24K - 0x00007f18da538000 |------------------------------| 0x00007f18da53e000 rw- unk1
map 4K - 0x00007f18dae98000 |------------------------------| 0x00007f18dae99000 rw- unk2
map 16K - 0x00007f18dcfb3000 |------------------------------| 0x00007f18dcfb7000 rw- unk3
map 4K - 0x00007f18ddb1f000 |------------------------------| 0x00007f18ddb20000 rw- unk4
map 4K - 0x00007f18de56f000 |------------------------------| 0x00007f18de570000 rw- unk5
map 4K - 0x00007f18df0f4000 |------------------------------| 0x00007f18df0f5000 rw- unk6
map 4K - 0x00007f18e06a9000 |------------------------------| 0x00007f18e06aa000 rw- unk7
map 124K - 0x00007f18e10b3000 |------------------------------| 0x00007f18e10d2000 rw- unk8
map 8K - 0x00007f18e31f6000 |------------------------------| 0x00007f18e31f8000 rw- unk9
map 36K - 0x00007f18e3465000 |------------------------------| 0x00007f18e346e000 rw- unk10
map 16K - 0x00007f18e38d3000 |------------------------------| 0x00007f18e38d7000 rw- unk11
map 3.2M - 0x00007f18e38d7000 |------------------------------| 0x00007f18e3c00000 r-- /usr/lib/locale/locale-archive
map 2M - 0x00007f18e3c00000 |------------------------------| 0x00007f18e3e00000 rw- unk12
map 16K - 0x00007f18e4449000 |------------------------------| 0x00007f18e444d000 rw- unk13
map 4K - 0x00007f18e65d3000 |------------------------------| 0x00007f18e65d4000 rw- unk14
map 16K - 0x00007f18e67ef000 |------------------------------| 0x00007f18e67f3000 rw- unk15
map 16K - 0x00007f18e6be0000 |------------------------------| 0x00007f18e6be4000 rw- unk16
map 12K - 0x00007f18e72fd000 |------------------------------| 0x00007f18e7300000 rw- unk17
map 4K - 0x00007f18e794d000 |------------------------------| 0x00007f18e794e000 rw- unk18
map 8K - 0x00007f18e8597000 |------------------------------| 0x00007f18e8599000 rw- unk19
map 292K - 0x00007f18e88f5000 |------------------------------| 0x00007f18e893e000 rw- unk20
map 428K - 0x00007f18e8953000 |------------------------------| 0x00007f18e89be000 rw- unk21
map 4K - 0x00007f18e89cd000 |------------------------------| 0x00007f18e89ce000 rw- unk22
map 4K - 0xffffffffff600000 |------------------------------| 0xffffffffff601000 r-x [vsyscall]
map 132K - 0x00007ffe55e0e000 |#####-------------------------| 0x00007ffe55e2f000 rw- [stack]
map 12K - 0x00007ffe55ed4000 |-----------------------------#| 0x00007ffe55ed7000 r-- [vvar]

So. As i have guessed we nee da memory region with X rights. So we only left with the following:

[0x7f18e6909dd7]> dm= ~!so | grep “-x”
map 4.1M - 0x000056257a70c000 |#-----------------------------| 0x000056257ab25000 r-x /usr/bin/php7.2
map 4K - 0xffffffffff600000 |------------------------------| 0xffffffffff601000 r-x [vsyscall]

I’d say that vsyscall is something related to syscalls, so we are only left wth a single memory map.
So next, i check the mapping inside the selected mem region:

[0x56257aa6c260]> dmS php
[Sections]

nth paddr size vaddr vsize perm name

0 0x00000000 0x0 0x00000000 0x0 ---- php7.2.
1 0x00000238 0x1c 0x56257a70c238 0x1c -r-- php7.2…interp
2 0x00000254 0x20 0x56257a70c254 0x20 -r-- php7.2…note.ABI_tag
3 0x00000274 0x24 0x56257a70c274 0x24 -r-- php7.2…note.gnu.build_id
4 0x00000298 0x3328 0x56257a70c298 0x3328 -r-- php7.2…gnu.hash
5 0x000035c0 0xed18 0x56257a70f5c0 0xed18 -r-- php7.2…dynsym
6 0x000122d8 0xbf10 0x56257a71e2d8 0xbf10 -r-- php7.2…dynstr
7 0x0001e1e8 0x13c2 0x56257a72a1e8 0x13c2 -r-- php7.2…gnu.version
8 0x0001f5b0 0x1b0 0x56257a72b5b0 0x1b0 -r-- php7.2…gnu.version_r
9 0x0001f760 0xbf688 0x56257a72b760 0xbf688 -r-- php7.2…rela.dyn
10 0x000dede8 0x4908 0x56257a7eade8 0x4908 -r-- php7.2…rela.plt
11 0x000e36f0 0x17 0x56257a7ef6f0 0x17 -r-x php7.2…init
12 0x000e3710 0x30c0 0x56257a7ef710 0x30c0 -r-x php7.2…plt
13 0x000e67d0 0x30 0x56257a7f27d0 0x30 -r-x php7.2…plt.got
14 0x000e6800 0x279a52 0x56257a7f2800 0x279a52 -r-x php7.2…text
15 0x00360254 0x9 0x56257aa6c254 0x9 -r-x php7.2…fini
16 0x00360260 0x64288 0x56257aa6c260 0x64288 -r-- php7.2…rodata
17 0x003c44e8 0x1 0x56257aad04e8 0x1 -r-- php7.2…stapsdt.base
18 0x003c44ec 0xc33c 0x56257aad04ec 0xc33c -r-- php7.2…eh_frame_hdr
19 0x003d0828 0x48620 0x56257aadc828 0x48620 -r-- php7.2…eh_frame
20 0x00418fd0 0x8 0x56257ad24fd0 0x8 -rw- php7.2…init_array
21 0x00418fd8 0x8 0x56257ad24fd8 0x8 -rw- php7.2…fini_array
22 0x00418fe0 0x76410 0x56257ad24fe0 0x76410 -rw- php7.2…data.rel.ro
23 0x0048f3f0 0x290 0x56257ad9b3f0 0x290 -rw- php7.2…dynamic
24 0x0048f680 0x1978 0x56257ad9b680 0x1978 -rw- php7.2…got
25 0x00491000 0x1a638 0x56257ad9d000 0x1a638 -rw- php7.2…data
26 0x004ab638 0x16 0x56257adb7638 0x16 -rw- php7.2…probes
27 0x004ab64e 0x0 0x56257adb7660 0x1cff0 -rw- php7.2…bss
28 0x004ab650 0x4a8 0x00000000 0x4a8 ---- php7.2…note.stapsdt
29 0x004abaf8 0x34 0x00000000 0x34 ---- php7.2…gnu_debuglink
30 0x004abb2c 0x125 0x00000000 0x125 ---- php7.2…shstrtab

But here i am not sure.

  1. I am right in general? Is this the area i need to focus on?
  2. If 1. is true, then how do i dump the .text section to the disc, for example, And then load it into Ghidra to decompile or build some graphs?
  3. In general what’s next? I am a bit confused.

Well interpreters dont generate binaries they generate intermediate (assembly) code which technically be baked into a binary with some magic , what you need to understand is how ioncube works : ioncube basically captures the intermediate code generated by the php interpreter , obfusticates it , base64 encodes it (open any php file in the application you are analyzing you’ll see a large chunk of base64 data) and passes it to the ioncube loader , which inturn executes it (ioncube functions somewhat like JVM).

Here’s a very good resource which can help you : https://media.blackhat.com/ad-12/Saher/bh-ad-12-stealing-from-thieves-Saher-slides.pdf

Hi there. Thanks for the link. Sadly it is outdated a bit. See, ioncube has several updates of their protection mechanism ever since. But anyway, i am not interested in reversing ioncude itself. I mean, in the end of the day the bytecode will end up in the memory in the format appropriate for direct CPU consumption. Isn’t it? So my task is just to find the right mem region. I am right? Or it always stored as an intermediate bytecode and passes over Zend engine? This seems not realistic, because it would cause huge processing overhead.
I couldn’t find any info in google about reversing PHP applications from that perspective. Maybe someone saw something?
Another idea which came up to me, is just to use strace, for example, find out from where the sys calls are happening and go straight there. Here another question. How can i dump the whole mem region with the application to a file and just open it then with Ghidra and statically analize?

i was able to dig this up , might help you.

(the author of the stack overflow answer is a ioncube employee)

This topic was automatically closed after 121 days. New replies are no longer allowed.