NiNi's Den

2018::ASIS-Quals::reverse

Word count: 996Reading time: 6 min
2018/05/04 Share

Another excuse, I had my wisdom tooth extracted, or I could solve them(rev) all.

WarmUp

Obviously, it’s a C program which was compacted to one line with some #define.
After formatted, it looks like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <stdint.h>
#define M 37
#define q (2+M/M)
#define v (q/q)
#define ef ((v+q)/2)
#define f (q-v-ef)
#define k (8-ef)
struct b {
int64_t y[13];
} S;
int m = 1811939329, N = 1, t[1 << 26] = {2}, a, * p, i, e = 73421233, s, c, U = 1;
g(d, h) {
for (i = s; i < 1 << 25; i *= 2) d = d * 1 LL * d % m;
for (p = t; p < t + N; p += s)
for (i = s, c = 1; i; i--) a = p[s] * (h ? c : 1 LL) % m, p[s] = (m * 1 U + * p - a) * (h ? 1 LL : c) % m, * p = (a * 1 U + * p) % m, p++, c = c * 1 LL * d % m;
}
l() {
while (e /= 2) {
N *= 2;
U = U * 1 LL * (m + 1) / 2 % m;
for (s = N; s /= 2;) g(136, 0);
for (p = t; p < t + N; p++) * p = * p * 1 LL * * p % m * U % m;
for (s = 1; s < N; s *= 2) g(839354248, 1);
for (a = 0, p = t; p < t + N;) a += * p << (e & 1), * p++ = a % 10, a /= 10;
}
}
z(n) {
int y = 3, j, c;
for (j = 2; j <= n;) {
l();
for (c = 2; c <= y - 1; c++) {
l();
if (y % c == 0) break;
}
if (c == y) {
l();
j++;
}
y++;
}
l();
return y - 1;
}
main(a, pq) char * pq; {
int b = sizeof(S), y = b, j = M;
l();
int x[M] = {
b - M - sizeof((short int) a),
(b >> v) + (k << v) + (v << (q | ef)) + z(v + (ef << v)),
(z(k * ef) << v) - pow(ef, f),
z(((j - ef * k) | (ef << k >> v) / k - ef << v) - ef),
(((y + M) & b) << (k / q + ef)) - z(ef + v),
((ef << k) - v) & y,
y * v + v,
(ef << (q * ef - v - (k >> ef))) * q - v,
(f << q) | (ef << (q * f + k)) - j + k,
(z(z(z(z(z(v))))) * q) & (((j / q) - (ef << v)) << q) | (j + (q | (ef << v))),
y | (q + v),
(ef << ef) - v + ef * (((j >> ef) | j) - v + ef - q + v),
(z(j & (b << ef)) & (z(v << v) << k)) - (q << v) - q,
(k << q) + q,
(z(y) >> (ef << v)) + (z(k + v)) - q,
(z(z(k & ef | j)) & b | ef | v << f << q << v & ef >> k | q << ef << v | k | q) + z(v << v) + v,
(ef >> v) * q * z(k - v) + z(ef << ef & q | k) + ef,
z(k << k) & v & k | y + k - v,
z(f >> ef | k >> ef | v | k) * (ef >> v) * q,
(ef << k - ef << v >> q << ef * ef) - j + (ef << v),
z(ef * k) * z(v << v) + k - v,
z((z(k) << z(v))) & y | k | v,
z(ef << ef << v << v) / ef + z(v << ef | k | (b >> q) & y - f) - (ef << q) + (k - v) - ef,
k << (ef + q) / z(ef) * z(q) & z(k << k) | v,
((z(y | j >> k * ef)) % ef << z(v << v << v) >> q << q | j) / ef + v,
(j - ef << ef << v * z(v >> v << v) >> ef) / ef % z(k << j) + q,
z(k - v) + k | z(ef << k >> v << f) - z(q << q) * ef >> v,
(z(ef | y & j | k) % q | j + ef << z(k | ef) % k << q | ef | k << ef << q / ef | y / ef + j >> q) & k << j | ef + v,
84,
z(v * ef << ef << q) * q % ef << k | k | q - v,
((z(20) * v) | (f >> q) | (k << k)) / ef - (ef << (v * q + ef)) - (k << q) + z(k) - q
};
while (j--) {
putchar(x[M - v - j]);
}
printf(" From ASIS With Love <3\n");
return 0;
}

It just do some calculate then ouput the flag, but it took lots of time.I found that function l and function g, they are basically doing nothing.I deleted the function l, g ,and local variables int m = 1811939329, N = 1, t[1 << 26] = {2}, a, * p, i, e = 73421233, s, c, U = 1;,after compilation & execution, the flag popped out immediately.

Baby C

This binary was obfuscated by movfuscator, and it’s my first time to solve such challenge, so that I did not realize that this was obfuscated at first time……

Using gdb, I found that uses sigaction to register callback function for SIGSEGV, SIGILL, then the binary will try to trigger them by accessing invalid address, so the binary can jump into libc to execute strncmp to compare that wether the input[3:14] equals to m0vfu3c4t0r! or not.

