ByteBandits CTF 2020

The challenges were good and really fun to solve, our team 7SecCTF managed to solve 6 challenges.

The gremlin challenge was particularly interesting


It was a Reverse-Engineering Challenge.
The challenge Description was :

There's a gremlin in my machinery. I guess it'll stop working soon. Can you help me?

along with a file cpg.bin to download
A Hint was also provided

u32 table[10][2] = { {0xff, 1}, {0xfe, 2}, {0xfd, 3}, 
{0xfc, 4}, {0xfb, 5}, {0x00, 5}, {0x01, 4}, {0x02, 3}, {0x03, 2}, {0x04, 1} };

I downloaded the cpg.bin file.

gremlin >> head cpg.bin
H:2,blockSize:1000,created:17168fe53f5,format:1,fletcher:a504a51d
H:2,blockSize:1000,created:17168fe53f5,format:1,fletcher:a504a51d
chunk:1,block:2,len:1,map:2,max:380,next:3,pages:3,root:400000c388,time:3ee,version:1RSTU'��LANGUAGE��C��6)��FULL_NAME��<global>NAME��<global>
��@&��NAME��"/home/jai/Documents/ctf/bbctf/re.c���    �
�y)��FULL_NAME��+/home/jai/Documents/ctf/bbctf/re.c:<global>�NAME��<global>�
��  �   (�  k�  �
�
�
�
�   �

On running strings command on it, the output contained many strings like LINE_NUMBER ORDER PARSER_TYPE_NAME CODE and also contained some code segments

gremlin >> strings cpg.bin
....
....
....
LINE_NUMBER
ORDER
PARSER_TYPE_NAME
ForStatement
CODE
 for (u8 i = 1; i <= key[1]; i++)
ARGUMENT_INDEX
COLUMN_NUMBER
LINE_NUMBER
CODE
TYPE_FULL_NAME
....
....
....

the for loop code segment was interesting, the file seemed like something related to CPG(Code Property Graph) representation, But i didn't know anything about CPG, so i examined the strings output for more details, i further came accross many more code segments

...
...
CODE
while (n > 0)
...
CODE
printf("%llu", out[i])
...
"%llu"
...
CODE
printf("\n")
...
...

we can also note that all the code segments are preceded by the string CODE, so i grepped the strings output

gremlin >> strings cpg.bin| grep CODE -A1|head -n30
CODE
u64 n
--
CODE
COLUMN_NUMBER
--
CODE
ARGUMENT_INDEX
--
CODE
TYPE_FULL_NAME
--
CODE
r = 0
--
CODE
ARGUMENT_INDEX
--
CODE
ARGUMENT_INDEX
--
CODE
while (n > 0)
--
CODE
n > 0
--
CODE
ARGUMENT_INDEX
--

after cleaning up the strings, we get

u64 n
r = 0
while (n > 0)
n > 0
r |= n & 0xff
n & 0xff
0xff
r <<= 1
n >>= 1
r >>= 1
return r;
u8 *s
u32 *idx
*key = table[s[0]]
table[s[0]]
table
s[0]
...
...
...
key[1]
return val;
char *s
u32 n
sz = 0
idx = 0
while (idx < n)
idx < n
*key = table[s[idx]]
table[s[idx]]
table
s[idx]
idx += key[1] + 1
key[1] + 1
key[1]
sz++
return sz;
idx = 0
in[] = { 0, 3, 9, 1, 1, 4, 5, 2, 7, 6, 1, 5, 0, 6, 3, 9, 8, 4,
  9, 9, 2,\n        1, 3, 7, 6, 5, 4, 6, 1, 1, 2, 3, 3, 2, 1, 0, 3, 8, 2, 7 }
...
...
...

and after cleaning all the repeated code we finally get a rough c code

u64 n
r = 0
while (n > 0){
    r |= n & 0xff
    r <<= 1
    n >>= 1
}
r >>= 1
return r;

u8 *s
u32 *idx

*key = table[s[0]]
s[0] &= key[0]
val = 0
val |= s[0]

for (u8 i = 1; i <= key[1]; i++){
    val <<= 1
    val |= s[i]
    *idx += key[1] + 1
return val;

char *s
u32 n
sz = 0
idx = 0
while (idx < n){
    *key = table[s[idx]]
    idx += key[1] + 1
    sz++
return sz;

idx = 0
in[] = { 0, 3, 9, 1, 1, 4, 5, 2, 7, 6, 1, 5, 0, 6, 3, 9, 8, 4,
         9, 9, 2, 1, 3, 7, 6, 5, 4, 6, 1, 1, 2, 3, 3, 2, 1, 0, 3, 8, 2, 7 }

len = sizeof(in) / sizeof(u8)
sz = calc_size(in, len)
idx_o = 0
*out = (u64*)malloc(sz * sizeof(u64))

while (idx < len){
    &out[idx_o++] = resolve(in + idx, &idx)

for (u32 i = 0; i < idx_o; i++)
    printf("%llu", out[i])
printf("\n")
return 0;

we can also see that an array named table is being referred here which appears to be same as the one from the provided Hint.

i then converted the above c code to python which involved removing some size calculation and memory allocation functions

table = [ [0xff, 1], [0xfe, 2], [0xfd, 3], [0xfc, 4],
           [0xfb, 5], [0x00, 5], [0x01, 4], [0x02, 3], [0x03, 2], [0x04, 1] ]

def resolve(s,idx):
    key = table[s[0]]
    s[0] &= key[0]
    val = 0
    val |= s[0]
    for i in range(1,key[1]+1):
        val <<= 1
        val |= s[i]
    idx += key[1] + 1
    return (idx,val)
def main():
    idx = 0
    ln = [ 0, 3, 9, 1, 1, 4, 5, 2, 7, 6, 1, 5, 0, 6, 3, 9, 8, 4,
           9, 9, 2, 1, 3, 7, 6, 5, 4, 6, 1, 1, 2, 3, 3, 2, 1, 0, 3, 8, 2, 7 ]
    l = len(ln)
    idx_o = 0
    out= [0]*l
    while (idx < l):
        (idx,out[idx_o]) = resolve(ln[idx:], idx)
        idx_o+=1
    for i in range(0,idx_o): 
        print(out[i],end='')
    print()
    return 0
main()

after running the above python code we get some integer output 311329622193015237 and the flag is flag{311329622193015237}

Initially i thought that it would be hard to solve, mostly because of the low number of solves, but it came out pretty easy.

It was a really good challenge :)