| tags:rev automation categories:Writeups series:midnight sun 2022
Midnight Sun CTF 2022 - REVVER writeup
Challenge Description
nc revver-01.hfsc.tf 3320
Automated reversing is a solved problem, right.
Solution
This was a pretty sad challenge (had too many problems).
First we connect to server to get the welcome message:
If we ask for a binary, we get something like this:
Server generates random shellcodes and we have to find the correct “answer” to them.
There are 20
different binaries. Each time, server randomizes the constant data
inside the shellcode, while keeping the same structure. That is, all binaries named
seven
have the exact same structure, but their constant data are different.
The first challenge is to determine if the shellcode is x86 or x64. We pick a
random binary (nine
in our case) and we check a random decompiled function:
As x64:
__int64 __fastcall sub_4EF(__int64 a1)
{
int v1; // eax
unsigned int v2; // esp
__int64 v3; // rbp
unsigned int v4; // eax
__int64 v6; // [rsp+0h] [rbp-14h] BYREF
v3 = v2;
*(_DWORD *)(v3 - 8) = v1;
*(_DWORD *)(v2 - 12LL) = sub_C(a1, (*(_DWORD *)(v3 - 8) + 4099) & 0xFFFFF000, 0LL, 12);
*(_DWORD *)(v2 - 4LL) = 192;
v6 = *(unsigned int *)(v2 - 12LL);
v4 = *(_DWORD *)(v2 - 4LL);
_InterlockedExchange((volatile __int32 *)&v6, v3);
__asm { int 80h; LINUX - }
*(_DWORD *)v4 = *(_DWORD *)(v6 - 8);
return v4 + 4;
}
And as x86:
// write access to const memory has been detected, the output may be wrong!
__int64 __usercall sub_4EF@<edx:eax>(int a1@<eax>)
{
__int32 v2; // [esp+0h] [ebp-10h] BYREF
int v3; // [esp+4h] [ebp-Ch]
int v4; // [esp+8h] [ebp-8h]
int v5; // [esp+Ch] [ebp-4h]
__int128 savedregs; // [esp+10h] [ebp+0h] BYREF
v4 = a1;
v3 = sub_C(0, 0, 12);
v5 = 192;
v2 = v3;
_InterlockedExchange(&v2, (__int32)&savedregs);
__asm { int 80h; LINUX - }
loc_C0 = *(_DWORD *)(v2 - 8);
return 0x7000000C4LL;
}
Obviously, the x86 version makes much more sense, so we have to deal with x86 shellcodes.
The next step is to analyze each of the shellcodes. Some shellcodes are broken (i.e., if we execute them they will crash as they depend on some registers whose values are unknown). However, shellcodes are very simple, so we can reverse them just by looking at them.
Among the 20
different binaries, there are only 5
different types of shellcodes, with each one
appearing exactly 4
times, in intervals of 5
. Below we analyze each shellcode type.
Type #1: Constant String in .rodata
Binaries: five
, ten
, fiveteen
, twenty
.
This is the simplest case. The answer is a just a random, constant string located at the end of the shellcode:
void __noreturn sub_0() {
int v0; // ecx
int v1; // ebx
void *v2; // eax
char v3[48]; // [esp+0h] [ebp-30h] BYREF
v0 = sys_open("swag.key", 2, 0);
if ( !v0 )
{
sub_5F9();
sys_exit(-1);
}
sub_54A((int)v3, 45, v0);
v1 = 0;
v2 = (void *)sub_625(45);
qmemcpy(v2, "61fEALbiiK9O5o1tFcUv9qwZ2Ai9JN41YHkrVfS2eW1H1", 0x2Du);
if ( !u_strcmp((int)v2, (int)v3) )
v1 = 1;
sys_exit(v1);
}
The challenge here, is to locate that constant string in the shellcode. We know that all data are located at the end of the shellcode, so we start processing the shellcode backwards, until we hit the code. The last function in all binaries, always has the same epilogue:
A) seg000:0000037B C9 leave
seg000:0000037C 5F pop edi
seg000:0000037D 5E pop esi
seg000:0000037E 5B pop ebx
seg000:0000037F C3 retn
B) seg000:0000059C C9 leave
seg000:0000059D C3 retn
Therefore, the first occurence of the sequence C3 .* C9
(working backwards) indicates the end of
shellcode data. Strings are null terminated, so we split data on NULL bytes. Some binaries
contain more than one constant strings, such as:
flag.txt
/midnightsunctf-2022/quals/revver/answer3.bin
Error!\n
%s
We create a blacklist with all known strings appear in the binaries. After we drop all blacklisted strings, there should be exactly one string left which is our answer, for example:
4bdTE1flxSsX1FGTO1H2hDGMtM0EbtgtAiFA97coYg6ZCMWJDbFHHrzoprOdcp0Q3I
Type #2: Constant in mov instructions, XOR
Binaries: one
, six
, eleven
, sixteen
.
In this type, the answer is stored byte-by-byte into a sequence of mov
instructions
and then is XORed with an 1-byte key:
void __noreturn sub_0() {
int v0; // edi
int i; // esi
int v2; // ebx
int j; // edx
char v4; // al
char v5[12]; // [esp+0h] [ebp-18h]
char v6[6]; // [esp+Ch] [ebp-Ch] BYREF
char v7[4]; // [esp+12h] [ebp-6h] BYREF
char addr[2]; // [esp+16h] [ebp-2h] BYREF
v0 = sys_open("flag.txt", 2, 0);
if ( !v0 )
{
sub_51C(v5[0]);
sub_548(-1);
}
for ( i = 0; i < 10; ++i )
{
if ( sys_read(v0, addr, 1u) > 0 )
v4 = addr[0];
else
v4 = -1;
v5[i] = v4;
}
v2 = 1;
qmemcpy(v6, "\"1In]", 5);
v6[5] = 127;
qmemcpy(v7, "Sk9|", sizeof(v7));
for ( j = 0; j < 10; ++j )
{
if ( ((unsigned __int8)v5[j] ^ 0xC) != v6[j] )
v2 = 0;
}
sub_548(v2);
}
If we take a look at the assembly we can see the pattern:
seg000:00000049 mov [ebp+var_C], 22h ; '"'
seg000:0000004D mov [ebp+var_B], 31h ; '1'
seg000:00000051 mov [ebp+var_A], 49h ; 'I'
seg000:00000055 mov [ebp+var_9], 6Eh ; 'n'
seg000:00000059 mov [ebp+var_8], 5Dh ; ']'
seg000:0000005D mov [ebp+var_7], 7Fh
seg000:00000061 mov [ebp+var_6], 53h ; 'S'
seg000:00000065 mov [ebp+var_5], 6Bh ; 'k'
seg000:00000069 mov [ebp+var_4], 39h ; '9'
seg000:0000006D mov [ebp+var_3], 7Ch ; '|'
seg000:00000071 xor edx, edx
seg000:00000073
...
seg000:00000085 xor cl, 0Ch
To extract these values, we use capstone to get a disassembly listing of the shellcode and the we use regural expressions. Once we have all data we do the XOR.
Type #3: Constant in mov instructions, SUB
Binaries: four
, nine
, fourteen
, nineteen
.
This case is similar to the previous one:
int sub_5A0() {
char *v0; // esi
signed int i; // ebx
int v2; // edi
signed int j; // ecx
__int16 A[36]; // [esp+0h] [ebp-98h]
__int16 B[36]; // [esp+48h] [ebp-50h]
unsigned int v8; // [esp+94h] [ebp-4h]
if ( !sub_4EE(0, 2) )
{
sub_504(A[0]);
sub_595();
}
v0 = (char *)sub_530();
memset(v0, 255, 0x48u);
for ( i = 0; i < (int)strlen(v0); ++i )
v0[i] = sub_4A0();
v8 = strlen(v0);
v2 = 1;
A[0] = 0xC36D;
A[1] = 0xCFD4;
A[2] = 0xD539;
A[3] = 0xDC5A;
A[4] = 0xEA9C;
A[5] = 0xFDC6;
A[6] = 0xEEC5;
A[7] = 0xDD2E;
A[8] = 0xD6E2;
A[9] = 0xE5F6;
A[10] = 0xC7D8;
A[11] = 0xF0AB;
A[12] = 0xE6E7;
A[13] = 0xC402;
A[14] = 0xF1A2;
A[15] = 0xD3A6;
A[16] = 0xC175;
A[17] = 0xC38F;
A[18] = 0xF783;
A[19] = 0xD90D;
A[20] = 0xFDBA;
A[21] = 0xE9DB;
A[22] = 0xCC78;
A[23] = 0xEB3E;
A[24] = 0xC306;
A[25] = 0xE44A;
A[26] = 0xE101;
A[27] = 0xC42A;
A[28] = 0xFD9D;
A[29] = 0xC980;
A[30] = 0xC8A6;
A[31] = 0xC2FA;
A[32] = 0xC116;
A[33] = 0xFADE;
A[34] = 0xEC4F;
A[35] = 0xE081;
B[0] = 0x34C0;
B[1] = 0x423D;
B[2] = 0x25B3;
B[3] = 0x29A5;
B[4] = 0x4FFD;
B[5] = 0x7540;
B[6] = 0x563D;
B[7] = 0x4FA6;
B[8] = 0x2B39;
B[9] = 0x3D38;
B[10] = 0x1E52;
B[11] = 0x48F7;
B[12] = 0x534E;
B[13] = 0x3278;
B[14] = 0x6011;
B[15] = 0x1908;
B[16] = 0x8EC;
B[17] = 0x2CFD;
B[18] = 0x50FA;
B[19] = 0x2981;
B[20] = 0x6E05;
B[21] = 0x531D;
B[22] = 0x1EE5;
B[23] = 0x2F94;
B[24] = 0x2C4C;
B[25] = 0x37A2;
B[26] = 0x5475;
B[27] = 0x898;
B[28] = 0x49F4;
B[29] = 0x42C6;
B[30] = 0x4120;
B[31] = 0x393E;
B[32] = 0x3965;
B[33] = 0x4C4F;
B[34] = 0x65A4;
B[35] = 0x39E5;
for ( j = 0; j < (int)(v8 / 2); ++j )
{
if ( A[j] + v0[2 * j + 1] != B[j] )
v2 = 0;
}
return v2;
}
If we look at the assembly, we can see that the constants are stored in mov
instructions:
seg000:00000639 mov [ebp+A], 0C36Dh
seg000:00000642 mov [ebp+var_96], 0CFD4h
seg000:0000064B mov [ebp+var_94], 0D539h
seg000:00000654 mov [ebp+var_92], 0DC5Ah
seg000:0000065D mov [ebp+var_90], 0EA9Ch
seg000:00000666 mov [ebp+var_8E], 0FDC6h
seg000:0000066F mov [ebp+var_8C], 0EEC5h
seg000:00000678 mov [ebp+var_8A], 0DD2Eh
seg000:00000681 mov [ebp+var_88], 0D6E2h
seg000:0000068A mov [ebp+var_86], 0E5F6h
seg000:00000693 mov [ebp+var_84], 0C7D8h
seg000:0000069C mov [ebp+var_82], 0F0ABh
seg000:000006A5 mov [ebp+var_80], 0E6E7h
seg000:000006AB mov [ebp+var_7E], 0C402h
seg000:000006B1 mov [ebp+var_7C], 0F1A2h
seg000:000006B7 mov [ebp+var_7A], 0D3A6h
seg000:000006BD mov [ebp+var_78], 0C175h
seg000:000006C3 mov [ebp+var_76], 0C38Fh
seg000:000006C9 mov [ebp+var_74], 0F783h
seg000:000006CF mov [ebp+var_72], 0D90Dh
seg000:000006D5 mov [ebp+var_70], 0FDBAh
seg000:000006DB mov [ebp+var_6E], 0E9DBh
seg000:000006E1 mov [ebp+var_6C], 0CC78h
seg000:000006E7 mov [ebp+var_6A], 0EB3Eh
seg000:000006ED mov [ebp+var_68], 0C306h
seg000:000006F3 mov [ebp+var_66], 0E44Ah
seg000:000006F9 mov [ebp+var_64], 0E101h
seg000:000006FF mov [ebp+var_62], 0C42Ah
seg000:00000705 mov [ebp+var_60], 0FD9Dh
seg000:0000070B mov [ebp+var_5E], 0C980h
seg000:00000711 mov [ebp+var_5C], 0C8A6h
seg000:00000717 mov [ebp+var_5A], 0C2FAh
seg000:0000071D mov [ebp+var_58], 0C116h
seg000:00000723 mov [ebp+var_56], 0FADEh
seg000:00000729 mov [ebp+var_54], 0EC4Fh
seg000:0000072F mov [ebp+var_52], 0E081h
seg000:00000735 mov [ebp+B], 34C0h
seg000:0000073B mov [ebp+var_4E], 423Dh
seg000:00000741 mov [ebp+var_4C], 25B3h
seg000:00000747 mov [ebp+var_4A], 29A5h
seg000:0000074D mov [ebp+var_48], 4FFDh
seg000:00000753 mov [ebp+var_46], 7540h
seg000:00000759 mov [ebp+var_44], 563Dh
seg000:0000075F mov [ebp+var_42], 4FA6h
seg000:00000765 mov [ebp+var_40], 2B39h
seg000:0000076B mov [ebp+var_3E], 3D38h
seg000:00000771 mov [ebp+var_3C], 1E52h
seg000:00000777 mov [ebp+var_3A], 48F7h
seg000:0000077D mov [ebp+var_38], 534Eh
seg000:00000783 mov [ebp+var_36], 3278h
seg000:00000789 mov [ebp+var_34], 6011h
seg000:0000078F mov [ebp+var_32], 1908h
seg000:00000795 mov [ebp+var_30], 8ECh
seg000:0000079B mov [ebp+var_2E], 2CFDh
seg000:000007A1 mov [ebp+var_2C], 50FAh
seg000:000007A7 mov [ebp+var_2A], 2981h
seg000:000007AD mov [ebp+var_28], 6E05h
seg000:000007B3 mov [ebp+var_26], 531Dh
seg000:000007B9 mov [ebp+var_24], 1EE5h
seg000:000007BF mov [ebp+var_22], 2F94h
seg000:000007C5 mov [ebp+var_20], 2C4Ch
seg000:000007CB mov [ebp+var_1E], 37A2h
seg000:000007D1 mov [ebp+var_1C], 5475h
seg000:000007D7 mov [ebp+var_1A], 898h
seg000:000007DD mov [ebp+var_18], 49F4h
seg000:000007E3 mov [ebp+var_16], 42C6h
seg000:000007E9 mov [ebp+var_14], 4120h
seg000:000007EF mov [ebp+var_12], 393Eh
seg000:000007F5 mov [ebp+var_10], 3965h
seg000:000007FB mov [ebp+var_E], 4C4Fh
seg000:00000801 mov [ebp+var_C], 65A4h
seg000:00000807 mov [ebp+var_A], 39E5h
We first extract all constants using capstone + regular expressions. Then we know that the
first half belongs to array A
and the next half to array B
. We substract them and we
get the plaintext. For example:
1159 - CE15 = 4344
5792 - E720 = 7072
2CF4 - C29E = 6A56
68B6 - EF62 = 7954
41E0 - FB8A = 4656
305 - C1AC = 4159
363C - C1D1 = 746B
5A9B - E223 = 7878
6042 - EED3 = 716F
4DC6 - FF6F = 4E57
6288 - EF35 = 7353
A5B - C80C = 424F
604D - F20A = 6E43
6165 - FAF1 = 6674
3570 - DD1B = 5855
31EE - CE8C = 6362
35DD - E683 = 4F5A
4F2E - DFB5 = 6F79
2FC3 - D870 = 5753
2E24 - CCDC = 6148
24A4 - DE2B = 4679
31BC - CA79 = 6743
4960 - D3F0 = 7570
2934 - E3CA = 456A
Answer (in ASCII): CDprjVyTFVAYtkxxqoNWsSBOnCftXUcbOZoyWSaHFygCupEj
Type #4: RC4 Decryption
Binaries: three
, eight
, thirteen
, eighteen
.
This type is a vanilla RC4 decryption:
int sub_79D() {
int fd; // ebx
void *v1; // edx
int v2; // ebx
int *target_hash; // edx
char v5[260]; // [esp+0h] [ebp-108h] BYREF
char *v6; // [esp+104h] [ebp-4h]
fd = sys_open(0, 2, "/midnightsunctf-2022/quals/revver/answer3.bin");
if ( !fd )
{
sub_701(v5[0]); // garbage
sys_exit(-1);
}
v1 = sub_72D(28);
memset(v1, 255, 0x1Cu);
v6 = u_read_from_file(v1, strlen(v1), fd);
u_do_rc4(v5, "isuGZEJzYCbVkzEaY", strlen("isuGZEJzYCbVkzEaY"));
u_do_xor(strlen(v6), v6, v5);
v2 = 0;
target_hash = sub_72D(28);
qmemcpy(target_hash, &dword_8AF, 0x1Cu);
if ( !u_strcmp(v6, target_hash) )
return 1;
return v2;
}
The only challenge is to find the ciphertext and the key. Both of them are “data”, so they are stored at the end of the shellcode. The heuristic here, is that the key is always ASCII-printable and the ciphertext is not. After dropping all blacklisted strings, we should be left with one printable and one nonprintable string. For example:
RC4 decryption key: FabBlhzcdYBRZuARz
RC4 ciphertext: '|çe[z¦Ýf\x94ÍZG8¼ä¡¡ý©ºÏ\x9c'
RC4 plaintext: lNjsMMkIxEzjfWwUQYZbNg
However, there is one caveat here: A ciphertext may contain a NULL byte. In that case, our script will mistakenly split it into two (or more) ciphertexts. In that case, we simply merge all nonprintable strings into one and we do the decryption.
Type #5: CRC32 Crack
Binaries: two
, seven
, twelve
, seventeen
.
This is the final and the most difficult case:
_BOOL4 sub_D4()
{
char v1[104]; // [esp+0h] [ebp-6Ch] BYREF
char *v2; // [esp+68h] [ebp-4h] BYREF
memset(&v1[100], 0, 0x64u);
v2 = v1;
sys_getcwd((char *)&v2, 0x15u);
return sub_E((int)v1, 0x15u) == 0x7E195C06;
}
int __usercall sub_E@<eax>(int a1@<eax>, unsigned int a2@<edx>)
{
unsigned int i; // esi
unsigned int v4; // edi
int j; // ecx
unsigned int v6; // esi
unsigned int k; // eax
int v9[256]; // [esp+0h] [ebp-404h]
int v10; // [esp+400h] [ebp-4h]
v10 = 0xEDB88320;
for ( i = 0; i < 0x100; ++i )
{
v4 = i;
for ( j = 8; j; --j )
{
if ( (v4 & 1) != 0 )
v4 = v10 ^ (v4 >> 1);
else
v4 >>= 1;
}
v9[i] = v4;
}
v6 = -1;
for ( k = 0; k < a2; ++k )
v6 = v9[(unsigned __int8)(*(_BYTE *)(k + a1) ^ v6)] ^ (v6 >> 8);
return ~v6;
}
Here, we have to give a string of specific input (here 0x15
bytes) whose CRC32 checksum
is equal to a constant value (here 0x7E195C06
). Cracking CRC32 is not hard and be done
either using a z3 solver, or the
old school
way (we use the second).
To extract the target CRC32 and the input size, we use capstone + regular expressions as
before (we look for a constant in a mov
followed by a push
):
seg000:000000FF xor ebx, ebx
seg000:00000101 mov esi, 14F123CEh
seg000:00000106 lea eax, [ebp+var_6C]
seg000:00000109 push 16h
seg000:0000010B pop edx
seg000:0000010C call sub_E
However, if our answer contains non ASCII characters, server throws a unicode related exception:
Traceback (most recent call last):
File "./challenge.py", line 245, in <module>
main()
File "./challenge.py", line 241, in main
play()
File "./challenge.py", line 206, in play
if len(xxx) == value[1] and value[0] == (zlib.crc32(bytes(xxx,'utf-8')) & 0xffffffff):
UnicodeEncodeError: 'utf-8' codec can't encode character '\udca6' in position 21: surrogates not allowed
The best way to deal with this problem is to simply not generate answers with non ASCII characters. We keep generating random solutions until we find a good one. For example:
[+] Target CRC32: 14F123CEh
[+] Input size: 22
[+] Generating random string: YCFV8AQWRIXSX5M8WG
[+] Current CRC32: 56DFC86A
[+] CRC32 successfully cracked: BF-65-D0-90
[+] Generating random string: FNZM26F43QGD2DFQ54
[+] Current CRC32: AEEAA64C
[+] CRC32 successfully cracked: 99-0B-E5-68
[+] Generating random string: D0ZZ6NTVI4MVZLAH47
[+] Current CRC32: 0CF651C9
[+] CRC32 successfully cracked: 1C-FC-F9-CA
[+] Generating random string: FDXG63F1FG5VUASCDO
[+] Current CRC32: 8CB45F25
[+] CRC32 successfully cracked: F0-F2-BB-4A
[+] Generating random string: CZFD180TZFWJQYWAZ4
[+] Current CRC32: CD3B9836
[+] CRC32 successfully cracked: E3-35-34-0B
[+] Generating random string: 7KXCLQ7B4B9PAXOINR
[+] Current CRC32: 9FFAB8DB
[+] CRC32 successfully cracked: 0E-15-F5-59
[+] Generating random string: 36GKT87FATZ3JYSDV1
[+] Current CRC32: 11D8984A
[+] CRC32 successfully cracked: 9F-35-D7-D7
[+] Generating random string: Q3C1YOFT2QD593R4QQ
[+] Current CRC32: 668103E0
[+] CRC32 successfully cracked: 35-AE-8E-A0
[+] Generating random string: C4X2CXMZUPN77LMMN3
[+] Current CRC32: C0DBF42E
[+] CRC32 successfully cracked: FB-59-D4-06
[+] Generating random string: 4ZQHH4C3L5QXN105JR
[+] Current CRC32: DA869343
[+] CRC32 successfully cracked: 96-3E-89-1C
[+] Generating random string: H1VGKG1RFDBK93L5G0
[+] Current CRC32: 4D999D3F
[+] CRC32 successfully cracked: EA-30-96-8B
[+] Generating random string: K80OKPJZOZT4EE34Q0
[+] Current CRC32: 590815E1
[+] CRC32 successfully cracked: 34-B8-07-9F
[+] Generating random string: VW386YKRMEYBZD3F5X
[+] Current CRC32: C7C82805
[+] CRC32 successfully cracked: D0-85-C7-01
[+] Generating random string: Q114WQ7FRH8DCLQE69
[+] Current CRC32: 8AFFBB8D
[+] CRC32 successfully cracked: 58-16-F0-4C
[+] Generating random string: B4XASG4KX0F0BPF1XI
[+] Current CRC32: 7C74EFE9
[+] CRC32 successfully cracked: 3C-42-7B-BA
[+] Generating random string: P37PBMQCO84RDW0DIQ
[+] Current CRC32: 4227695A
[+] CRC32 successfully cracked: 8F-C4-28-84
[+] Generating random string: JIAKDA6H9C2TIO2UC6
[+] Current CRC32: 7DAFB46F
[+] CRC32 successfully cracked: BA-19-A0-BB
[+] Generating random string: Y2VHJ60XQWX7LIM5IV
[+] Current CRC32: F4F22640
[+] CRC32 successfully cracked: 95-8B-FD-32
[+] Generating random string: 95FS97SMUSRQ7ITBRL
[+] Current CRC32: E050315D
[+] CRC32 successfully cracked: 88-9C-5F-26
[+] Generating random string: KS0ZFCFZXM9GS5CAT0
[+] Current CRC32: A02DB521
[+] CRC32 successfully cracked: F4-18-22-66
[+] Generating random string: X7N0FYCM1EFMESWROT
[+] Current CRC32: 8923DEF8
[+] CRC32 successfully cracked: 2D-73-2C-4F
[+] Collison found: 'X7N0FYCM1EFMESWROT-s,O'
[+] Verifying CRC32: 14F123CE
[+] Shellcode answer (16h bytes): 'X7N0FYCM1EFMESWROT-s,O'
NOTE:
The binary seven
seems to use only the input bytes that are multiples of 4:
_BOOL4 __usercall sub_535@<eax>(int a1@<eax>, char *a2@<edx>)
{
int i; // ebx
char v4[104]; // [esp+0h] [ebp-68h] BYREF
if ( a1 < 17 )
{
sub_4FE(v4[0]);
sub_52A();
}
memset(&v4[100], 0, 0x64u);
for ( i = 0; i < 100; ++i )
{
v4[i] = **(_BYTE **)&a2[4 * i + 4];
if ( !v4[i] )
break;
}
return u_do_crc32() == 0x177FDC5D;
}
However, if we generate valid answers such as ....a...b...c...d...e
, they are not
accepted by the server. It turns out that we should send the same asnwers as the other binaries.
Putting all together
Finally, we put all types of binaries together in crack script and we get the flag.
The flag is: midnight{Reversing_got_alot_easier_with_backup_cameras}
.
Crack Script
#!/usr/bin/env python3
# ---------------------------------------------------------------------------------------
# Midnight Sun CTF 2022 - REVVER (RE 588)
# ---------------------------------------------------------------------------------------
import binascii
import socket
import re
import string
import capstone
import sys
import random
import zlib
# Blacklisted constant strings in "data section" of the shellcode.
# We exclude these strings from our computations.
_RODATA_BLACKLIST = [
'',
'swag.key',
'Error! Could not open file\n',
'recv failed',
'accept failed',
'Waiting for incoming connections...',
'Could not create socket',
'Connection accepted',
'Client disconnected',
'Bind failed',
'flag.txt',
'/midnightsunctf-2022/quals/revver/answer3.bin',
'Error!\n',
'%s',
'\n',
'Error! Not enough arguments\n'
]
# Lookup table for CRC32.
_CRC32_TBL = [
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
]
# ---------------------------------------------------------------------------------------
# Helper Routines
# ---------------------------------------------------------------------------------------
def recv_until(*trg_strs):
"""Receive until you encounter any of the target string(s)."""
recv_buf = bytes()
while not any(trg in recv_buf for trg in trg_strs):
recv_buf += sock.recv(8192)
if len(recv_buf) > 65536:
print('[!] Warning. Receiving buffer limit reached.')
break
return recv_buf
# ---------------------------------------------------------------------------------------
def parse_server_input(inp):
"""Parse server input and extract binary name and shellcode."""
inp = inp.decode('utf-8')
index, shellcode = None, None
for line in inp.split('\n'):
match = re.search(r'RANDOM BINARY (.*)', line)
if match:
index = match.group(1)
match = re.search(r'^([0-9a-f]+)$', line)
if match:
shellcode = binascii.unhexlify(match.group(1))
return index, shellcode
# ---------------------------------------------------------------------------------------
def extract_const_strs_from_shellcode(shellcode):
"""Extract non-blacklisted constant strings, located at the end of the shellcode.
There are two ways that a shellcode ends:
A) seg000:0000037B C9 leave
seg000:0000037C 5F pop edi
seg000:0000037D 5E pop esi
seg000:0000037E 5B pop ebx
seg000:0000037F C3 retn
B) seg000:0000059C C9 leave
seg000:0000059D C3 retn
We scan shellcode backwards until we hit the C9/C3 pattern.
(we may be very unlucky that this pattern is part of a ciphertext; in that case
just rerun the program ;)).
"""
print('[+] Extracting constant strings from shellcode ...')
data = []
buf = ''
for idx, char in reversed(list(enumerate(shellcode))):
if char == 0xC3:
# We hit a `retn` instrction. Scan backwards for `leave`.
if shellcode[idx - 1] == 0xC9 or shellcode[idx - 4] == 0xC9:
break
if char == 0:
data.append(buf[::-1]) # NULL byte found. Reverse string and add it to list.
buf = ''
else:
buf += chr(char)
if buf:
data.append(buf[::-1]) # Add leftovers (if any).
is_printable = lambda a: len(a) == len([c for c in a if c in string.printable])
p, np = [], []
# Look for black listed strings.
for s in data:
if s in _RODATA_BLACKLIST:
print('[+] Found blacklisted string:', repr(s))
elif is_printable(s):
print('[+] Found printable string:', repr(s))
p.append(s)
else:
print('[+] Found non-printable string:', repr(s))
np.append(s)
return p, np
# ---------------------------------------------------------------------------------------
def extract_const_from_insn(code, insn_regex, nearby=-1):
"""Extract a constant value from an assembly instruction."""
md = capstone.Cs(capstone.CS_ARCH_X86, capstone.CS_MODE_32)
consts = []
last_loc = -1
for insn in md.disasm(code, 0):
# NOTE: We can extract constant from `insn` fields. What we do is a bad way.
match = re.search(insn_regex, insn.mnemonic + ' ' + insn.op_str)
if match and (nearby < 0 or insn.address > nearby and (insn.address - nearby < 0x10)):
# Assume we have only 1 group.
const = int(match.group(1), 16)
# All instructions should have some proximity.
if insn.address - last_loc > 0x10:
consts = []
last_loc = insn.address
consts.append(const)
return consts, last_loc
# ---------------------------------------------------------------------------------------
# Shellcode Categories
# ---------------------------------------------------------------------------------------
def const_str_in_rodata(shellcode):
"""The answer is simply a const, printable string in .rodata."""
print('[+] Shellcode category: Const string in .rodata')
p, _ = extract_const_strs_from_shellcode(shellcode)
assert(len(p) == 1) # We should have exactly 1 non-blacklisted string.
return p[0]
def crypto_in_insn(shellcode):
"""Answer is the XOR between the bytes of `mov` insructions with an 1-byte key."""
print('[+] Shellcode category: Crypto in instructions')
cipher, _ = extract_const_from_insn(shellcode, r'mov byte ptr \[ebp - .*\], [0x]*([0-9a-f]+)$')
key, _ = extract_const_from_insn(shellcode, r'xor cl, [0x]*([0-9a-f]+)$')
assert(len(key) == 1)
plain = [c ^ key[0] for c in cipher]
print(f'[+] Plaintext: {plain}')
return ''.join('%c' % p for p in plain)
def crypto_in_insn_word(shellcode):
"""Answer is the difference between the words of `mov` insructions."""
print('[+] Shellcode category: Difference between words in instructions')
nums, _ = extract_const_from_insn(shellcode, r'mov word ptr \[ebp - .*\], [0x]*([0-9a-f]+)$')
print('[+] Total number of ciphers:', len(nums))
plain = []
for i in range(len(nums) >> 1):
diff = (nums[(len(nums) >> 1) + i] - nums[i]) & 0xFFFF
print('[+] Computing diff: %X - %X = %X' % (nums[(len(nums) >> 1) + i], nums[i], diff ))
plain.append(diff >> 8)
plain.append(diff & 0xFF)
return ''.join('%c' % p for p in plain)
def rc4_decryption(shellcode):
"""The answer the rc4 decryption. printable key, non printalbe ciphertext."""
print('[+] Shellcode category: RC4 decryption')
p, np = extract_const_strs_from_shellcode(shellcode)
assert(len(p) == 1) # We should have exactly 1 key.
key = p[0]
# It's very unlikely to have a printable ciphertext/
# (if this happens, just rerun the script).
ciphertext = np[0]
# if a ciphertext has a NULL byte, then we it will be split across `np` array. Concat.
if len(np) > 1:
print(f'[+] {len(np)} ciphertexts found. Merging ...')
ciphertext = '\x00'.join(r for r in reversed(np))
print('[+] RC4 decryption key:', key)
print('[+] RC4 ciphertext:', '-'.join('%02X' % ord(c) for c in ciphertext))
# NOTE: Crypto.Cipher.ARC4 seems to not give the expected result,
# so we implement RC4 on our own.
S = list(range(256))
j = 0
for i in range(256):
j = (j + S[i] + ord(key[i % len(key)])) % 256
S[i], S[j] = S[j], S[i]
plaintext = ''
i, j = 0, 0
for c in ciphertext:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
K = S[(S[i] + S[j]) % 256]
plaintext += chr(ord(c) ^ K)
print('[+] RC4 plaintext:', plaintext)
return plaintext
def crack_single_crc32(curr_crc32, trg_crc32):
"""Cracks a single CRC32.
We do the old-school approach (no Z3 solver).
This function is based on:
https://stackoverflow.com/questions/9285898/reversing-crc32/13394385#13394385
Want to append bytes: X Y Z W
Take for register a3 a2 a1 a0 (a is the 'already calculated' crc for string)
Note that a3 is the most significant byte and a0 the least.
f is the wanted new CRC byte string, and xyzw is the modification pad
I'll show it a little different way:
a0 + X =(1) points to b3 b2 b1 b0 in table
a1 + b0 + Y =(2) points to c3 c2 c1 c0 in table
a2 + b1 + c0 + Z =(3) points to d3 d2 d1 d0 in table
a3 + b2 + c1 + d0 + W =(4) points to e4 e3 e2 e1 in table
b3 + c2 + d1 + e0 =f0
c3 + d2 + e1 =f1
d3 + e2 =f2
e3 =f3
(1) (2) (3) (4)
(figure 4)
This is reversed in the same way as the 16bit version.
I shall give an example with real values.
For the table values use the CRC-32 table in the appendix.
Take for CRC register before, a3 a2 a1 a0 -> AB CD EF 66
Take for CRC register after, f3 f2 f1 f0 -> 56 33 14 78 (wanted value)
Here we go:
First byte of entries entry value
e3=f3 =56 -> 35h=(4) 56B3C423 for e3 e2 e1 e0
d3=f2+e2 =33+B3 =E6 -> 4Fh=(3) E6635C01 for d3 d2 d1 d0
c3=f1+e1+d2 =14+C4+63 =B3 -> F8h=(2) B3667A2E for c3 c2 c1 c0
b3=f0+e0+d1+c2=78+23+5C+66=61 -> DEh=(1) 616BFFD3 for b3 b2 b1 b0
Now we have all needed values, then
X=(1)+ a0= DE+66=B8
Y=(2)+ b0+a1= F8+D3+EF=C4
Z=(3)+ c0+b1+a2= 4F+2E+FF+CD=53
W=(4)+d0+c1+b2+a3=35+01+7A+6B+AB=8E
(final computation)
"""
get_bytes = lambda n : ((n & 0xFF000000) >> 24, (n & 0x00FF0000) >> 16,
(n & 0x0000FF00) >> 8, (n & 0x000000FF))
curr_crc32 = ~curr_crc32
trg_crc32 = ~trg_crc32
a3, a2, a1, a0 = get_bytes(curr_crc32)
f3, f2, f1, f0 = get_bytes(trg_crc32)
st = 0x0
end = 0xff
# Capture e3/e2/e1/e0/ (4) values.
for i in range(st,end):
if ((_CRC32_TBL[i] & 0xFF000000) == (trg_crc32 & 0xFF000000)):
e3, e2, e1, e0 = get_bytes(_CRC32_TBL[i])
four = i
break
# d3=f2+e2 =33+B3 =E6 -> 4Fh=(3) E6635C01 for d3 d2 d1 d0
d3 = f2^e2 # Lookup d3 and assign the values for d2/d1/d0/(3)
for i in range(st, end):#($i = 0; $i < 256; $i++)
if ((_CRC32_TBL[i] & 0xFF000000) == (d3 << 24)):
_, d2, d1, d0 = get_bytes(_CRC32_TBL[i])
three = i
break
# c3=f1+e1+d2 =14+C4+63 =B3 -> F8h=(2) B3667A2E for c3 c2 c1 c0
c3 = f1^e1^d2;
for i in range(st, end):#($i = 0; $i < 256; $i++)
if ((_CRC32_TBL[i] & 0xFF000000) == (c3 << 24)):
_, c2, c1, c0 = get_bytes(_CRC32_TBL[i])
two = i
break
# b3=f0+e0+d1+c2=78+23+5C+66=61 -> DEh=(1) 616BFFD3 for b3 b2 b1 b0
b3 = f0^e0^d1^c2;
for i in range(st, end):
if ((_CRC32_TBL[i] & 0xFF000000) == (b3 << 24)):
_, b2, b1, b0 = get_bytes(_CRC32_TBL[i])
one = i
break
'''
Now we have all needed values, then
X=(1)+ a0= DE+66=B8
Y=(2)+ b0+a1= F8+D3+EF=C4
Z=(3)+ c0+b1+a2= 4F+2E+FF+CD=53
W=(4)+d0+c1+b2+a3=35+01+7A+6B+AB=8E
(final computation)
'''
X = one ^ a0
Y = two ^ b0 ^ a1
Z = three ^ c0 ^ b1 ^ a2
W = four ^ d0 ^ c1 ^ b2 ^ a3
return [X, Y, Z, W]
def crc32_crack(shellcode):
print('[+] Shellcode category: Crack CRC32')
trg_crc, addr = extract_const_from_insn(shellcode, r'mov esi, 0x([0-9a-f]+)$')
sz, _ = extract_const_from_insn(shellcode, r'push [0x]*([0-9a-f]+)$', addr)
assert(len(trg_crc) == 1 and len(sz) == 1)
trg_crc = trg_crc[-1]
sz = sz[-1]
print(f'[+] Target CRC32: {trg_crc:08X}h')
print(f'[+] Input size: {sz}')
for i in range(1048576):
'''The server is not happy with non-ASCII answer when encoded to UTF-8:
Traceback (most recent call last):
File "./challenge.py", line 245, in <module>
main()
File "./challenge.py", line 241, in main
play()
File "./challenge.py", line 206, in play
if len(xxx) == value[1] and value[0] == (zlib.crc32(bytes(xxx,'utf-8')) & 0xffffffff):
UnicodeEncodeError: 'utf-8' codec can't encode character '\udca6' in position 21: surrogates not allowed
Therefore the generated answer must be ASCII printable. So we generate
random strings of size `sz - 4`, until the missing 4 bytes are also ASCII printable.
'''
rnd = ''.join(random.choices(string.ascii_uppercase + string.digits, k=sz-4))
base = rnd.encode('utf-8')
curr_crc = zlib.crc32(base)
print('[+] Generating random string:', rnd)
print(f'[+] Current CRC32: {curr_crc:08X}')
crack = crack_single_crc32(curr_crc, trg_crc)
print('[+] CRC32 successfully cracked:', '-'.join('%02X' % c for c in crack))
# Build target input.
trg_inp = '%s%c%c%c%c' % (rnd, crack[0], crack[1], crack[2], crack[3])
# If the `crack` is not printable ASCII, try again with another `rnd`.
# All must be printable so we don't have unicode issues ;)
if len([x for x in crack if x > 0x20 and x < 0x80]) == 4:
new_crc = zlib.crc32(bytes(trg_inp, 'utf-8'))
print('[+] Collison found:', repr(trg_inp))
print(f'[+] Verifying CRC32: {new_crc:08X}')
assert(new_crc == trg_crc)
return trg_inp
print('[!] Error. CRC32 ASCII collision cannot be found')
exit()
# ---------------------------------------------------------------------------------------
# Lambdas for the 20 different binaries
# (we only have 5 different binary types; each type appears 4 times)
# ---------------------------------------------------------------------------------------
one = lambda shellcode: crypto_in_insn(shellcode)
two = lambda shellcode: crc32_crack(shellcode)
three = lambda shellcode: rc4_decryption(shellcode)
four = lambda shellcode: crypto_in_insn_word(shellcode)
five = lambda shellcode: const_str_in_rodata(shellcode)
six = lambda shellcode: crypto_in_insn(shellcode)
seven = lambda shellcode: crc32_crack(shellcode)
eight = lambda shellcode: rc4_decryption(shellcode)
nine = lambda shellcode: crypto_in_insn_word(shellcode)
ten = lambda shellcode: const_str_in_rodata(shellcode)
eleven = lambda shellcode: crypto_in_insn(shellcode)
twelve = lambda shellcode: crc32_crack(shellcode)
thirteen = lambda shellcode: rc4_decryption(shellcode)
fourteen = lambda shellcode: crypto_in_insn_word(shellcode)
fiveteen = lambda shellcode: const_str_in_rodata(shellcode)
sixteen = lambda shellcode: crypto_in_insn(shellcode)
seventeen= lambda shellcode: crc32_crack(shellcode)
eighteen = lambda shellcode: rc4_decryption(shellcode)
nineteen = lambda shellcode: crypto_in_insn_word(shellcode)
twenty = lambda shellcode: const_str_in_rodata(shellcode)
# ---------------------------------------------------------------------------------------
if __name__ == "__main__":
print('[+] REVVER simulator started.')
if len(sys.argv) == 2:
index = sys.argv[1]
print('[+] Running in local mode for shellcode:', index)
shellcode = open(f'shellcodes/{index}.sc', 'rb').read()
answer = eval(f'{index}(shellcode)')
print('[+] Answer:', repr(answer))
exit()
# ---------------------------------------------------------------
# Remote Mode
# ---------------------------------------------------------------
sock = socket.create_connection(('revver-01.hfsc.tf', 3320))
recv_until(b' 2) Play')
sock.send(b'2\n')
for i in range(1, 21+1):
print(f'================ {i} ================')
serv_inp = recv_until(b'ANSWER: ', b'YOU FAIL', b'midnight{')
if b'FAIL' in serv_inp:
print('[!] Error. Invalid answer!')
print('[+] Please re-run program.')
exit()
elif b'midnight{' in serv_inp:
print('[+] Got Flag!', serv_inp)
exit()
print(f'[+] Received {len(serv_inp)} bytes from server')
index, shellcode = parse_server_input(serv_inp)
print(f"[+] Operating for shellcode: '{index}'")
try:
answer = eval(f'{index}(shellcode)')
except NameError:
print('[!] Error. Cannot process shellcode:', index)
print('[+] Storing it locally under `shellcodes/` for offline processing ...')
open(f'shellcodes/{index}.sc', 'wb').write(shellcode)
exit()
print(f"[+] Shellcode answer ({len(answer):X}h bytes): '{answer}'")
sock.send(answer.encode('utf-8') + b'\n')
print('[+] Program finished. Bye bye :)')
# ---------------------------------------------------------------------------------------
'''
ispo@ispo-glaptop:~/ctf/midnight_sun_ctf_2022/revver$ ./revver_crack.py
[+] REVVER simulator started.
================ 1 ================
[+] Received 3291 bytes from server
[+] Operating for shellcode: 'one'
[+] Shellcode category: Crypto in instructions
[+] Plaintext: [48, 59, 102, 61, 81, 91, 104, 123, 108, 76]
[+] Shellcode answer (Ah bytes): '0;f=Q[h{lL'
================ 2 ================
[+] Received 3974 bytes from server
[+] Operating for shellcode: 'eleven'
[+] Shellcode category: Crypto in instructions
[+] Plaintext: [65, 76, 55, 42, 83, 72, 78, 60, 45, 98]
[+] Shellcode answer (Ah bytes): 'AL7*SHN<-b'
================ 3 ================
[+] Received 613 bytes from server
[+] Operating for shellcode: 'seventeen'
[+] Shellcode category: Crack CRC32
[+] Target CRC32: EC73187Ch
[+] Input size: 17
[+] Generating random string: TQNDAIPTDZ6TM
[+] Current CRC32: C698D8F1
[+] CRC32 successfully cracked: A4-BF-78-70
[+] Generating random string: CYYSY1ZBOUHUT
[+] Current CRC32: 5EA16C4C
[+] CRC32 successfully cracked: 19-0B-41-E8
[+] Generating random string: 7YX2G631VSDS9
[+] Current CRC32: 02C0C55B
[+] CRC32 successfully cracked: 0E-A2-20-B4
[+] Generating random string: XD5DU9UTGFJCN
[+] Current CRC32: 86D055F4
[+] CRC32 successfully cracked: A1-32-30-30
[+] Generating random string: OMAZMMFKO4OI4
[+] Current CRC32: 83978746
[+] CRC32 successfully cracked: 13-E0-77-35
[+] Generating random string: 1V49D0F3LG5UE
[+] Current CRC32: D114C627
[+] CRC32 successfully cracked: 72-A1-F4-67
[+] Generating random string: WDANJPBO83Z8Q
[+] Current CRC32: F54A7E59
[+] CRC32 successfully cracked: 0C-19-AA-43
[+] Generating random string: 318NBOMILSBFB
[+] Current CRC32: 2C97100A
[+] CRC32 successfully cracked: 5F-77-77-9A
[+] Generating random string: DX8UDF60BKZ3Z
[+] Current CRC32: 563EDA15
[+] CRC32 successfully cracked: 40-BD-DE-E0
[+] Generating random string: MDWQEDH6M6KOW
[+] Current CRC32: D6F485C1
[+] CRC32 successfully cracked: 94-E2-14-60
[+] Generating random string: UBLVBG8O8VUKB
[+] Current CRC32: 8770DC41
[+] CRC32 successfully cracked: 14-BB-90-31
[+] Generating random string: ZV9D3LEYX35GC
[+] Current CRC32: E71D2FF8
[+] CRC32 successfully cracked: AD-48-FD-51
[+] Generating random string: K9X42F10Y2NOL
[+] Current CRC32: 87209362
[+] CRC32 successfully cracked: 37-F4-C0-31
[+] Generating random string: GFAOTBV2QGBJH
[+] Current CRC32: 272D47DE
[+] CRC32 successfully cracked: 8B-20-CD-91
[+] Generating random string: C2KLVS08O3WV8
[+] Current CRC32: 8948641C
[+] CRC32 successfully cracked: 49-03-A8-3F
[+] Generating random string: GO0Y91FLOZ20M
[+] Current CRC32: FA75AA2E
[+] CRC32 successfully cracked: 7B-CD-95-4C
[+] Generating random string: Z96Z29HFG8IR1
[+] Current CRC32: 963C2347
[+] CRC32 successfully cracked: 12-44-DC-20
[+] Generating random string: ZNW0QURRILP0D
[+] Current CRC32: 170C8026
[+] CRC32 successfully cracked: 73-E7-EC-A1
[+] Generating random string: 540FB66B7JTT9
[+] Current CRC32: 8EE929B1
[+] CRC32 successfully cracked: E4-4E-09-38
[+] Generating random string: 2QOLP3UQK9CXT
[+] Current CRC32: 0F2EA573
[+] CRC32 successfully cracked: 26-C2-CE-B9
[+] Generating random string: PN93HPUBNLU2O
[+] Current CRC32: 5B3B8397
[+] CRC32 successfully cracked: C2-E4-DB-ED
[+] Generating random string: SFN0CEY8ZAKUE
[+] Current CRC32: BC1FF30E
[+] CRC32 successfully cracked: 5B-94-FF-0A
[+] Generating random string: FC3DLREM9UXTR
[+] Current CRC32: 90975210
[+] CRC32 successfully cracked: 45-35-77-26
[+] Collison found: 'FC3DLREM9UXTRE5w&'
[+] Verifying CRC32: EC73187C
[+] Shellcode answer (11h bytes): 'FC3DLREM9UXTRE5w&'
================ 4 ================
[+] Received 2927 bytes from server
[+] Operating for shellcode: 'six'
[+] Shellcode category: Crypto in instructions
[+] Plaintext: [112, 59, 116, 77, 96, 76, 83, 70, 62, 56]
[+] Shellcode answer (Ah bytes): 'p;tM`LSF>8'
================ 5 ================
[+] Received 3047 bytes from server
[+] Operating for shellcode: 'seven'
[+] Shellcode category: Crack CRC32
[+] Target CRC32: 27A958F9h
[+] Input size: 30
[+] Generating random string: D2OE0OGSMKG2GWG0J2QO1BE1B0
[+] Current CRC32: DACD2BFE
[+] CRC32 successfully cracked: 15-1A-6F-A8
[+] Generating random string: Z1FCWEMM8I778KP4MXCO3OPI1Q
[+] Current CRC32: 4BF6B65E
[+] CRC32 successfully cracked: B5-87-54-39
[+] Generating random string: FG66WX4RSYYVB9OAZ73VOETACR
[+] Current CRC32: CF8EC255
[+] CRC32 successfully cracked: BE-F3-2C-BD
[+] Generating random string: H137V3M5R2EC9BBP32WFJB7J31
[+] Current CRC32: AC121E12
[+] CRC32 successfully cracked: F9-2F-B0-DE
[+] Generating random string: IKEYIDU5OM5TFZT8V8Y4S0GB9C
[+] Current CRC32: 7E445EDD
[+] CRC32 successfully cracked: 36-6F-E6-0C
[+] Generating random string: I3Q0B6LLHW7886RRZLVCEJJHWX
[+] Current CRC32: 7A42C6BB
[+] CRC32 successfully cracked: 50-F7-E0-08
[+] Generating random string: OVO8WCVD707KZ09Y46XESJIB6E
[+] Current CRC32: 31EBC77A
[+] CRC32 successfully cracked: 91-F6-49-43
[+] Generating random string: O5TNILZ62BG9WUU1V2DU7XUE18
[+] Current CRC32: 9555F5CE
[+] CRC32 successfully cracked: 25-C4-F7-E7
[+] Generating random string: SRBXN1D3X8AK5D2FEEU6ZI7NCH
[+] Current CRC32: 3E924181
[+] CRC32 successfully cracked: 6A-70-30-4C
[+] Collison found: 'SRBXN1D3X8AK5D2FEEU6ZI7NCHjp0L'
[+] Verifying CRC32: 27A958F9
[+] Shellcode answer (1Eh bytes): 'SRBXN1D3X8AK5D2FEEU6ZI7NCHjp0L'
================ 6 ================
[+] Received 4818 bytes from server
[+] Operating for shellcode: 'fiveteen'
[+] Shellcode category: Const string in .rodata
[+] Extracting constant strings from shellcode ...
[+] Found blacklisted string: ''
[+] Found printable string: 'sTpG378ZBrA9snf70Vcq9m0MkbdULHuJw2lzzeSiezG7nQsNdCqkjS2C6VGKntGzQujruqhpWhiRcIl'
[+] Found blacklisted string: 'recv failed'
[+] Found blacklisted string: 'accept failed'
[+] Found blacklisted string: 'Waiting for incoming connections...'
[+] Found blacklisted string: 'Could not create socket'
[+] Found blacklisted string: 'Connection accepted'
[+] Found blacklisted string: 'Client disconnected'
[+] Found blacklisted string: 'Bind failed'
[+] Found blacklisted string: '%s'
[+] Found blacklisted string: '\n'
[+] Shellcode answer (4Fh bytes): 'sTpG378ZBrA9snf70Vcq9m0MkbdULHuJw2lzzeSiezG7nQsNdCqkjS2C6VGKntGzQujruqhpWhiRcIl'
================ 7 ================
[+] Received 3149 bytes from server
[+] Operating for shellcode: 'ten'
[+] Shellcode category: Const string in .rodata
[+] Extracting constant strings from shellcode ...
[+] Found blacklisted string: ''
[+] Found printable string: 'cXz5zeR4buf9Mg49UxQGpVU9spQJBfDnu4PJllIRWeDyh19EP22P7SRFrtK'
[+] Found blacklisted string: 'Error!\n'
[+] Shellcode answer (3Bh bytes): 'cXz5zeR4buf9Mg49UxQGpVU9spQJBfDnu4PJllIRWeDyh19EP22P7SRFrtK'
================ 8 ================
[+] Received 3377 bytes from server
[+] Operating for shellcode: 'two'
[+] Shellcode category: Crack CRC32
[+] Target CRC32: B6923162h
[+] Input size: 29
[+] Generating random string: UOSTHUEOLZ3DKW55F758K2SL4
[+] Current CRC32: 2ED2029A
[+] CRC32 successfully cracked: 62-ED-08-A4
[+] Generating random string: WSIMZZ83MXWOB8BL1R2KIM7CD
[+] Current CRC32: CAB3119B
[+] CRC32 successfully cracked: 63-FE-69-40
[+] Generating random string: N3P78IBXJXU632IA2GLS3U802
[+] Current CRC32: ABA25261
[+] CRC32 successfully cracked: 99-BD-78-21
[+] Generating random string: V6CJOFDO034CJO4FEQRUVKEN8
[+] Current CRC32: E51D53E5
[+] CRC32 successfully cracked: 1D-BC-C7-6F
[+] Generating random string: WMTJOHKPXEG046U4TLJ1KS3H5
[+] Current CRC32: 74B52B29
[+] CRC32 successfully cracked: D1-C4-6F-FE
[+] Generating random string: L6PGF0XUYXGPFL22NW73H6VPI
[+] Current CRC32: D4E923AF
[+] CRC32 successfully cracked: 57-CC-33-5E
[+] Generating random string: 6OV168RAJ5NLDG3OF39TBTHWO
[+] Current CRC32: 0A7C0C24
[+] CRC32 successfully cracked: DC-E3-A6-80
[+] Generating random string: 53O8UL3BHOINURI6UXGNFO2W8
[+] Current CRC32: 55ECB7F1
[+] CRC32 successfully cracked: 09-58-36-DF
[+] Generating random string: B1LPTMGYU6AXTXS7D1LCTUJK5
[+] Current CRC32: CB9CDBA9
[+] CRC32 successfully cracked: 51-34-46-41
[+] Collison found: 'B1LPTMGYU6AXTXS7D1LCTUJK5Q4FA'
[+] Verifying CRC32: B6923162
[+] Shellcode answer (1Dh bytes): 'B1LPTMGYU6AXTXS7D1LCTUJK5Q4FA'
================ 9 ================
[+] Received 4155 bytes from server
[+] Operating for shellcode: 'eight'
[+] Shellcode category: RC4 decryption
[+] Extracting constant strings from shellcode ...
[+] Found blacklisted string: ''
[+] Found printable string: 'NbpMzcLzTGwiksqqK'
[+] Found blacklisted string: 'Error! Not enough arguments\n'
[+] Found non-printable string: '9ùþh¨ÔÎQhS>e¯Ï-F\x19çéùðq'
[+] RC4 decryption key: NbpMzcLzTGwiksqqK
[+] RC4 ciphertext: 39-F9-FE-68-A8-D4-CE-51-68-53-3E-65-AF-CF-2D-46-19-E7-E9-F9-F0-71
[+] RC4 plaintext: VkKzxLMSHUowJgormfNZhj
[+] Shellcode answer (16h bytes): 'VkKzxLMSHUowJgormfNZhj'
================ 10 ================
[+] Received 1908 bytes from server
[+] Operating for shellcode: 'eighteen'
[+] Shellcode category: RC4 decryption
[+] Extracting constant strings from shellcode ...
[+] Found blacklisted string: ''
[+] Found non-printable string: '\x8bö\x9aû[\x15<fªÿ\nW\x03ר\x1f/ºVf7u'
[+] Found printable string: 'SEyGAPzghOnKAKxRd'
[+] RC4 decryption key: SEyGAPzghOnKAKxRd
[+] RC4 ciphertext: 8B-F6-9A-FB-5B-15-3C-66-AA-FF-0A-57-03-D7-A8-1F-2F-BA-56-66-37-75
[+] RC4 plaintext: fitkKdadaEIOeMdxvwPmZt
[+] Shellcode answer (16h bytes): 'fitkKdadaEIOeMdxvwPmZt'
================ 11 ================
[+] Received 1062 bytes from server
[+] Operating for shellcode: 'twenty'
[+] Shellcode category: Const string in .rodata
[+] Extracting constant strings from shellcode ...
[+] Found blacklisted string: ''
[+] Found printable string: '7LGd5mwXnNDJkvu7HsBe9fhL4xhuNNvBakS3smdjqD7PkYCGR4giNdGSZ7RCarm3zq2BCEBAp7k65cPWZXXzrr3'
[+] Shellcode answer (57h bytes): '7LGd5mwXnNDJkvu7HsBe9fhL4xhuNNvBakS3smdjqD7PkYCGR4giNdGSZ7RCarm3zq2BCEBAp7k65cPWZXXzrr3'
================ 12 ================
[+] Received 3704 bytes from server
[+] Operating for shellcode: 'nine'
[+] Shellcode category: Difference between words in instructions
[+] Total number of ciphers: 32
[+] Computing diff: 4F87 - E924 = 6663
[+] Computing diff: 67B4 - FD5F = 6A55
[+] Computing diff: 30FC - E58C = 4B70
[+] Computing diff: 3B43 - CAD8 = 706B
[+] Computing diff: 597F - EA32 = 6F4D
[+] Computing diff: 36FE - ED93 = 496B
[+] Computing diff: 784A - FDD8 = 7A72
[+] Computing diff: 5B92 - F523 = 666F
[+] Computing diff: 40F8 - CA87 = 7671
[+] Computing diff: 6126 - F4D2 = 6C54
[+] Computing diff: 5756 - FCF0 = 5A66
[+] Computing diff: 4C16 - D4A9 = 776D
[+] Computing diff: 2BC1 - D175 = 5A4C
[+] Computing diff: 38EC - F19E = 474E
[+] Computing diff: 26E9 - D472 = 5277
[+] Computing diff: 420B - D5A1 = 6C6A
[+] Shellcode answer (20h bytes): 'fcjUKppkoMIkzrfovqlTZfwmZLGNRwlj'
================ 13 ================
[+] Received 4184 bytes from server
[+] Operating for shellcode: 'twelve'
[+] Shellcode category: Crack CRC32
[+] Target CRC32: EBFA834Dh
[+] Input size: 20
[+] Generating random string: EXWO6S8EAXHUW725
[+] Current CRC32: FE1638CF
[+] CRC32 successfully cracked: 79-AC-F3-44
[+] Generating random string: TZO8I3CGCAISOWQ0
[+] Current CRC32: BD59205D
[+] CRC32 successfully cracked: EB-B4-BC-07
[+] Generating random string: UNUVPXBRLCJ5LNIV
[+] Current CRC32: 8FBF490B
[+] CRC32 successfully cracked: BD-DD-5A-35
[+] Generating random string: EPXVNBCF64DGBAK9
[+] Current CRC32: 6912C57D
[+] CRC32 successfully cracked: CB-51-F7-D3
[+] Generating random string: PWH7ZNOMNLH045KB
[+] Current CRC32: 00AE53FA
[+] CRC32 successfully cracked: 4C-C7-4B-BA
[+] Generating random string: HNEEYPLSYGZ0PLIX
[+] Current CRC32: D4A4BB69
[+] CRC32 successfully cracked: DF-2F-41-6E
[+] Generating random string: BIYBE1OI724TYNBA
[+] Current CRC32: 1CDD2762
[+] CRC32 successfully cracked: D4-B3-38-A6
[+] Generating random string: R1XCH780I0IONZQN
[+] Current CRC32: E4410568
[+] CRC32 successfully cracked: DE-91-A4-5E
[+] Generating random string: 7BCQE94EOAT08J7L
[+] Current CRC32: E619F8BE
[+] CRC32 successfully cracked: 08-6C-FC-5C
[+] Generating random string: 25DMUMKMUUS17808
[+] Current CRC32: FDA4F6C3
[+] CRC32 successfully cracked: 75-62-41-47
[+] Collison found: '25DMUMKMUUS17808ubAG'
[+] Verifying CRC32: EBFA834D
[+] Shellcode answer (14h bytes): '25DMUMKMUUS17808ubAG'
================ 14 ================
[+] Received 4615 bytes from server
[+] Operating for shellcode: 'three'
[+] Shellcode category: RC4 decryption
[+] Extracting constant strings from shellcode ...
[+] Found blacklisted string: ''
[+] Found printable string: 'oHkAdQZfDLeWngmKD'
[+] Found blacklisted string: 'Error! Could not open file\n'
[+] Found non-printable string: '<ê\x19\x9d.f¼YÏïCÂg(\x84õÜÄë¿·\x81'
[+] Found blacklisted string: '/midnightsunctf-2022/quals/revver/answer3.bin'
[+] RC4 decryption key: oHkAdQZfDLeWngmKD
[+] RC4 ciphertext: 3C-EA-19-9D-2E-66-BC-59-CF-EF-43-C2-67-28-84-F5-DC-C4-EB-BF-B7-81
[+] RC4 plaintext: OpwyGUBePAtCTxmbtRUNMV
[+] Shellcode answer (16h bytes): 'OpwyGUBePAtCTxmbtRUNMV'
================ 15 ================
[+] Received 5396 bytes from server
[+] Operating for shellcode: 'thirteen'
[+] Shellcode category: RC4 decryption
[+] Extracting constant strings from shellcode ...
[+] Found blacklisted string: ''
[+] Found non-printable string: '»ä>Ü\x1a\x96\r÷\x84íwÿBîê\x03i\x06P\x05»ª'
[+] Found blacklisted string: 'recv failed'
[+] Found printable string: 'hTJTTRHuTEycoaIgL'
[+] Found blacklisted string: 'accept failed'
[+] Found blacklisted string: 'Waiting for incoming connections...'
[+] Found blacklisted string: 'Could not create socket'
[+] Found blacklisted string: 'Connection accepted'
[+] Found blacklisted string: 'Client disconnected'
[+] Found blacklisted string: 'Bind failed'
[+] Found blacklisted string: '\n'
[+] RC4 decryption key: hTJTTRHuTEycoaIgL
[+] RC4 ciphertext: BB-E4-3E-DC-1A-96-0D-F7-84-ED-77-FF-42-EE-EA-03-69-06-50-05-BB-AA
[+] RC4 plaintext: gDQZibaLRUIwvzpnComCvG
[+] Shellcode answer (16h bytes): 'gDQZibaLRUIwvzpnComCvG'
================ 16 ================
[+] Received 717 bytes from server
[+] Operating for shellcode: 'sixteen'
[+] Shellcode category: Crypto in instructions
[+] Plaintext: [34, 96, 74, 114, 69, 93, 71, 92, 42, 95]
[+] Shellcode answer (Ah bytes): '"`JrE]G\*_'
================ 17 ================
[+] Received 5140 bytes from server
[+] Operating for shellcode: 'fourteen'
[+] Shellcode category: Difference between words in instructions
[+] Total number of ciphers: 52
[+] Computing diff: 3A0B - E293 = 5778
[+] Computing diff: 1786 - CB17 = 4C6F
[+] Computing diff: 203B - D4D7 = 4B64
[+] Computing diff: 2B89 - DB20 = 5069
[+] Computing diff: 258C - D034 = 5558
[+] Computing diff: 4DC0 - F979 = 5447
[+] Computing diff: 2E77 - E50C = 496B
[+] Computing diff: 27BF - D84C = 4F73
[+] Computing diff: 4791 - FF26 = 486B
[+] Computing diff: 2A38 - E2C5 = 4773
[+] Computing diff: 39BC - D74B = 6271
[+] Computing diff: 32FA - C98F = 696B
[+] Computing diff: 3CBD - DA5C = 6261
[+] Computing diff: 1C5B - C7F6 = 5465
[+] Computing diff: 64E6 - ED7A = 776C
[+] Computing diff: 2FB0 - C061 = 6F4F
[+] Computing diff: 3B5F - CE0E = 6D51
[+] Computing diff: 75FB - FFB7 = 7644
[+] Computing diff: 27B3 - D442 = 5371
[+] Computing diff: 4BF2 - E18D = 6A65
[+] Computing diff: 1231 - CDE6 = 444B
[+] Computing diff: 5DA1 - E353 = 7A4E
[+] Computing diff: 5BAE - F057 = 6B57
[+] Computing diff: 42C9 - EE7F = 544A
[+] Computing diff: 24C1 - DE6C = 4655
[+] Computing diff: 272C - C1DB = 6551
[+] Shellcode answer (34h bytes): 'WxLoKdPiUXTGIkOsHkGsbqikbaTewloOmQvDSqjeDKzNkWTJFUeQ'
================ 18 ================
[+] Received 1402 bytes from server
[+] Operating for shellcode: 'nineteen'
[+] Shellcode category: Difference between words in instructions
[+] Total number of ciphers: 46
[+] Computing diff: 2A31 - D5BB = 5476
[+] Computing diff: 3AAE - D94D = 6161
[+] Computing diff: 2E80 - CA27 = 6459
[+] Computing diff: 69B0 - F969 = 7047
[+] Computing diff: 635A - FAED = 686D
[+] Computing diff: 393E - D6DB = 6263
[+] Computing diff: 50ED - E4A1 = 6C4C
[+] Computing diff: 3A99 - D148 = 6951
[+] Computing diff: 35FF - EE97 = 4768
[+] Computing diff: 5020 - E0AD = 6F73
[+] Computing diff: 5113 - E1CD = 6F46
[+] Computing diff: 3126 - DEC5 = 5261
[+] Computing diff: 61CA - EE70 = 735A
[+] Computing diff: 5344 - EEE0 = 6464
[+] Computing diff: 4036 - D6EB = 694B
[+] Computing diff: 239F - DE57 = 4548
[+] Computing diff: 3959 - EEFF = 4A5A
[+] Computing diff: 6A21 - F5AA = 7477
[+] Computing diff: 3148 - E3E4 = 4D64
[+] Computing diff: 3797 - F250 = 4547
[+] Computing diff: 3521 - E9CF = 4B52
[+] Computing diff: 38AF - F464 = 444B
[+] Computing diff: 4082 - EA35 = 564D
[+] Shellcode answer (2Eh bytes): 'TvaadYpGhmbclLiQGhosoFRasZddiKEHJZtwMdEGKRDKVM'
================ 19 ================
[+] Received 3710 bytes from server
[+] Operating for shellcode: 'five'
[+] Shellcode category: Const string in .rodata
[+] Extracting constant strings from shellcode ...
[+] Found blacklisted string: ''
[+] Found blacklisted string: 'swag.key'
[+] Found printable string: 'c4ZQCT0s20MrXAN2slY2MOsF7GDORA0VXIxeirAOxS0JGQbqPiSWQC8IXj7ldIaMih5X6nQYnhkuo1'
[+] Found blacklisted string: 'Error! Could not open file\n'
[+] Shellcode answer (4Eh bytes): 'c4ZQCT0s20MrXAN2slY2MOsF7GDORA0VXIxeirAOxS0JGQbqPiSWQC8IXj7ldIaMih5X6nQYnhkuo1'
================ 20 ================
[+] Received 4868 bytes from server
[+] Operating for shellcode: 'four'
[+] Shellcode category: Difference between words in instructions
[+] Total number of ciphers: 96
[+] Computing diff: 3E74 - C51A = 795A
[+] Computing diff: 66CF - ED77 = 7958
[+] Computing diff: 239B - D84D = 4B4E
[+] Computing diff: 471E - E1CF = 654F
[+] Computing diff: 2C31 - E8E6 = 434B
[+] Computing diff: 44FB - EFA4 = 5557
[+] Computing diff: 1F6E - D1FF = 4D6F
[+] Computing diff: 3CCF - CD8C = 6F43
[+] Computing diff: 617F - F827 = 6958
[+] Computing diff: 72E - C2BD = 4471
[+] Computing diff: 1C5D - D81A = 4443
[+] Computing diff: 338C - D120 = 626C
[+] Computing diff: 366D - D1F3 = 647A
[+] Computing diff: 5A95 - ED44 = 6D51
[+] Computing diff: 6574 - EC08 = 796C
[+] Computing diff: 71C3 - FE69 = 735A
[+] Computing diff: 1784 - D30B = 4479
[+] Computing diff: 4800 - F7B9 = 5047
[+] Computing diff: 16B3 - CB6F = 4B44
[+] Computing diff: 5F80 - EB0D = 7473
[+] Computing diff: 64CB - F05B = 7470
[+] Computing diff: 31C1 - CB69 = 6658
[+] Computing diff: 438C - E22B = 6161
[+] Computing diff: 3D53 - EBEE = 5165
[+] Computing diff: 4758 - D80B = 6F4D
[+] Computing diff: 3D08 - F2BB = 4A4D
[+] Computing diff: 94D - C0D8 = 4875
[+] Computing diff: 61F5 - E8B3 = 7942
[+] Computing diff: 743A - FAF2 = 7948
[+] Computing diff: 44BD - D476 = 7047
[+] Computing diff: 2A59 - E110 = 4949
[+] Computing diff: 23F1 - E080 = 4371
[+] Computing diff: 4947 - FBF2 = 4D55
[+] Computing diff: 19A6 - CA5A = 4F4C
[+] Computing diff: 1143 - CBDD = 4566
[+] Computing diff: 43C6 - D758 = 6C6E
[+] Computing diff: 70D2 - F982 = 7750
[+] Computing diff: 6FA1 - FC34 = 736D
[+] Computing diff: 4365 - EB04 = 5861
[+] Computing diff: 2538 - CBCD = 596B
[+] Computing diff: 30D3 - EF72 = 4161
[+] Computing diff: 2BB3 - D268 = 594B
[+] Computing diff: 3383 - E419 = 4F6A
[+] Computing diff: 7093 - FF2A = 7169
[+] Computing diff: 2AA3 - D633 = 5470
[+] Computing diff: 15D6 - CF66 = 4670
[+] Computing diff: 2652 - C30B = 6347
[+] Computing diff: 3E81 - EB35 = 534C
[+] Shellcode answer (60h bytes): 'yZyXKNeOCKUWMooCiXDqDCbldzmQylsZDyPGKDtstpfXaaQeoMJMHuyByHpGIICqMUOLEflnwPsmXaYkAaYKOjqiTpFpcGSL'
================ 21 ================
[+] Got Flag! b" \nb'midnight{Reversing_got_alot_easier_with_backup_cameras}'\n \n"
'''
# ---------------------------------------------------------------------------------------