we're given a PE32 exe file which we are supposed to reverse and break its serial protections.
I analyzed it a bit using cutter, didn't fully analyze it, but found out it sets different characters at different place which are not sequenced and then check each character of required `serial` input by some non-sequential character pointers.
looking at `main` function's disassembly, I found a function call which places a given character pointer or string in given address, it was repeatedly called.
a sample call is as follow:```│           0x0040119c      6a01           push 1                      ; 1│           0x0040119e      6800524000     push 0x405200               ; "="│           0x004011a3      8d8d20faffff   lea ecx, dword [var_5e0h]│           0x004011a9      c78530faffff.  mov dword [var_5d0h], 0│           0x004011b3      c78534faffff.  mov dword [var_5cch], 0xf   ; 15│           0x004011bd      c68520faffff.  mov byte [var_5e0h], 0│           0x004011c4      e8d7240000     call fcn.004036a0```
the first argument (ecx) is the address and the second argument (pushed to the stack) is the character pointer / string and the third argument is an index of size 4.
so it does something like this: `*first = *(char*)(second + third);`
later, gets input from user and checks againt the flag by copy pasted if checks (very apparent)...
a sample check:```│           0x00401df0      6a0a           push 0xa                    ; 10│           0x00401df2      8b06           mov eax, dword [esi]│           0x00401df4      8b4804         mov ecx, dword [eax + 4]│           0x00401df7      03ce           add ecx, esi│           0x00401df9      ff1558504000   call dword [sym.imp.MSVCP140.dll_public:_char___thiscall_std::basic_ios_char__struct_std::char_traits_char__::widen_char_const] ; 0x405058 ; ">`"│           0x00401dff      0fb6c0         movzx eax, al│           0x00401e02      8d55d8         lea edx, dword [var_28h]│           0x00401e05      50             push eax│           0x00401e06      8bce           mov ecx, esi│           0x00401e08      e8131e0000     call fcn.00403c20│           0x00401e0d      83c404         add esp, 4│           0x00401e10      8d8520faffff   lea eax, dword [var_5e0h]│           0x00401e16      8d4dd8         lea ecx, dword [var_28h]│           0x00401e19      50             push eax│           0x00401e1a      e821170000     call fcn.00403540│           0x00401e1f      85c0           test eax, eax│       ┌─< 0x00401e21      0f858a090000   jne 0x4027b1```that `lea eax, dword [var_5e0h]` is where a character of flag resides in runtime.
so I ran the program in ida using an external debugger and checked the value of each `lea eax, dword [...]` of if checks and wrote them and got the flag: `RaziCTF{Protected_Source_Code_dccef51a}`
it could be solved statically in linux using radare2 + r2pipe too now I think about it... :)