rev

Challenges

hidden string

This binary seems to be giving me some prompts but where are these strings coming from??

note: for the flag use the part of it that looks like it might sense. There is a slight bug in the challenge :)

challengearrow-up-right

circle-check
  • My initial reconnaissance didn't yield anything meaningful, strings, file carve or obj dump didn't really provide much information due to the output is obfuscated.. So ...its binary ninja huh, I just like the theme and the layout of this app so much. Open it and we jumped to main, and noticed the helper sub_4015e0 and the leaf sub_401550. All three touched data_404160, data_404168, and data_404170,

  • They all interact with the data section which...is the flag being scatter everywhere?

  • A three-column table in .data. Later figured but the way I called these are per-entry (pointer, length, xorKey) layout.

  • See it in Binary Ninja the function and the data arrays:

LOGICALLY SPEAKING:

  • sub_401550(id) XOR-decodes the id-th string with its key, prints length-1 bytes, then XORs it back. BN shows the table layout clearly:

  • The stride is therefore 0x18 per entry; valid IDs are 0..0x2f (guarded in both the printer and checker).

Field (per id)
Address pattern
Meaning

(&data_404160)[id * 3]

base 0x404160 + id * 0x18 + 0x00

pointer to bytes

*(id * 0x18 + 0x404168)

base 0x404168 + id * 0x18

length (incl. \0)

*(id * 0x18 + 0x404170)

base 0x404170 + id * 0x18

XOR key (1 byte)

Focus on the highlighted lines (important piece), phewwwww, that's a lot of low level code (\tuf), now lets run the binary, we will see prompts like:

  • We already know main calls sub_4015e0 with small integer arrays. Each element is an ID into a string table. sub_4015e0 prints the corresponding strings with spaces, and optionally a newline:

  • Inside that, sub_401550(id) does it things (explained above)

  • We also know that the prefix check ENO{???} is also included:

  • The machine is little-endian, so 0x7b4f4e45 in a 32-bit register corresponds in memory to bytes (you get the idea):

  • Now we know where it all starts...to not bore you, but after this, you pretty much just traced the line after the ENO{ to see what encryption logic is being applied, and reverse it; The moment you have a string that pass the check "enter flag", done.

circle-info

And with all that information, the solve script follow these steps:

  • First -- open the string table in .data (starting at 0x4160), treating each 24-byte row as (ptr, len, key)

  • XOR-decoding (0x61) (they cancels out) the bytes so we can read the hidden words.

  • Then it walks the byte stream at 0x2020 as (index, offset) pairs and plucks the corresponding characters out of that table to rebuild the message.

    • It stops on the first } or the first (0,0) pair (to skip the padding that would add www) <-- that www is what the announcement meant.

  • Finally, wraps the result with ENO{…} for full flagasano.

  • ENO{stackxorrocks}

Last updated