Resources/Tips
- Pay attention to the flavortext!
- How to debug in IDA and watch for changes in certain areas of the binary
The secret of this next challenge is cleverly hidden. However, with the right approach, finding the solution will not take an overlong amount of time.
tl;dr
- The flag is actually hidden in the ciphertext, but is “Overlong”
- The print loop never decrypts til the flag as there is a preset boundary
- To get past this boundary you can:
- Patch the file
- Dynamically alter stack variables during debugging
- The flag will then be decrypted!
Walkthrough
When launching the .exe we get this:
One of my first observations was that the message was not stored in plaintext in the binary. This meant that the message was either encrypted or dynamically generated by the binary!
The first function we see when opening in IDA is “starter”:
As we can see from the pink box, that portion of the assembly is what displays the text we see in the first screenshot.
As the function call uses stack variables, convention is to push arguments onto the stack from last to first: dsMessageBoxA(0, Text, Caption, 0)
int MessageBoxA(
HWD hWnd, WindowHandler
LPCSTR lpText, MessageTobeDisplayed
LPCSTR lpCaption, TitleBox TITLE text
UINT uType OK button
);
Notice anything fishy here in the assembly above? I missed it and didn’t realise until much later on… It isn’t obvious until you see how the function
sub_401160
operates:
After some reversing, this is the result: (click image to expand)
The thing I did wrong at the beginning was I did not fully understand what this function did yet I dived deep into the decrypt
function which wasted a lot of time.
The function arguments can be determined from the following (ref. blue box):
The main point of interest is that the function can return either:
- The length of the string at
Text
up til the first EOL character (NULL) - The counter when it reaches 28
whichever occurs first.
So how does "Overlong" apply to this challenge?
Looking at the ciphertext
string, it is much longer than 28 characters…
The route I ended up taking was to modify stack variables during debug time, although there is more than one way to solve this challenge…
We first add a breakpoint at the following locationi (F2 key):
After the breakpoint is set we launch the debugging session (F9 key), which should stop at exactly that point.
We step over the current instrcution such that the value 0x1c
/28
is pushed onto the stack:
From there we edit the value thats passed into the decode
function to be much much longer… say maybe 0xcc
instead! (F2 key for edit)
After this we let the program continue execution (F9 key again) and voila:
What I learned
- Don’t fall too deep into rabbit holes
- Don’t be afraid to use dynamic reversing… ie. debugging
Solving the challenge would be 100x harder if doing statically