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:1
�RSTU'��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 :)