Wednesday, September 25, 2019

# InCTF 2019 - s3cur3-r3v

## Description

Hello, can you reverse this object code for me ??? I would be thankfull to you.

challenge.html

## Solution

After googling some of the code, we learned that it corresponds to a series of PHP opcodes for some program. We tried to understand it by rewriting the original program with help from an online PHP shell. The shell we used from 3v4l.org provides VLD output (the PHP disassembly for our code), so we realized we could use it to prototype our code and compare the opcodes to the original program.

After some time, our code looked like this:

``````<?php
function printflag(\$input) {
\$success = "Yayyyy, Here's your flag:";
\$fail = "Naay try harder !!!";

global \$flag;

\$alphabet = "";
for (\$i = 32; \$i < 97; \$i++) {
\$alphabet .= chr(\$i);
}

echo "Alphabet| " . \$alphabet . "\n";

if (strlen(\$input) % 4 != 0) {
}

\$aux = strlen(\$input)*3/4;
if (0 < strrpos(\$input, "`")) {
\$idx = strlen(\$input) - strrpos(\$input, "`");
} else {
\$idx = 0;
}

\$code = array();
\$code[0] = \$aux - \$idx;

\$input_arr = str_split(\$input);

for (\$i = 0, \$x = 0, \$pos = array(); \$i < count(\$input_arr); \$i += 4) {
\$pos[0] = strpos(\$alphabet, \$input_arr[\$i]);
\$pos[1] = strpos(\$alphabet, \$input_arr[\$i+1]);
\$pos[2] = strpos(\$alphabet, \$input_arr[\$i+2]);
\$pos[3] = strpos(\$alphabet, \$input_arr[\$i+3]);

\$code[\$x++] = (\$pos[0] << 2) | (\$pos[1] >> 4);
if (\$pos[2] < 64) {
\$code[\$x++] = (\$pos[1] << 4) | (\$pos[2] >> 2);
if (\$pos[3] < 64) {
\$code[\$x++] = (\$pos[2] << 6) | \$pos[3];
}
}
}

\$encoded_input = '';
for (\$i = 0; \$i < count(\$code); \$i++) {
\$encoded_input .= chr(\$code[\$i]);
}

echo \$encoded_input . "\n";

echo \$success . \$flag . "\n";
} else {
echo \$fail . "\n";
}
}

if (isset(\$_GET['flag']))
printflag(\$_GET['flag']);
?>
``````

Although parts of it seemed weird (such as lines 20 to 27), the main loop gave us many insights about what was going on there. For each block of 4 bytes `(a,b,c,d)` of input, the code encodes the bytes as their indexes in the alphabet, which are numbers from `0` to `63`, and then stores each index in `\$code`. The trick is that, since numbers from `0` to `63` take up 6 bits only, `(a,b,c,d)` can be stored in 24 bits (3 bytes), and that’s exactly what the code does, storing each block of 4 bytes in 3 bytes of `\$code` using some bit magic. It’s a very basic encoding scheme which looks a lot like base64 with a custom alphabet.

To decode it we wrote this script:

``````from binascii import hexlify

k = "YtPEU\x10E\x24\x19\x5DV\x11UE\x92E\x04\xD8\x5De\x99\x5D5RQ\x25SAU\x98YuVU\x16\x10e\x85\xD1I\x96\x13Y\x96\x17M\x85\xD6E\x85\xD6Q\x04V"
b = bin(int(hexlify(k), 16))[2:]
if len(b) % 8 != 0:
b = '0' * (8 - (len(b) % 8)) + b

alpha = [chr(i) for i in range(32, 98)]

s = ''
for x in range(6, len(b)+1, 6):
bp = b[x-6:x]
s += alpha[int(bp, 2)]

print(s)
``````

The code outputs `671015401209758154621038766973524253056867565180987129836987387618764016`, which is a very suspicious value, because all characters are numbers, which is unlikely to happen at random (although we didn’t realize this at first).

Then we opened `http://3.15.186.35/?flag=671015401209758154621038766973524253056867565180987129836987387618764016` and our flag was at the bottom of the page: `inctf{d1d_y0u_n0t_f1nd_th3_b453_64_3ncrypt10n_s000000_3asy}`

Special thanks to Diogenes “diofeher”, Alisson “Infektion” and Daniel “dapolinario” for all their work =)