Cursed app
104
If we want to say 100, should we start at 1 and count until 100?
Download: cursed_app.txz
This is a reversing challenge, we’ll analyze it in Ghidra.
Decompilation of the code and a quick inspection brings up the following interesting function:
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
...
undefined8 FUN_001010e0(undefined8 param_1,long param_2)
{
...
if (iVar2 != 0) {
puts("please locate license file, run ./app license_key");
/* WARNING: Subroutine does not return */
exit(0);
}
__stream = fopen(*(char **)(param_2 + 8),"r");
if (__stream != (FILE *)0x0) {
fseek(__stream,0,2);
lVar3 = ftell(__stream);
fseek(__stream,0,0);
__ptr = (char *)malloc((long)(int)lVar3);
if (__ptr != (char *)0x0) {
fread(__ptr,1,(long)(int)lVar3,__stream);
}
fclose(__stream);
iVar2 = ((int)*__ptr * 0xaf + 0x91) % 0x100;
if (((((((((iVar2 * iVar2 * 0x164 + 0x202 + iVar2 * 0xeb) % (iVar2 * 0x67 + 2) == 0) &&
(iVar2 = ((int)__ptr[1] * 0x5d + 0xda) % 0x100,
(iVar2 * iVar2 * 0x3da + 0x354 + iVar2 * 0x3c) % (iVar2 * 0x56 + 0x35f) == 0)) &&
(iVar2 = ((int)__ptr[2] * 5 + 0x95) % 0x100,
(iVar2 * iVar2 * 0x19e + 0x3aa + iVar2 * 0x49) % (iVar2 * 0xb9 + 0xb2) == 0)) &&
(((iVar2 = ((int)__ptr[3] * 0x35 + 0xd4) % 0x100,
(iVar2 * iVar2 * 0x210 + 0xba + iVar2 * 0x20c) % (iVar2 * 0x7e + 0x38) == 0 &&
...
(iVar2 = ((int)__ptr[0x3a] * 0x79 + 0x25) % 0x100,
(iVar2 * iVar2 * 0x2a9 + 0x349 + iVar2 * 0x203) % (iVar2 * 7 + 0xbb) == 0)))))) {
puts("Congratz! You got the correct flag!!");
bVar1 = true;
}
if (!bVar1) {
puts("Bummer! You got the wrong flag!!");
}
return 0;
}
...
Essentially it asks for a file, reads it in and checks checksums of 0x3b
characters to make sure they are correct.
As we look at the expressions in the big “if” statement it becomes obvious that the checksums of individual characters are independent of each other, and we can bruteforce each character seperately. All expressions have the same structure, so with a bit of editing we can build a table out of them and process characters one by one:
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
rules = [
[0xaf, 0x91, 0x164, 0x202, 0xeb, 0x67, 2],
[0x5d, 0xda, 0x3da, 0x354, 0x3c, 0x56, 0x35f],
[5, 0x95, 0x19e, 0x3aa, 0x49, 0xb9, 0xb2],
[0x35, 0xd4, 0x210, 0xba, 0x20c, 0x7e, 0x38],
[0xb5, 0xd, 0x26a, 0x3ce, 0x130, 8, 0x27f],
[0x5b, 2, 5, 0x4b, 0x2f7, 0x30e, 0x55],
[0x43, 0x76, 0x37d, 0x1f1, 0xed, 0x106, 0xdd],
[0xe7, 0x74, 0x213, 0x3e5, 0x287, 0xf5, 0x184],
[0x77, 0xdf, 0x228, 0x2ce, 0x1e7, 10, 0x22a],
[0xcb, 0x88, 0x336, 0x3bd, 0x95, 0x78, 0x230],
[0x51, 0x96, 0x9d, 0x21a, 0x2b0, 0x144, 0x265],
[0x29, 0x8d, 0x56, 0xcb, 0x2db, 0x15, 0x203],
[0x73, 0x5f, 0x2df, 0x88, 0x178, 0x116, 0x262],
[0xf3, 0xe4, 0x31b, 0x37c, 0xdd, 0xca, 0x33b],
[0x4f, 0x51, 0x66, 0x366, 0x345, 0x234, 0xf9],
[0x7b, 0x8e, 0x12e, 0x282, 0x2b0, 5, 0xd5],
[0xa9, 0x59, 0xe, 0x2a8, 0x272, 0x96, 0x1c8],
[0xad, 0xe6, 0x33e, 0x12e, 0x214, 0x19f, 0x1f1],
[0xab, 0x9a, 0x10f, 0xe2, 0x72, 0x20, 0x292],
[0x4b, 0xb8, 0x366, 0x39, 0x35a, 0x37d, 0x1a8],
[0xf5, 0x5b, 0x375, 0x9d, 0x2f3, 0x6a, 0x3d7],
[0xed, 0x22, 0x36c, 0x173, 0x189, 0x66, 0x196],
[0x3d, 0x69, 0x3cb, 0x214, 0x3c0, 0x3e, 0x390],
[0x9f, 0x2c, 0x215, 0x7a, 0x1d8, 0x29, 0x32],
[0x77, 0xef, 0xa7, 0x308, 0x21f, 0x38, 0x290],
[0xb3, 0x70, 0xf8, 0x19e, 0x3ce, 0x87, 0x52],
[0x47, 0xae, 0x2f3, 0x115, 0x1cf, 10, 0x113],
[0xbf, 0x90, 0xe3, 0x234, 0x2a6, 0x37, 0x27a],
[0x51, 0x9b, 0x379, 0x330, 0x210, 0x173, 0x2ea],
[0x57, 200, 0x14d, 0x25, 0x2e0, 0x2e6, 0xd],
[0xa7, 0xa0, 0x27c, 0xd5, 200, 0x382, 0x265],
[0xe7, 0x66, 0x300, 0x2e2, 0x1a, 0x18a, 0x3e1],
[0x71, 0xd9, 0x8a, 0xfc, 0x34b, 0x14d, 0x244],
[0xaf, 9, 0x1ae, 0x2cb, 0x164, 0x69, 0x1fc],
[0xdb, 0xa6, 0xac, 0x32c, 0x2ca, 2, 0x124],
[0xb3, 0x39, 0x358, 0x2b9, 0x3be, 0x1f1, 0x3be],
[0x97, 0x1b, 0x394, 0x15, 0x397, 0x4b, 699],
[0x3d, 0xf0, 0x141, 0x1ec, 0x3b9, 0x78, 0x199],
[0x29, 0x76, 0x7b, 0x3c4, 0x10c, 0x4a, 0x14e],
[0x2d, 0x96, 0x264, 0x16c, 0x210, 0xd, 0x27d],
[0x4f, 0xd7, 0xd6, 0x3a6, 0x28, 0x3ba, 0xa6],
[0x3f, 0xa0, 0x388, 0x34d, 0x15a, 0xf0, 0x3d],
[0xd3, 0x72, 0x22f, 0x299, 0x22a, 0x93, 0x379],
[0x79, 2, 0x2cf, 0x32b, 0x3df, 0x82, 0x195],
[0x75, 0xe6, 0x21d, 300, 0x134, 0x27, 0x29],
[0x51, 0x52, 0x234, 0x229, 0x253, 0x23, 0x205],
[0x55, 0xa3, 0x3b0, 0x3b0, 0xe3, 0x8a, 0xd9],
[0xed, 0xa5, 0x203, 0x14b, 0x306, 0x24, 0x28c],
[0x81, 0x7f, 0x362, 0x14, 0x1a4, 0xb, 0x15a],
[0x19, 0xeb, 0xb8, 0x140, 0x67, 0x211, 0x17e],
[0x9b, 0x3a, 0x357, 0xa0, 0x33c, 0x46, 0x10e],
[0x55, 0xf0, 0x3b7, 0xd5, 0x234, 10, 0x207],
[0x49, 0x3d, 0x282, 0x362, 0x79, 7, 0x142],
[0x81, 0x56, 0x3d, 0x181, 0x326, 0x17, 0x14f],
[0x9b, 0xb1, 399, 0x24, 0xc4, 0x65, 0xda],
[0x99, 0x7e, 0x360, 0x2aa, 0x116, 0x3c, 0x142],
[0xe3, 0xf5, 0x123, 0x1f8, 0x152, 0x51, 700],
[0xc3, 0x16, 0x300, 0x13, 0x3ca, 0x148, 0x1e1],
[0x79, 0x25, 0x2a9, 0x349, 0x203, 7, 0xbb]]
out = ""
for x in rules:
for c in range(256):
v = (c * x[0] + x[1]) % 0x100
if (v * v * x[2] + x[3] + v * x[4]) % (v * x[5] + x[6]) == 0:
out += chr(c)
break
print out
When we run the script we quickly get the flag: ASIS{y0u_c4N_s33_7h15_15_34513R_7h4n_Y0u_7h1nk_r16h7?__!!!}
.