# Cobol OTP challenge

### Description

To save the future you have to look at the past. Someone from the inside sent you an access code to a bank account with a lot of money. Can you handle the past and decrypt the code to save the future?

### Setup

The challenges include two files `otp.cob`

and `out`

`otp.cob`

is a Cobol program that at a glance, encrypts a message by xoring an unknown key (50 bytes) with a message (50 bytes as well)

`out`

looks like an encrypted message:

$ hexdump -C out

00000000 45 6e 74 65 72 20 79 6f 75 72 20 6d 65 73 73 61 |Enter your messa| 00000010 67 65 20 74 6f 20 65 6e 63 72 79 70 74 3a 0a a6 |ge to encrypt:..| 00000020 d2 13 96 79 3b 10 64 68 75 9f dd 46 9f 5d 17 55 |...y;.dhu..F.].U| 00000030 6a 68 43 8f 8c 2d 92 31 07 54 60 68 26 9f cd 46 |jhC..-.1.T`h&..F| 00000040 87 31 2a 54 7b 04 5f a6 eb 06 a4 70 30 11 32 4a |.1*T{._....p0.2J| 00000050 0a |.|

### Issue 1

Taking a look at the heart of the encryption:

`call 'CBL_XOR' using ws-key(ws-ctr:1) ws-flag by value ws-xor-len end-call`

Reading the documentation https://documentation.microfocus.com/help/index.jsp?topic=%2FGUID-0E0191D8-C39A-44D1-BA4C-D67107BAF784%2FHRCLRHCALL5H.html we discover that this performs a

xor between `ws-key[ws-ctr]`

and `ws-flag`

with the length of `ws-xor-len`

bytes. The result is stored in `ws-flag`

.

Looking at the types we’ve understood that `ws-ctr`

and `ws-xor-len`

are one **decimal digit** long only. Therefore `ws-ctr`

will wrap around every 10 bytes.

Thus, this limits the valid key space, since the xor of the key with the encrypted data must yield a printable character. In this case, we see that

encrypted[1] ^ key[1] = printable_char1 encrypted[11] ^ key[1] = printable_char2 encrypted[21] ^ key[1] = printable_char3 encrypted[31] ^ key[1] = printable_char4 encrypted[41] ^ key[1] = printable_char5

And, of course, this holds for the `key[2]`

, etc..

### Issue 2

Remembering that Cobol arrays are 1 based, the value of `ws-flag(ws_ctr:1)`

when `ws_ctr`

is 0 yields nothing and the xor is effectively nullified, and this gives us 5 unencrypted chars for free:

<code>*********u*********C*********&*********_*********\n</code>

Since we had ~40 options for every character and still have 9 key character to guess we start by assuming the message looks like “`flag{***************}\n`

“, where the * mean unknown character.

Pluging in the right key chars to yield the above string we get:

<code>flag{***_u_c4n_***_CO2_c3***_&_s4v3***3_fUtUr***}\n</code>

Now we could try to read the message and guess the needed keys. By assuming the word save (s4v3) should have _ after it and future is a reasonable word we tried all the options to get meaningful phrases from:

<code>flag{N**_u_c4n_b**_CO2_c3r**_&_s4v3_**3_fUtUrE**}\n</code>

With a little guess work we think it reads something along the lines of: `Now you can buy CO2 cer** & save the future**`

Pluging in our guesses gave us the full flag:

<code>flag{N0w_u_c4n_buy_CO2_c3rts_&_s4v3_th3_fUtUrE1!}</code>