# John Cena
This challenge was fairly simple, but had one or two complications.
The first step was parsing the image. Before I could script it, I opened upthe image in GIMP to have a look at spacing. As it turned out, each brailleblock was 30 pixels wide, but the heights weren't consistent. On odd rows itwas 43 pixels high, and even rows were 44 pixels high. There were 33 blocks toa row, and 57 rows in the image.
After taking measurements, it was scripting time. I used `PIL` and `numpy`,becuase I like python :P. The main chunker is shown below:
```pyi = Image.open("braille.png")a = np.asarray(i)a = a[:, 6:-6, :]
slices = []ypos = 0for row in range(57):    for col in range(33):        chunk = a[ypos: ypos+44, col * 30: (col + 1) * 30, :]        slices.append(chunk)
    ypos += 44 if row % 2 else 43```
Rather than multiplying the `row` value, I tracked the current y positionusing the `ypos` variable, which allowed me to account for the varying rowheights. There were over a thousand individual chunks, so I've only put one ofthem here for illustation:
![](https://i.imgur.com/z7QkAar.png)
After compiling the chunks, I needed to identify the circles within them.Rather that using anything fancy, I just tested 6 pixels in each chunk, eachslightly off the centre of one of the circles. For larger circles, it wouldhit a pink pixel, but smaller circles would hit a black pixel. This code forthis is below:
```pydata = ''for i in slices:    px = [        i[4, 7, 0] > 50,        i[19, 7, 0] > 50,        i[34, 7, 0] > 50,
        i[4, 20, 0] > 50,        i[19, 20, 0] > 50,        i[34, 20, 0] > 50,    ]    p = ''.join(map(str, map(int, px)))    data += lookup[p]```
I converted each block into a 6-digit string of 0s and 1s, allowing me to mapit into a braille character using
```pylookup = {    '100000': '⠁',    '110000': '⠃',    '100100': '⠉',    '100110': '⠙',    '100010': '⠑',    '110100': '⠋',    '110110': '⠛',    '110010': '⠓',    '010100': '⠊',    '010110': '⠚',    '001111': '⠼',    '000000': ' ',}```
The output braille, sadly, wasn't technically valid. The `⠼` characternormally indicates that the next sequence of characters create a number, untila blank symbol is found. For example, `⠼⠁⠃` would be `12`. In this case,however it was used to indicate that only the immediate next character was anumber. This means that same symbol of characteres decoded to `1B`. To decodethis, I wrote the horrible bit of python shown below:
```pynums = '⠚⠁⠃⠉⠙⠑⠋⠛⠓⠊'charas = ' abcdef???????'
is_num = Falseout = ''for i in BRAILLE:    if i == '⠼':        is_num = True    else:        idx = nums.index(i)        out += str(idx) is_num else charas[idx]        is_num = Falseprint(out)```
This produced a hex string, shown below as a hexdump.
```00000000  7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 02 00 3e 00 01 00 00 00  |.ELF..............>.....|00000018  80 00 40 00 00 00 00 00 40 00 00 00 00 00 00 00 e0 00 00 00 00 00 00 00  |..@.....@.......à.......|00000030  00 00 00 00 40 00 38 00 01 00 40 00 04 00 03 00 01 00 00 00 07 00 00 00  |[email protected]...@.............|00000048  80 00 00 00 00 00 00 00 80 00 40 00 00 00 00 00 80 00 40 00 00 00 00 00  |..........@.......@.....|00000060  49 00 00 00 00 00 00 00 49 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00  |I.......I...............|00000078  00 00 00 00 00 00 00 00 b8 01 00 00 00 bf 01 00 00 00 be b4 00 40 00 31  |........¸....¿....¾´[email protected]|00000090  c9 67 8b 14 0e 83 c2 31 67 89 14 0e ff c1 83 f9 15 75 ee ba 15 00 00 00  |Ég....Â1g...ÿÁ.ù.uîº....|000000a8  0f 05 b8 3c 00 00 00 31 ff 0f 05 00 26 1f 18 4a 3b 03 42 00 47 0a 00 42  |..¸<...1ÿ...&..J;.B.G..B|000000c0  03 2e 04 32 41 44 31 04 4c 00 2e 73 68 73 74 72 74 61 62 00 2e 74 65 78  |...2AD1.L..shstrtab..tex|000000d8  74 00 2e 64 61 74 61 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |t..data.................|000000f0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |........................|00000108  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |........................|00000120  0b 00 00 00 01 00 00 00 07 00 00 00 00 00 00 00 80 00 40 00 00 00 00 00  |..................@.....|00000138  80 00 00 00 00 00 00 00 33 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |........3...............|00000150  10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 11 00 00 00 01 00 00 00  |........................|00000168  03 00 00 00 00 00 00 00 b4 00 40 00 00 00 00 00 b4 00 00 00 00 00 00 00  |........´.@.....´.......|00000180  15 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00  |........................|00000198  00 00 00 00 00 00 00 00 01 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00  |........................|000001b0  00 00 00 00 00 00 00 00 c9 00 00 00 00 00 00 00 17 00 00 00 00 00 00 00  |........É...............|000001c8  00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |........................|```
I didn't have Linux handy, and the binary wouldn't run in WSL, so I did theless-than-obvious thing and converted it to python.
Running it through radare showed that it was grabbing some data, adding 49(0x31) to each byte, then printing it out.
```[0x00400080]> pdf            ;-- section..text:            ;-- section.LOAD0:            ;-- rip:/ (fcn) entry0 53|   entry0 ();|           ; CALL XREF from 0x00400080 (entry0)|           0x00400080      b801000000     mov eax, 1                  ; [04] -rwx section size 73 named LOAD0|           0x00400085      bf01000000     mov edi, 1|           0x0040008a      beb4004000     mov esi, 0x4000b4           ; section..data ; "&\x1f\x18J;\x03B"|           0x0040008f      31c9           xor ecx, ecx|           ; CODE XREF from 0x004000a1 (entry0)|       .-> 0x00400091      678b140e       mov edx, dword [esi + ecx]|       :   0x00400095      83c231         add edx, 0x31               ; '1'|       :   0x00400098      6789140e       mov dword [esi + ecx], edx|       :   0x0040009c      ffc1           inc ecx|       :   0x0040009e      83f915         cmp ecx, 0x15               ; 21|       `=< 0x004000a1      75ee           jne 0x400091|           0x004000a3      ba15000000     mov edx, 0x15               ; 21|           0x004000a8      0f05           syscall|           0x004000aa      b83c000000     mov eax, 0x3c               ; '<' ; 60|           0x004000af      31ff           xor edi, edi|           0x004000b1      0f05           syscall            ;-- section_end..text:\           0x004000b3  ~   0026           add byte [rsi], ah            ;-- section..data:|           ; DATA XREF from 0x0040008a (entry0)|           0x004000b4      26             invalid                     ; [02] -rw- section size 21 named .data[0x00400080]>```
Running that in my python shell gave me
```py>>> a = '261f184a3b034200470a0042032e0432414431044c'>>> a = binascii.unhexlify(a)>>> print(''.join(chr(i + 49) for i in a))WPI{l4s1x;1s4_5crub5}>>> ```
and that was the flag.