What do we have here?

Challenge description

It says "web server", and the filename is "c99.zip", so maybe it's a PHP shell or something?

a PHP file

Inside the zip, there is a PHP file. Let's check what's in it. (using notepad++ )

contents of the PHP file

Hmm... some obfuscated PHP code. How do I know it's obfuscated? Well, the principal indicator of obfuscation or confusion here is the usage of the evil eval function ?.

Also the variable names are obscure and don't mean anything. Plus, the variables' content doesnt look like any useful data, so maybe it will be decrypted or deobfuscated somehow. Bottom line, does that look like normal PHP code to you? ?


What to do?

Well, we'll de-obfuscate it.

I'll show two methods here. A quick one ; suitable for CTFs and to get the job done quickly ☠️ . And a slow detailed one, to analyze the PHP file as much as possible.


The quick method

Whenever you see an obfuscated script; whether it be PHP code, JS file, VBS worm, Obfuscated powershell script, or whatever... Just look for the "eval( )" (or similar methods / functions) and replace it with "var_dump( )" (or "console.log( )" in JS ... or "echo" in powershell).

In most cases: the obfuscated code will finish its deobfuscation right before execution. So we will intervene at this point and examine the deobfuscated code...

using var_dump( ) instead of eval( )

After deobfuscation. Contains the flag

That was quick.. Just take a good look and you will spot the flag.

Challenge completed ^^


The slow detailed method

Since we're going to reverse it, lets start from the bottom up...

First: we untie the expression on Line 9 ...

untied line 9

Now it's a bit clearer to see.

Lets work from in-out... remember, we're reversing this PHP file, so we always work bottom --> up, and in ---> out..

$iuq has occured 3 times

The innermost part is a call to a function by the name "$iuq". The dollar sign "$" at the beginning indicates it's a variable's name. With the help of Notepad++'s syntax highlighting, we could see that this variable is defined on line 6, and has the value of "str_replace".

So, it is PHP's "str_replace" function. Lets check it at PHP's documentation

documentation of str_replace( )

Ok, so we're basically replacing all occurences of the 1st argument ("ec") in the string in the 3rd argument ("$kyo1.$kyo2.$kyo3.$kyo4") by an empty string " " (2nd argument).

What is that 3rd agument? you see that dot (" . ")? that's the way you concatenate (add) strings in PHP. Check it in the documentation.

Documentation of string concatenation

So basically:

$kyo1 . $kyo2 . $kyo3 . $kyo4 = $kyo1 + $kyo2 + $kyo3 + $kyo4

Instead of doing it manually, why not let PHP do it for us instead?

Install XAMPP, start Apache and MySQL services

XAMPP control panel

Navigate to the xampp directory, then inside "htDocs" folder, and copy "c99.php" file there. Then open your browser and type "localhost/c99.php" in the address bar

blank page

Nothing, lol. That's because we don't have any "echo" or "print" or "var_dump()" function calls in our file. Lets add one of them, and dont forget that we must end our lines in php with a semicolon.. (of course -as always- take a copy of our c99.php file, and modify it. ALWAYS TAKE BACKUPS).

Printing out the concatenation's result

After we add line 15, we refresh the page. We will get this long string (416 characters)

concatenation result

Lets comment-out line 15 (in PHP: using double forward-slashes //, or C-style comments /**/). Then we'll run the $iuq function (str_replace) on the 416-chars string, and then var_dump the result again.

after str_replace( )

Now we have 340 characters only. That means that we have indeed used "str_replace" function on our string, and removed all occurences of the sub-string "ec".

What's the next step?

Running the function "$gj" with an argument. The argument is our 340-characters string.

What is the "$gj" function? Same idea...

All occurences of $gj

We assign a 34-characters string on line 4 to $gj. Then we call the str_replace function on it on line 8, so we remove all occurences of the sub-string "cox" in the variable $gj.

So if we var_dump $gj before line 8, we'll get the 34-characters string, and if we var_dump it after line 8, we will get the shorter str_replace'd one. Lets see both...

printing out $gj twice. Before and after str_replace( )

$gj before and after str_replace( )

Pretty easy, right?

So we found out that "$gj" is actually "base64_decode" function. Now lets continue...

Now we know that the evil "eval( )" will run with the following argument:

eval( ) and its args

Lets var_dump it:

lets take that code to an online PHP beautifier:

online PHP beautifier

That looks A LOT easier on the eyes. Lets take it to notepad++ and save it as "c100.php" for example (to save the file, and to get syntax highlighting there).

Beautified code is copied to notepad++

Nice. What to do now? I think we could see the flag already.

You found "ag{hidden_in_php}" on line 9, and "fl" on line 6. Just add them together, and you've got the flag: "flag{hidden_in_php}"

But my goal here isn't getting the flag to just solve the challenge. Lets dig deeper and dissect the code to the end to gain more experience with PHP and obfuscation.?


We could see an evil "eval( )" on line 11. Lets do the same thing we did earlier to it.. untie the expression... I think it looks pretty straight-forward this way...

untied the eval( ) line

Again, lets start from innermost to outermost. We've got a preg_replace function..

preg_replace( ) and its args

Documentation of preg_replace( )

Dont waste your time (yet) on the 1st and 2nd args. The 3rd one (string to run the preg_replace on) is the most important one..

Supposedly, we should use 2 PHP functions: "join( )" and "array_slice( )" on the array $a. Guess where that array comes from?

preg_replace( )'s 3rd argument comes from $_COOKIE

It comes from the $_COOKIE array. Well, bad luck, that's a dead end ?

Why? you may ask.. Well, this is our server and our PHP file, so WE are the ones who set the cookies. So somehow we're expected to create a Cookies array in a way such that the eval( ) on line 11 takes it in, and executes some unknown code. So we basically dont know what the result of the eval( ) should look like, and we dont know what the $_COOKIE array should look like either..

In conclusion , we dont know the input or the output, so we're not going anywhere here.

This is a very nice lesson about distraction in CTFs and in reverse-engineering in general. You see something that could be the flag, capture it and dont waste time ?.