## 3DSCTF - A HUNDRED BASES OF GREY - MISC
When we enter the page, we are greeted with a beautiful soundtrack (which unfortunately doesn't hold any useful information for retrieving the flag) and a couple of gifs. From the website we can extract flag1-6, 1st, 2nd, 3rd, 4th gifs.
From the names we can expect that flag1-6 are the gifs that somehow decoded can give us the flag. All frames of gifs are one-colored, so let's look at their RGB values:
```pythonfrom PIL import ImageSequence, Image
colors = []for i in range(6):	im = Image.open('flag' + str(i + 1) + '.gif')	colors.append([])
	try:		while True:			new_frame = im.convert('RGB')			colors[i].append(new_frame.getdata()[0])			im.seek(im.tell()+1)	except EOFError:		pass
from pprint import pprintpprint(colors)```
After running, we get this output:
```[[(3, 3, 3),  (5, 5, 5),  (5, 5, 5),  (3, 3, 3),  (3, 3, 3),  (5, 5, 5),  ...  (3, 3, 3),  (5, 5, 5)], [(3, 3, 3),  (18, 18, 18),  (18, 18, 18),  (3, 3, 3),  (18, 18, 18),  (10, 10, 10),  ...  (13, 13, 13),  (5, 5, 5)],
  ...  [(189, 189, 189),  (217, 217, 217),  (199, 199, 199),  (189, 189, 189),  (15, 15, 15),  ...  (217, 217, 217),  (194, 194, 194)]]```
It seems like all colors have the same R, G and B values - maybe it will be a good idea to convert every frame to a number and inspect these sequences? Worth a try:
```pythonfor i in range(6):	colors[i] = [x for (x, j, k) in colors[i]]	print('flag' + str(i + 1) + '.gif:', colors[i])```
After conversion we get these sequences:```flag1.gif: [3, 5, 5, 3, 3, 5, 3, 5, 3, 3, 5, 5, 3, 3, 5, 3, 3, 3, 5, 5, 3, 5, 5, 5, 3, 5, 5, 3, 3, 5, 3, 5, 3, 5, 5, 3, 3, 3, 3, 5, 3, 3, 5, 5, 3, 5, 3, 5, 3, 3, 5, 5, 3, 5, 3, 3, 3, 3, 5, 5, 3, 5, 5, 5, 3, 3, 5, 5, 3, 3, 3, 3, 3, 5, 5, 3, 3, 5, 3, 3, 3, 3, 5, 5, 3, 3, 3, 5]flag2.gif: [3, 18, 18, 3, 18, 10, 3, 18, 15, 5, 13, 13, 3, 20, 3, 5, 13, 18, 3, 18, 18, 5, 13, 15, 3, 18, 3, 5, 13, 18, 5, 13, 5]flag3.gif: [10, 20, 18, 10, 18, 15, 18, 8, 18, 15, 18, 8, 10, 18, 10, 13, 18, 15, 18, 15, 10, 13]flag4.gif: [33, 43, 74, 59, 33, 66, 46, 59, 18, 23, 64, 10, 8, 38, 26, 66, 20, 3, 84, 84, 84, 84, 84, 84]flag5.gif: [64, 133, 26, 89, 64, 59, 23, 143, 36, 51, 36, 94, 36, 140, 13, 166]flag6.gif: [189, 217, 199, 189, 15, 140, 120, 31, 13, 145, 166, 135, 33, 115, 181, 168, 217, 194]```
Hmmm... first sequence has only two different values, maybe it holds some information in binary? Let's try to decode flag1 sequence to binary by mapping 3 to '0' and 5 to '1':
```pythonguessed_mapping = {3: '0', 5: '1'}print("".join([guessed_mapping[i] for i in colors[0]]))```
We get `0110010100110010001101110110010101100001001101010011010000110111001100000110010000110001`, which after translation to ASCII is `e27ea5470d1`.
That's a good sign! We got something printable, it even looks like something in hex. But what now? We guessed values that can be mapped to numbers in flag1 sequence - with other gifs it's a little bit more complicated. That's where 1st, 2nd, 3rd and 4th gifs come in handy. Let's look at RGB values on them (spoiler - they also have R = G = B):
```pythonstrips = []gifs = ['1st.gif', '2nd.gif', '3rd.gif', '4th.gif']
for i, name in enumerate(gifs):	im = Image.open(name)	strips.append([]) 	for j in range(0, 500, 20):		frame = im.convert('RGB')		strips[i].append(frame.getdata()[j]) 	strips[i] = [x for (x, j, k) in strips[i]]	print(name + ':', strips[i])```
Our script will print:
```1st.gif: [3, 5, 8, 10, 13, 15, 18, 20, 23, 26, 28, 31, 33, 36, 38, 41, 43, 46, 48, 51, 54, 56, 59, 61, 64]2nd.gif: [66, 69, 71, 74, 77, 79, 82, 84, 87, 89, 92, 94, 97, 99, 102, 105, 107, 110, 112, 115, 117, 120, 122, 125, 127]3rd.gif: [130, 133, 135, 138, 140, 143, 145, 148, 150, 153, 156, 158, 161, 163, 166, 168, 171, 173, 176, 179, 181, 184, 186, 189, 191]4th.gif: [194, 196, 199, 201, 204, 207, 209, 212, 214, 217, 219, 222, 224, 227, 229, 232, 235, 237, 240, 242, 245, 247, 250, 252, 255]```
It looks like pallette - all numbers from flag1-6 gifs can be found here. Looks like 2nd sequence is continuation of 1st, 3rd of 2nd and 4th of 3rd, so it might be a good idea to merge these into one pallette list. Also - we got something interesting from flag1.gif by mapping 3 to 0 and 5 to 1. Natural thought that could come is to map all numbers to their corresponding indices in our pallete:
```pythonpallette = sum(strips, [])colors = [map(pallette.index, i) for i in colors]
for i in range(6):	print('flag' + str(i + 1) + '.gif:', colors[i])```
We get:
```flag1.gif: [0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1]flag2.gif: [0, 6, 6, 0, 6, 3, 0, 6, 5, 1, 4, 4, 0, 7, 0, 1, 4, 6, 0, 6, 6, 1, 4, 5, 0, 6, 0, 1, 4, 6, 1, 4, 1]flag3.gif: [3, 7, 6, 3, 6, 5, 6, 2, 6, 5, 6, 2, 3, 6, 3, 4, 6, 5, 6, 5, 3, 4]flag4.gif: [12, 16, 28, 22, 12, 25, 17, 22, 6, 8, 24, 3, 2, 14, 9, 25, 7, 0, 32, 32, 32, 32, 32, 32]flag5.gif: [24, 51, 9, 34, 24, 22, 8, 55, 13, 19, 13, 36, 13, 54, 4, 64]flag6.gif: [73, 84, 77, 73, 5, 54, 46, 11, 4, 56, 64, 52, 12, 44, 70, 65, 84, 75]```
Unfortunately, mapping every number to binary (0 -> '0', 1 -> '1', 2 -> '10' and so on), merging into one string and translating to ASCII doesn't give any interesting results for flag2-6 gifs. So let's try a different approach...
So far we've used `GRAY` and `HUNDRED` from task name, what about `BASES`? Let's do some converting!
Highest number on the second list is 7, so that may suggest octal. Indeed, after joining numbers on a list we get `066063065144070146066145060146141` which converted to ASCII gives us `635d8f6e0fa`.
However, if we use the same approach to the next list, we do not get anything that makes sense. So let's try next "sensible" base - decimal. `3763656265623634656534` maps to `7cebeb64ee4`.
Next list has many `32` at the end, which suggests Base32 with `32` as a padding. `MQ4WMZRWGIYDCOJZHA======` maps to `d9ff6201998`.
Penultimate list is encoded in Base64 (the same idea - last value is `64`). `YzJiYWI3NTNkN2E=` maps to `c2bab753d7a`.
Last, but not least - the last list is encoded in Ascii85, Adobe version (highest number is 84). `<~@<5skB4u$qCi+%~>` maps to `asdfghjklmn`.
So, after concatenating all of those together and adding necessary `3DS{` and `}` we obtain `3DS{e27ea5470d1635d8f6e0fa7cebeb64ee4d9ff6201998c2bab753d7aasdfghjklmn}` which is the correct flag.
Whole script (with decoding included) can be found [here](https://gist.github.com/michsiw96/14b1e60ae2e93137ec4cde61e99c7309).