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 :nut_and_bolt:
  • The flag will then be decrypted!

Walkthrough

When launching the .exe we get this:
intro

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!
no-strings

The first function we see when opening in IDA is “starter”:
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: :gear:

sub

After some reversing, this is the result: (click image to expand)

reverse-start

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

function

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. :thinking:

So how does "Overlong" apply to this challenge?

Looking at the ciphertext string, it is much longer than 28 characters…
cipherlength

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… :twisted_rightwards_arrows:

We first add a breakpoint at the following locationi (F2 key):
break

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:
stack0-view

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)

stackedit

After this we let the program continue execution (F9 key again) and voila:
flag

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