I used demovfuscator to deobfuscate the binary, but there were still so much mov in binary. I thought the discription of challenge, This babyc needed swaddling!,means that it used movfuscator more than one time,but I was wrong….
Since the tool is still in development phase, I only used the function to generate flow chat.
flow.png
(You can solve this challenge without any deobfuscator, it’s not so hard)

Before every branch, the corresponding char would show up many times. So I got the flag.

Echo

Putting it into IDA, I realized that this is actually a brainfuck interpretor.And I found a flag string in binary.

Also, I found the brainfuck hard coded in this binary by gdb:

1
>>[<+<+>>-]<<[->>+<<]>[>>>>>+<<<<<-]<>>>[<<+<+>>>-]<<<[->>>+<<<]>[>>>>>>+<<<<<<-]<>>>>[<<<+<+>>>>-]<<<<[->>>>+<<<<]>[>>>>>>>+<<<<<<<-]<>>>>>[<<<<+<+>>>>>-]<<<<<[->>>>>+<<<<<]>[>>>>>>>>+<<<<<<<<-]<>>[<+<+>>-]<<[->>+<<]>[>>>>>>>>>+<<<<<<<<<-]<>>>[<<+<+>>>-]<<<[->>>+<<<]>[>>>>>>>>>>+<<<<<<<<<<-]<>>>>[<<<+<+>>>>-]<<<<[->>>>+<<<<]>[>>>>>>>>>>>+<<<<<<<<<<<-]<>>>>>[<<<<+<+>>>>>-]<<<<<[->>>>>+<<<<<]>[>>>>>>>>>>>>+<<<<<<<<<<<<-]<>>[<+<+>>-]<<[->>+<<]>[>>>>>>>>>>>>>+<<<<<<<<<<<<<-]<>>>[<<+<+>>>-]<<<[->>>+<<<]>[>>>>>>>>>>>>>>+<<<<<<<<<<<<<<-]<>>>>[<<<+<+>>>>-]<<<<[->>>>+<<<<]>[>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<-]<>>>>>[<<<<+<+>>>>>-]<<<<<[->>>>>+<<<<<]>[>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<-]<>>[<+<+>>-]<<[->>+<<]>[>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<-]<>>>[<<+<+>>>-]<<<[->>>+<<<]>[>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<-]<>>>>[<<<+<+>>>>-]<<<<[->>>>+<<<<]>[>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<-]<>>>>>[<<<<+<+>>>>>-]<<<<<[->>>>>+<<<<<]>[>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<-]<>>[<+<+>>-]<<[->>+<<]>[>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<-]<>>>[<<+<+>>>-]<<<[->>>+<<<]>[>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<-]<>>>>[<<<+<+>>>>-]<<<<[->>>>+<<<<]>[>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<-]<>>>>>[<<<<+<+>>>>>-]<<<<<[->>>>>+<<<<<]>[>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<-]<>>[<+<+>>-]<<[->>+<<]>[>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<-]<>>>[<<+<+>>>-]<<<[->>>+<<<]>[>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<-]<>>>>[<<<+<+>>>>-]<<<<[->>>>+<<<<]>[>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<-]<>>>>>[<<<<+<+>>>>>-]<<<<<[->>>>>+<<<<<]>[>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<-]<>>[<+<+>>-]<<[->>+<<]>[>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<-]<>>>[<<+<+>>>-]<<<[->>>+<<<]>[>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<-]<>>>>>>>[+]>[+]>[+]>[+]>[+]>[+]>[+]>[+]>[+]>[+]>[+]>[+]>[+]>[+]>[+]>[+]>[+]>[+]>[+]>[+]>[+]>[+]>[+]>[+]>[+]><<<<<<<<<<<<<<<<<<<<<<<<<,[.,]

It’s not so hard to find out that this brainfuck code will decode the flag in binary, and there is a loop [.,] to implement echo in the end.

This part is trap, the brainfuck code [+]>[+]>[+]>[+]>[+]>[+]>[+]>[+]>[+]>[+]>[+]>[+]>[+]>[+]>[+]>[+]>[+] is equivalent to:

1
2
3
4
5
6
7
8
9
10
while( *char ){
++*char;
}
char += 1;
while( *char ){
++*char;
}
char += 1;
...so on

It set the chars in flag to 0, remove it to get the flag.

Density

It just use some rule to expand the original input(with random string), then encoded them with base 64.

Left or Right?

There were so much Rust reverseing challenge recently…
I am still too slow to analyze such program.

They are not so hard ・゜・(PД`q。)・ ゜・

Blame on my wisdom teeth.

Original Author: Terrynini

Original link: http://blog.terrynini.tw/en/2018-ASIS-Quals-reverse/

Publish at: May 4th 2018, 3:00:11

Copyright: This article is licensed under CC BY-NC 4.0

CATALOG
  1. 1. WarmUp
  2. 2. Baby C
  3. 3. Echo
  4. 4. Density
  5. 5. Left or Right?