NeoPI in the Wild

By Scott Behrens

NeoPI was a project developed by myself and Ben Hagen to aid in the detection of obfuscated and encrypted webshells.  I recently came across an article about Webacoo shell and a rewrite of this php backdoor to avoid detection from NeoPI.

Webacoo’s developer used a few interesting techniques to avoid detection.  The first technique was to avoid signature based detection by using the function ‘strrev’:


This bypasses our traditional based signature detection and also lends to a few other techniques to bypass signature based detection.  Another webshell surfaced after NeoPI’s release that uses similar techniques to avoid signature based detection.  Another example could be the following (as seen in

$b = 'bas'.'e64'.'_de'.'code';

We can see that just by breaking up the word, the risk of detection is highly mitigated.  As I suggested at B-Sides, signature based detection is complimentary to the tests in NeoPI but by itself, ineffective.   These methods described above completely thwart this tests effectiveness.

But one thing these techniques must do at some point is actually eval the code.  Webacoo for example uses the following:

eval($b(str_replace(" ","","a W Y o a X …SNIP

By developing a regex that looks for eval and a variable holding the global function, we can flag this file as malicious.  After running this test against a WordPress server with Webacoo’s shell, I observed the following:


Figure 1 – Webacoo identified as suspicious in eval test

NeoPI was able to detect the function and flagged it as malicious.  This particular type of use of eval isn’t very common and I have really only seen it used in malware.  That being said functions.php was also flagged so I imagine this test can still have many false positives and should be used to help aid in manual investigation of the files identified.

Another tweak Webacoo’s developer did was insert spaces in-between each character of a base64 encoded string.  The function str_replace() is called to replace each space before the code is base64_decoded  and eval’d.

In order to thwart this particular obfuscation technique, I went ahead and modified the entropy function to strip spaces within the data the function is analyzing. The screenshot below shows a scan against 1752 php files in WordPress and shows the entropy test results as flagging webacoo as potentially malicious. This increased NeoPI’s effectiveness at detecting webacoo.php but is more of a stopgap solution as the attacker can craft other junk characters to lower the shells entropy and index of coincidence. Some additional thought and research is needed on potentially looking for these complicated search and replace functions to determine if the data being obfuscated is malicious.


Figure 2 – Test results after modifying entropy code results in higher entropy of webacoo.php

The latest version of the code can be checked out at which includes these enhancements.

As for improving the other tests effectiveness, I am looking into the possibility of identifying base64 encodings without looking for the function name.  This technique may be helpful by building a ratio of upper and lower case characters and seeing if there is a trend with files that use obfuscation.

If anyone has interesting techniques for defeating NeoPI please respond to this post and I’ll look at adding more detection mechanisms to this tool!

5 thoughts on “NeoPI in the Wild

  1. I havent tested but it looks like from the source code you miss a lot of php eval functions like preg_replace(), call_user_func(), create_function() etc.
    I collected all of them in the configuration of my static analysis tool for PHP vulnerabilities (including backdoors)

    • That is correct, the signature check is sort of a ‘low hanging fruit’ approach to detecting a webshell. In particular we added this check as a complimentary method for the other methods such as entropy, IC, longest word, which are mostly useful for detecting obfuscated webshells. The primary target when using NeoPI is for the strangely obfuscated and encrypted webshells, so we have decided to leave some of the signature based checks to other tools.

  2. Could NeoPI perform constant-folding of simple functions, like concatenations and functions like strrev() and str_replace(), before performing the entropy analysis?

    • One thing I am interested in is string/function parsing. I think this type of feature would be really interesting. I think a new module for NeoPI could be written to do some of this…I need to do some digging on the best approach.

  3. This may help you in your base64 detection:

    NAME : isBase64Encoded
    PARAMS : string
    RETURN : bool
    DESC : Tests input string to see if it is
    Base64 encoded
    EX : in:MzAz, out:True
    in:MzAz(), out:False
    def isBase64Encoded(s):
    s = s.strip()
    if len(s) % 4 == 0:
    if re.match(‘^[A-Za-z0-9+/]+[=]{0,2}$’, s):
    return True
    return False
    # EOF: isBase64Encoded

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s