Rating:
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... :)