Description: I’ve recently got into woodworking and have build a beautiful fence just like this one.
Now I’m working on a flag, but it turns out all garbled for some reason…
T0n40g5BG03cmk0D1hr}T{dFe_3g_3buL_5_n0
In this crypto challenge, only a ciphertext is given which needs to be decoded and the hint is also given.
This classic challenge ciphertext is text that is encoded using Rail Fence Encoding (also called zigzag cipher) is a transposition cipher. The message is written in a zigzag pattern on an imaginary fence, thus its name. It is not strong as the number of keys is small enough to brute force them.
Move on to rev category, this challenge is like Flagchecker of ELF 64 Binary
Let’s try to executing the binary file
Here’s the decompiled of main function,
From the decompiled code looks like an xor program and I’m quite curious about what the target array will do.
Aha nice! the value of target array has discovered from .rodata section.
So here’s the conclusion, The program will reads the flag, checks its length, calculates a seed for the random number generator from the flag, and then checks each character of the flag against a value in the target array.
The target array is XORed with the result of rand() % 0x100. Since the seed for rand() is determined by the flag, we can predict the sequence of random numbers. However, that the seed is calculated by multiplying all the ASCII values of the characters in the flag, which makes it difficult to reverse.
Here’s the high-level approach to solve this:
Brute force the seed: Since the seed is a product of ASCII values, and ASCII printable characters range from 32 to 126, the maximum value for the seed is 126^63. However, this is not feasible to brute force. But, considering that the flag format is TBTL{.*}, we can reduce the search space. The seed is also an uint (32-bit), so the maximum value is 2^32-1. This is feasible to brute force.
Predict the random sequence: Once the seed are correct, we can generate the same sequence of random numbers as the program.
Recover the flag: Now that the same rand() sequence, we can manage to recover the flag. For each character in the flag, calculate target[i] ^ (rand() % 0x100) to get the original character.