Debugging encoded extensions

Sometimes we need to debug the extensions created by other developers to fix possible issues or adjust some functionality. Also, it is a well-known situation in Magento when you have to debug and resolve the extensions conflicts.

Some developers use different encoding algorithms to hide the code of their extensions, no matter that this fact contradicts the open source politics. You can face with different types of the encoding such as ionCube, chr() and others. For example, the ionCube encoding method needs an additional server configuration, and that is why it is used quite rarely.
In this article we are describing how to debug the chr() encoded extensions. By the way, you should also remember that some extensions are protected by the license and you are not able to use any part of their code.

Let’s assume that the observer’s method returns some error. However, we are not sure where exactly this error is because this extension is encoded.

Here is an example of chr() encoded extension’s class:

<?php
 class Other_Developer_Model_Observer{public function observeLayoutHandleInitialization(Varien_Event_Observer$���){if (!Mage::getStoreConfigFlag(chr(115).chr(109).chr(97).chr(114).chr(116).chr(95).chr(99).chr(97).chr(116).chr(97).chr(108).chr(111).chr(103).chr(47).chr(103).chr(101).chr(110).chr(101).chr(114).chr(97).chr(108).chr(47).chr(101).chr(110).chr(97).chr(98).chr(108).chr(101).chr(100)))return ;$����=$���->{"\x67\x65\x74\x45\x76\x65\x6e\x74"}()->{"\x67\x65\x74\x41\x63\x74\x69\x6f\x6e"}();$�����=$����->{"\x67\x65\x74\x46\x75\x6c\x6c\x41\x63\x74\x69\x6f\x6e\x4e\x61\x6d\x65"}();if ($�����== chr(99).chr(97).chr(116).chr(97).chr(108).chr(111).chr(103).chr(95).chr(99).chr(97).chr(116).chr(101).chr(103).chr(111).chr(114).chr(121).chr(95).chr(118).chr(105).chr(101).chr(119)){$����->{"\x67\x65\x74\x4c\x61\x79\x6f\x75\x74"}()->{"\x67\x65\x74\x55\x70\x64\x61\x74\x65"}()->{"\x61\x64\x64\x48\x61\x6e\x64\x6c\x65"}(chr(119).chr(112).chr(95).chr(115).chr(109).chr(97).chr(114).chr(116).chr(99).chr(97).chr(116).chr(97).chr(108).chr(111).chr(103).chr(95).chr(112).chr(114).chr(111).chr(100).chr(117).chr(99).chr(116).chr(95).chr(108).chr(105).chr(115).chr(116));}if ($�����== chr(99).chr(97).chr(116).chr(97).chr(108).chr(111).chr(103).chr(115).chr(101).chr(97).chr(114).chr(99).chr(104).chr(95).chr(114).chr(101).chr(115).chr(117).chr(108).chr(116).chr(95).chr(105).chr(110).chr(100).chr(101).chr(120)|| $�����== chr(99).chr(97).chr(116).chr(97).chr(108).chr(111).chr(103).chr(115).chr(101).chr(97).chr(114).chr(99).chr(104).chr(95).chr(97).chr(100).chr(118).chr(97).chr(110).chr(99).chr(101).chr(100).chr(95).chr(114).chr(101).chr(115).chr(117).chr(108).chr(116)|| $�����== chr(116).chr(97).chr(103).chr(95).chr(112).chr(114).chr(111).chr(100).chr(117).chr(99).chr(116).chr(95).chr(108).chr(105).chr(115).chr(116)){$����->{"\x67\x65\x74\x4c\x61\x79\x6f\x75\x74"}()->{"\x67\x65\x74\x55\x70\x64\x61\x74\x65"}()->{"\x61\x64\x64\x48\x61\x6e\x64\x6c\x65"}(chr(119).chr(112).chr(95).chr(115).chr(109).chr(97).chr(114).chr(116).chr(99).chr(97).chr(116).chr(97).chr(108).chr(111).chr(103).chr(95).chr(115).chr(101).chr(97).chr(114).chr(99).chr(104).chr(95).chr(114).chr(101).chr(115).chr(117).chr(108).chr(116).chr(95).chr(108).chr(105).chr(115).chr(116));}}public function afterSaveOrignSalesSettings($���){$����=$���->{"\x67\x65\x74\x57\x65\x62\x73\x69\x74\x65"}();$�����=$���->{"\x67\x65\x74\x53\x74\x6f\x72\x65"}();$this->{"\x63\x6f\x70\x79\x4f\x72\x69\x67\x6e\x53\x61\x6c\x65\x73\x53\x65\x74\x74\x69\x6e\x67\x73"}($����,$�����);$this->{"\x5f\x72\x65\x69\x6e\x69\x74\x43\x6f\x6e\x66\x69\x67\x44\x61\x74\x61"}();}public function reinitConfigData(){$this->{"\x5f\x72\x65\x69\x6e\x69\x74\x43\x6f\x6e\x66\x69\x67\x44\x61\x74\x61"}();}}

