**Tags:** crypto

Rating:

# Count on me

## 467 Points

-----

> CORRECTION: AES 256 is used. Not AES 128.

> Hint! To decrypt the message, you need a hex-string of 64 characters in length.

> Hint! WARNING: This challenge has been updated at 02-02-2020 15:00 UTC to fix a critical mistake.

-----

We are given the source for the challenge

```py

from Crypto.Cipher import AES

# this is a demo of the encyption / decryption proceess.

a = 'flagflagflagflag'

key = '1111111111111111111111111111111111111111111111111111111111111111'.decode('hex')

iv = '42042042042042042042042042042042'.decode('hex')

#encrypt

aes = AES.new(key,AES.MODE_CBC, iv)

c = aes.encrypt(a).encode("hex")

print c

#decrypt

aes = AES.new(key,AES.MODE_CBC, iv)

print aes.decrypt(c.decode("hex"))

```

together with all the challenge details

```

AES 256 CBC

iv: 42042042042042042042042042042042

ciphertext: 059fd04bca4152a5938262220f822ed6997f9b4d9334db02ea1223c231d4c73bfbac61e7f4bf1c48001dca2fe3a75c975b0284486398c019259f4fee7dda8fec

```

The key for the AES decrption is a .png

![Key Glyphs](https://raw.githubusercontent.com/jack4818/CTF/master/HackTM/key.png)

and the task of this challenge is to interpret this string as a len64 hex string.

Looking at each glyph it seemed reasonable to see this as a Vigesimal system. The lower half counting between `0-4` and the upper lines counting `[0,5,10,15]`. This means each glyph can be a number between `0,19`.

Going left to right we obtain an array on base10 integers

```py

glyphs = [19, 3, 10, 15, 2, ?, 16, 16, 18, 12, 19, 6, 19, 12, 8, ?, 5, 8, 17, 18, 18, 5, 9, 3, 11, 10, 1, 10, 10, 0, 10, ?, 0, 8, 18, 10, 0, 15, 18, 5, 18, 14, 19, 1, 1, 0, 4, 6, 15, 4, 11, 16, 10, 8, 14, 5, 13, 16, 9]

```

Where I have replaced the blurred glyphs with `?`. The question is, how do we take these numbers and get a len 64 string? To test, I swap all `? = 0`. The first thing I tried was joining each element to obtain one long int in base10 and converting to a hex string:

```py

int_10 = int(''.join([str(i) for i in glyphs]))

>>> 1912238077151019519101301131115151171262422020013152031511518194401653166721318114717

int_16 = hex(int_10)[2:]

>>> 'fbfd6a5a0c04ee47556e2a9a42a7eb5f2280c8c7830703c5d41bbce3e0508caa29d59d'

len(int_16)

>>> 70

```

Then I tried converting each glyph to base16 and then concat:

```py

concat_int_16 = ''.join([hex(i)[2:] for i in glyphs]

>>> 13c238077fa13513ad01dbff111c624220200df203f1f1213440105310672d121e711

len(concat_int_16)

>>> 69

```

Neither of these were appropriate. I got stuck here for a while and solved some other challenges. Coming back later I had the idea of concating each glyph from base20. One way to do this would be to go through `glyphs` and replace `{10,19} -> {a,j}`, but I found it easier to just grab an int_2_base function from an old challenge and solve

```py

import string

digs = string.digits + string.ascii_letters

def int2base(x, base):

if x < 0:

sign = -1

elif x == 0:

return digs[0]

else:

sign = 1

x *= sign

digits = []

while x:

digits.append(digs[int(x % base)])

x = int(x / base)

if sign < 0:

digits.append('-')

digits.reverse()

return ''.join(digits)

glyphs = [19, 3, 10, 15, 2, 0, 16, 16, 18, 12, 19, 6, 19, 12, 8, 0, 5, 8, 17, 18, 18, 5, 9, 3, 11, 10, 1, 10, 10, 0, 10, 0, 0, 8, 18, 10, 0, 15, 18, 5, 18, 14, 19, 1, 1, 0, 4, 6, 15, 4, 11, 16, 10, 8, 14, 5, 13, 16, 9]

int_20 = ''.join([int2base(i, 20) for i in glyphs])

int_10 = int(int_20, 20)

int_16 = hex(int_10)[2:]

print(int_20)

print(int_10)

print(int_16)

print(len(int_16))

>>> j3af20ggicj6jc8058hii593ba1aa0a008ia0fi5iej11046f4bga8e5dg9

>>> 55273615734144947969560678724501073228899919180366431845779064168750747885529

>>> 7a33c20284ab07c18b0100b75594af73c47005d27a90b86496f3bbe27c6e1fd9

>>> 64

```

Now we're getting there!! All that's left is to go through all `20**3` options from the three missing glyphs and decode the ciphertext

## Python Implementation

```py

from Crypto.Cipher import AES

from Crypto.Util.number import long_to_bytes

import string

digs = string.digits + string.ascii_letters

def int2base(x, base):

if x < 0:

sign = -1

elif x == 0:

return digs[0]

else:

sign = 1

x *= sign

digits = []

while x:

digits.append(digs[int(x % base)])

x = int(x / base)

if sign < 0:

digits.append('-')

digits.reverse()

return ''.join(digits)

ciphertext = bytes.fromhex('059fd04bca4152a5938262220f822ed6997f9b4d9334db02ea1223c231d4c73bfbac61e7f4bf1c48001dca2fe3a75c975b0284486398c019259f4fee7dda8fec')

iv = bytes.fromhex('42042042042042042042042042042042')

for i in range(0,20):

for j in range(0,20):

for k in range(0,20):

glyphs = [19, 3, 10, 15, 2, i, 16, 16, 18, 12, 19, 6, 19, 12, 8, j, 5, 8, 17, 18, 18, 5, 9, 3, 11, 10, 1, 10, 10, 0, 10, k, 0, 8, 18, 10, 0, 15, 18, 5, 18, 14, 19, 1, 1, 0, 4, 6, 15, 4, 11, 16, 10, 8, 14, 5, 13, 16, 9]

bigint_20 = ''.join([int2base(i, 20) for i in glyphs])

bigint_10 = int(bigint_20,20)

key = long_to_bytes(bigint_10)

aes = AES.new(key,AES.MODE_CBC, iv)

plaintext = aes.decrypt(ciphertext)

if b'Hack' in plaintext:

print(plaintext)

```

#### Flag

`HackTM{can_1_h@ve_y0ur_numb3r_5yst3m_??}`

Original writeup (https://github.com/jack4818/CTF/tree/master/HackTM#crypto).