Challenge Writeup
When unpacking and executing the binary both via the command line and as an GUI application, nothing
happens. So let's load the binary into IDA. Whilst analyzing the main function we see that we are
expected to supply an argument when executing the binary. If we supply one argument, that argument
will be used as a parameter for the function sub_401000. If we try
executing the binary via the command line again, and supply an argument, we receive two strings and
the application exits. Time to dive in deeper.
Jumping into the function, the rather long sequential mov instructions are rather curious
and deserve closer analysis. In total, 36 bytes get loaded into ebp+var_28 up and until
ebp+var_5. This is also exactly the length of the loop which occurs a little later. In
this loop, for each iteration a memory page is allocated using VirtualAlloc with a size
of 1000 bytes. The page is set to PAGE_EXECUTE_READWRITE. The return value of the call to
VirtualAlloc is stored in [ebp+var_34], which will be called later. In
between the page creation and subsequent call, the allocated memory page is filled as follows: for the
nth round of iteration, the nth byte from the user's input is taken and added to the nth byte of the
previously allocated 'string'. The resulting byte is then written to the memory page. As this page is
then executed, and becomes inherently part of the program, any invalid instructions will cause the
program to crash. So we have to come up with an ingenious way of ensuring this page does not crash.
However, we are only limited to one specific byte for each iteration.
Therefore, we have to identify a byte that serves as a thrustworthy opcode that is unlikely to crash
if it is executed. One opcode that immediately comes to mind is the opcode 0xC3, which is
the RET instruction which will return execution to the calling program, as such being quite harmless.
Based on the input constraints and length check, we determine that the maximum length of the input
string is 30. So we can sort of brute force our way to ensure the output byte is always C3.
Eventually, you will end up with the following bytes, which all appear within ASCII range.
input = "\x73\x65\x65\x20\x74\x68\x72\x65\x65\x2x\x20\x43"
input += "\x33\x20\x43\x33\x20\x43\x33\x20\x43\x33\x20\x43"
input += "\x33\x20\x43\x33\x20\x43\x33\x21\x20\x58\x44"
Based on that we can conclude that the input string needs to be: see
three, C3 C3 C3 C3 C3 C3 C3! XD.
Eventually we end up with the flag for this challenge
i_w0uld_l1k3_to_RETurn_this_joke@flare-on.com. And with that,
we have completed the fourth Flare-On challenge!