Note that chr() is a PHP function. This function returns the one-character string containing the character specified by ASCII. The ASCII value can be specified in decimal, octal, or hex values.

As you noticed, we do not see any methods or variables there. So, let’s try to decode the class.
In the beginning, we need to get the readable formatting for this class. We should find the special symbols (for example: “;” , “{”, “}”) and special construction’s words (“if”, “for”..) which help separate the code. Then, we need to insert line breaks and spaces to make the correct formatting. As a result, we will get the following format of the code:

<?php
 class Other_Developer_Model_Observer
 {
     public function observeLayoutHandleBaseInitialization(Varien_Event_Observer $���)
     {
        if (!Mage::getStoreConfigFlag(chr(115).chr(109).chr(97).chr(114).chr(116).chr(95).chr(99).chr(97).chr(116).chr(97).chr(108).chr(111).chr(103).chr(47).chr(103).chr(101).chr(110).chr(101).chr(114).chr(97).chr(108).chr(47).chr(101).chr(110).chr(97).chr(98).chr(108).chr(101).chr(100)))return ;
        $����=$���->{"\x67\x65\x74\x45\x76\x65\x6e\x74"}()->{"\x67\x65\x74\x41\x63\x74\x69\x6f\x6e"}();
        $�����=$����->{"\x67\x65\x74\x46\x75\x6c\x6c\x41\x63\x74\x69\x6f\x6e\x4e\x61\x6d\x65"}();
        if ($�����== chr(99).chr(97).chr(116).chr(97).chr(108).chr(111).chr(103).chr(95).chr(99).chr(97).chr(116).chr(101).chr(103).chr(111).chr(114).chr(121).chr(95).chr(118).chr(105).chr(101).chr(119)) {
            $����->{"\x67\x65\x74\x4c\x61\x79\x6f\x75\x74"}()->{"\x67\x65\x74\x55\x70\x64\x61\x74\x65"}()->{"\x61\x64\x64\x48\x61\x6e\x64\x6c\x65"}(chr(119).chr(112).chr(95).chr(115).chr(109).chr(97).chr(114).chr(116).chr(99).chr(97).chr(116).chr(97).chr(108).chr(111).chr(103).chr(95).chr(112).chr(114).chr(111).chr(100).chr(117).chr(99).chr(116).chr(95).chr(108).chr(105).chr(115).chr(116));
        }
        if ($�����== chr(99).chr(97).chr(116).chr(97).chr(108).chr(111).chr(103).chr(115).chr(101).chr(97).chr(114).chr(99).chr(104).chr(95).chr(114).chr(101).chr(115).chr(117).chr(108).chr(116).chr(95).chr(105).chr(110).chr(100).chr(101).chr(120)|| $�����== chr(99).chr(97).chr(116).chr(97).chr(108).chr(111).chr(103).chr(115).chr(101).chr(97).chr(114).chr(99).chr(104).chr(95).chr(97).chr(100).chr(118).chr(97).chr(110).chr(99).chr(101).chr(100).chr(95).chr(114).chr(101).chr(115).chr(117).chr(108).chr(116)|| $�����== chr(116).chr(97).chr(103).chr(95).chr(112).chr(114).chr(111).chr(100).chr(117).chr(99).chr(116).chr(95).chr(108).chr(105).chr(115).chr(116)) {
            $����->{"\x67\x65\x74\x4c\x61\x79\x6f\x75\x74"}()->{"\x67\x65\x74\x55\x70\x64\x61\x74\x65"}()->{"\x61\x64\x64\x48\x61\x6e\x64\x6c\x65"}(chr(119).chr(112).chr(95).chr(115).chr(109).chr(97).chr(114).chr(116).chr(99).chr(97).chr(116).chr(97).chr(108).chr(111).chr(103).chr(95).chr(115).chr(101).chr(97).chr(114).chr(99).chr(104).chr(95).chr(114).chr(101).chr(115).chr(117).chr(108).chr(116).chr(95).chr(108).chr(105).chr(115).chr(116));
        }
     }

    public function afterSaveBaseSalesSettings($���)
    {
        $����=$���->{"\x67\x65\x74\x57\x65\x62\x73\x69\x74\x65"}();
        $�����=$���->{"\x67\x65\x74\x53\x74\x6f\x72\x65"}();
        $this->{"\x63\x6f\x70\x79\x4f\x72\x69\x67\x6e\x53\x61\x6c\x65\x73\x53\x65\x74\x74\x69\x6e\x67\x73"}($����,$�����);
        $this->{"\x5f\x72\x65\x69\x6e\x69\x74\x43\x6f\x6e\x66\x69\x67\x44\x61\x74\x61"}();
    }
    public function _reinitConfigData()
    {
        $this->{"\x5f\x72\x65\x69\x6e\x69\x74\x43\x6f\x6e\x66\x69\x67\x44\x61\x74\x61"}();
    }
}

