Hi!
On 22 May 2014 00:53, Derick Rethans <derick@php.net> wrote:
> On Wed, 21 May 2014, Nicolai Scheer wrote:
>
> > Do you have an example of a tool that can reverse opcodes to php code?
> > Maybe I did not search for the right thing, I did not stumble upon any.
>
> It exists, there are tools. I might have seen code that does it.
>
> > I always thought the opcodes where kind of cryptic, at least a bit... I'm
> > not longing for "true" protection. It's enough if the scripts can not be
> > read and modified in an easy way.
>
> Yes, that is definitely possible. I actually have a working extension
> for PHP 5.3 and 5.4 that stores encrypted opcodes. PHP 5.5 not yet
> implemented.
>
That's very interesting. Guess you won't share the code?
Maybe we can get a little more technical again... As I already said, the
blenc extension would be a good start (just store encrypted php sources),
at least for me to experiment with. Unfortunately it crashes php when used
with opcache. To be more precise it seems to crash, when an included file
is served from opcache's cache.
I tried to do my own minimal extension for testing purposes. It justs
overrides zend_compile_file, so it can read base64 encoded files.
It boils down to:
zend_op_array *my_compile(zend_file_handle *file_handle, int type TSRMLS_DC)
{
char *buf, *decoded_buf;
size_t buf_size, decoded_buf_size = 0;
zval *code;
zend_op_array *opcode = NULL;
zend_stream_fixup( file_handle, &buf, &buf_size );
if ( strncasecmp( buf, "BS64:", 5 ) == 0 )
{
MAKE_STD_ZVAL(code);
// just base64_decode the file...
decoded_buf = php_base64_decode(buf+5, buf_size-5,
&decoded_buf_size );
// cut <?php...
ZVAL_STRINGL( code, decoded_buf+5, decoded_buf_size-5, TRUE );
opcode = zend_compile_string( code, (char*)file_handle->filename
TSRMLS_CC );
efree(decoded_buf);
efree(code);
}
else
{
opcode = zend_compile_file_original( file_handle, type TSRMLS_CC );
}
return opcode;
}
The "encoded" files just contain the string "BS64:" followed by the base64
encoded script.
I tested this one on windows, 32bit, php 5.5.12, VC11 NTS using the shipped
opcache extension using the php embedded webserver.
The main file:
<?php
echo "hello world - me\n";
require_once __DIR__ . '/class_1.php';
#echo "stuff?";
The "encoded" file class_1.php:
BS64:PD9waHANCg0KY2xhc3MgY2xhc3NfMQ0Kew0KCXB1YmxpYyBmdW5jdGlvbiBfX2NvbnN0cnVjdCgpDQoJew0KCQllY2hvICJjcmVhdGVkIG9iamVjdCBmcm9tIGNsYXNzIDFcbiI7DQoJfQ0KDQp9DQo=
If I run this once (php started via php -S localhost:8000) it works fine. I
added a lot of debug comments to the opcache code ensuring it runs through
the methods I expect.
If I run this twice, everything is still ok. Now, if I just uncomment the
"echo stuff" in the main script and run it again, php crashes.
That's the very same behaviour I get with blenc. I don't know why it is
crashing. I had an intermediate example where it crashed everytime I used
an included encoded script, but I can not reproduce this again.
It seems, as if the opcode returned from zend_compile_string differs from
the usual zend_compile and this crashes the engine when this opcode is
executed again (fetched from opache). Also, there are memory leaks reported
for the function above (zend_opcode.c and plain_wrapper.c), maybe I'm just
doing it wrong?
Any insight is very appreciated. I know this approach is stupid simple, but
I'm just trying to figure out which way I could proceed and how stuff works
down there.
Thanks for any help!
Greetings
Nico