Analyse Me
Description
Challenge files
- server.py earlier analyse.py which is quite unsolvable according to me
Lets take a look at contents of server.py
Here we have two parts of the challenge, Only after solving the first, we can move forward to the second part.
The first part is simple (figuratively), We are presented a "|" separated list of integers each element of which is bigint representation of ascii string of random base encodings out of bases :- 16,32,64,85
Lets see what we get after processing data from the network and converting it to strings
Seems all right, now we need to decode the stuff.
Well, one could say (most of the times) which decoding is it by simply looking at the characters used AND by the size of encoded string.
| Encoding | Block size | characters |
|---|---|---|
| Base16 | 2 | 0-9a-f |
| Base32 | 8 | 0-9A-Z |
| Base64 | 4 | 0-9a-zA-z+/ |
| Base85 | 1 | 0-9a-zA-Z!#$%&()*+-;<=>?@^_{|}~\` |
But why do these have an association of block size to decode properly?
Because, to decode a string, we need the result should be a byte-string.
and a byte is 8 bits, whereas what each character of an encoding could mean is its size.
Base16 16 values = 4 bits => each character can contain 4 bits of information. And to make a multiple of 8 bits, we would require 2 characters.
Base32, 32 values = 5bits => each character can contain 5 bits of information. And to make a multiple of 8 bits, we would require a block of 8 characters, and each block would decode to a byte-string of size 5
Base64, 64 values = 6bits => we would require 4 characters to form a multiple of 8, and hence each 4 character block decodes to 3 character block
Base85? We have a weird base, we stop caring. 😄
Enough of detour, lets decode now
We will simply start from lower base, try to decode, if it results in error, move to an higher base.
But there’s one caveat, the string may actually decode on a lower base, and produce garbage decoding.
We may check for decoded string to be in printable domain and raise an error otherwise. This way we may ensure correctness.
G00D_TH3_FIRST_P4RT_I5_D0N3_HER3_I5_4_F14G_F0R_Y0U_H4RD_W0RK_=_zh3r0{f4k3_f14g}.
Awesome! We are now presented with the second part of the challenge
Writing so much in this writeup, I can tell, this could have been easily two challenges. But anyways
Now this is a really obfusticated way of doing things. It is basically
- Replacing each byte with its substituent in
table - Repeating this some random number of times from 2-4
- Xoring the resultant string with the key obtained from first part
For reversing this, we will need to reverse the TABLE and xor it with the provided key
The TABLE itself was weird way of writing a table XD
Now we need to do the de-substitution of the flag_unxored bytes, until we get the flag