Well then, it is much better but still not clear enough. We are able to recognise the class methods, but still we do not know where exactly the error appears. The only thing left – to decode “chr(101).chr(97).chr(114).chr(99) …” or “{“\x67\x65\x74\x57\x65\x62\x73\x69\x74\x65”}”.
For this purpose we will use the great function echo(). Our debugger stopped inside of the afterSaveBaseSalesSettings() method. So, we do not need to decode the full class, let’s do it only for the method where the error occurs. But you can also try to decode all the code if you want to.

In order to decode the encoded string we should create a simple PHP script.

echo 'public function afterSaveBaseSalesSettings($���)'.'<br />';
echo '    {'.'<br />';
echo         '$����=$���->'."\x67\x65\x74\x57\x65\x62\x73\x69\x74\x65".'()'.'<br />';
echo         '$�����=$���->'."\x67\x65\x74\x53\x74\x6f\x72\x65".'()'.'<br />';
echo         '$this->'."\x63\x6f\x70\x79\x4f\x72\x69\x67\x6e\x53\x61\x6c\x65\x73\x53\x65\x74\x74\x69\x6e\x67\x73".'($����,$�����)'.'<br />';
echo         '$this->'."\x5f\x72\x65\x69\x6e\x69\x74\x43\x6f\x6e\x66\x69\x67\x44\x61\x74\x61".'()'.'<br />';
echo '    }';

The content which does not need to be decoded and the variables with names like $���� should be escaped by ‘ ’.
And for strings like {“\x67\x65\x74\x57\x65\x62\x73\x69\x74\x65”} we should remove ‘{}’.

Now just run the PHP script and check the result:

public function afterSaveBaseSalesSettings($���)
{
$����=$���->getWebsite()
$�����=$���->getStore()
$this->copyOrignSalesSettings($����,$�����)
$this->_reinitConfigData()
}

Unfortunately, we are not able to decode the variable names like $����, but it is not necessary in this case.
Using the same way we can decode strings like ..chr(99).chr(97).chr(116).chr(97).

For example, we need to decode the following part:

 if ($�����== chr(99).chr(97).chr(116).chr(97).chr(108).chr(111).chr(103).chr(95).chr(99).chr(97).chr(116).chr(101).chr(103).chr(111).chr(114).chr(121).chr(95).chr(118).chr(105).chr(101).chr(119))  {
$����->{"\x67\x65\x74\x4c\x61\x79\x6f\x75\x74"}()->{"\x67\x65\x74\x55\x70\x64\x61\x74\x65"}()->{"\x61\x64\x64\x48\x61\x6e\x64\x6c\x65"}(chr(119).chr(112).chr(95).chr(115).chr(109).chr(97).chr(114).chr(116).chr(99).chr(97).chr(116).chr(97).chr(108).chr(111).chr(103).chr(95).chr(112).chr(114).chr(111).chr(100).chr(117).chr(99).chr(116).chr(95).chr(108).chr(105).chr(115).chr(116));
 }

After the code has been processed by our PHP script we get the following result:

if ($�����==catalog_category_view) {
$����->getLayout()->getUpdate()->addHandle(catalog_product_list)
}

The described way is not very convenient because it requires a lot of time and patience.
But sometimes it is the only way to encode the Magento extension.
Thank you for reading our article, and you’re welcome to leave your feedback in the comments below.