HackTheBox – Ebola Virus

In this write-up we will be visiting theĀ Ebola Virus challenge from HackTheBox.

We suspect that some terrorists have a plan to use the Ebola virus. We have managed to collect an encypted message and its key. Can you help us decrypt the message?


We are given two files, encrypted.bin and key.txt, of which the key.txt file contains the following contents.

CTGAAATGTTCCGCGAGCCGAACCGATTCACCGCCTAGAAACGTATTGTGCTGGTGTGCGGCGGTTAGAGATATTAGGTAGCGCCGTTACTCTAACATTTCGAATCAACCTTTCAGGGGAGTCACTGCCATCGTAAGTAGAGTACTTAGCATCGATGGCCATGCCTACTAATTACAGGCTGAATGACACTAAACCTTAGTTCACTGACCCGTTTTGTCATGTACTCTTGTGGTATGGGTCTTCAAATTGATCTGATTGGGAAGATAGAAAAACGGCTCTATCCTGGGTCGAGCCTCCCATGAAGCAGTCAAGGGGCCGCGAGGACTTCGATACTTGCCCTGCTCGAGCACATTTTAAAGCTTATTCCACATACTAGACTTACCCCCCGGCGTGTCGTACTGGAAGGTTAAACCTCTTGAGTTGATCTGACAACCTAGACGCGTGCCACGTTGTGTGGGATAGGTCACTCTCATTTCCACGAGGGACCAGAACCTTTGGCAATCCAGTTATTCTGCACTCGTGGCCGCCTCTCCTGGCAGGGGACCGGTAAGTTTGCGTATTCGCCGGGGAGTGGAGACGGATCGTCGTACACTGTTTCGAAAATTTTTGAGGATGGAGAGCAGAGCTATTGGATAAACGCTTGTACAGGTTCAATACTATTAGCAACGTGCCACCGGCACAGCTATCTCTGTTTCGCATGAAAGAGCCGTTAATCACGACGTTTAATCGAAACACATACCGATGGTCTACGAATATTATATCCGATACTAAGTCGGCCGCCGCAGTCCAGACGCCATATCGCTTTGAAGACCCCAAGGCGAACATTAACCGGTACGAGCAACTGCGGAGTGCCCTGCAATAGTCCGTCTGTAAAGGGCCCAGGCTAGGGCAAATAGTCCCTAAAACTAGAGATGGTCAACCGCTATGTGGGGCATTCTCCGTGAGACTCAGCCGTATTACAGTGAGCGTATTCCCAAACTCCCCTTCTGTGTATGACCAGTGTCGCTGCAAATGGACCGAGCAG

Looking at the contents of the file, we notice that the only symbols present are A, G, C and T. Interestingly, these are equivalent to the four nucleobases in the nucleic acid of a DNA sequence. Googling various combinations of DNA and ciphers, we stumble upon a promising GitHub repository.

In short, the encryption described in the GitHub repository will transform a string into a bit string comprising of 1 and 0, and then for every two bits in the bit string, it will transform them as follows.

  • 00: A
  • 01: C
  • 10: G
  • 11: T

Thus, in order to decode the DNA Sequence cipher, we must map the A, G, C, and T characters to their respective bits, after which we convert to single bytes for every 8 bits. This can be scripted in Python as shown below.

encoded = 'CTGAAATGTTCCGCGAGCCGAACCGATTCACCGCCTAGAAACGTATTGTGCTGGTGTGCGGCGGTTAGAGATATTAGGTAGCGCCGTTACTCTAACATTTCGAATCAACCTTTCAGGGGAGTCACTGCCATCGTAAGTAGAGTACTTAGCATCGATGGCCATGCCTACTAATTACAGGCTGAATGACACTAAACCTTAGTTCACTGACCCGTTTTGTCATGTACTCTTGTGGTATGGGTCTTCAAATTGATCTGATTGGGAAGATAGAAAAACGGCTCTATCCTGGGTCGAGCCTCCCATGAAGCAGTCAAGGGGCCGCGAGGACTTCGATACTTGCCCTGCTCGAGCACATTTTAAAGCTTATTCCACATACTAGACTTACCCCCCGGCGTGTCGTACTGGAAGGTTAAACCTCTTGAGTTGATCTGACAACCTAGACGCGTGCCACGTTGTGTGGGATAGGTCACTCTCATTTCCACGAGGGACCAGAACCTTTGGCAATCCAGTTATTCTGCACTCGTGGCCGCCTCTCCTGGCAGGGGACCGGTAAGTTTGCGTATTCGCCGGGGAGTGGAGACGGATCGTCGTACACTGTTTCGAAAATTTTTGAGGATGGAGAGCAGAGCTATTGGATAAACGCTTGTACAGGTTCAATACTATTAGCAACGTGCCACCGGCACAGCTATCTCTGTTTCGCATGAAAGAGCCGTTAATCACGACGTTTAATCGAAACACATACCGATGGTCTACGAATATTATATCCGATACTAAGTCGGCCGCCGCAGTCCAGACGCCATATCGCTTTGAAGACCCCAAGGCGAACATTAACCGGTACGAGCAACTGCGGAGTGCCCTGCAATAGTCCGTCTGTAAAGGGCCCAGGCTAGGGCAAATAGTCCCTAAAACTAGAGATGGTCAACCGCTATGTGGGGCATTCTCCGTGAGACTCAGCCGTATTACAGTGAGCGTATTCCCAAACTCCCCTTCTGTGTATGACCAGTGTCGCTGCAAATGGACCGAGCAG'
decoder = { 'A': '00', 'C': '01', 'G': '10', 'T': '11' }
decoded = ''.join([decoder[c] for c in encoded])

octets = [int(decoded[i:i+8], 2) for i in range(0, len(decoded), 8)]

Upon running the above script, the octets variable ends up containing the following data.

[120, 14, 245, 152, 150, 5, 143, 69, 151, 32, 27, 62, 231, 174, 230, 154, 242, 35, 60, 172, 153, 111, 29, 193, 63, 96, 208, 95, 210, 168, 180, 121, 77, 176, 178, 44, 124, 147, 99, 165, 57, 113, 195, 196, 167, 131, 132, 112, 23, 203, 209, 225, 91, 254, 211, 177, 223, 186, 206, 173, 244, 15, 141, 227, 234, 8, 200, 0, 105, 220, 215, 171, 98, 93, 83, 130, 75, 66, 169, 102, 40, 125, 140, 126, 87, 157, 137, 19, 252, 9, 243, 212, 76, 114, 31, 21, 86, 155, 182, 199, 160, 175, 1, 119, 226, 248, 222, 16, 92, 134, 110, 81, 190, 238, 163, 43, 71, 116, 253, 70, 42, 20, 129, 127, 164, 53, 47, 61, 228, 118, 233, 101, 221, 122, 74, 161, 107, 11, 249, 179, 217, 106, 139, 162, 26, 54, 219, 17, 239, 216, 3, 255, 138, 58, 34, 72, 156, 250, 48, 25, 251, 18, 189, 12, 115, 201, 6, 229, 22, 145, 39, 55, 123, 246, 78, 2, 37, 188, 52, 97, 191, 13, 128, 68, 197, 142, 183, 24, 51, 204, 214, 49, 194, 218, 89, 100, 181, 33, 148, 205, 159, 224, 133, 80, 166, 4, 240, 90, 198, 36, 30, 104, 185, 94, 67, 45, 109, 236, 10, 149, 41, 202, 144, 50, 213, 192, 28, 136, 235, 65, 103, 59, 170, 79, 117, 184, 135, 73, 108, 241, 46, 38, 207, 84, 7, 85, 247, 187, 56, 82, 237, 158, 64, 232, 88, 146]

Looking at the data above, we notice that there are 256 entries in the map of which none are duplicates. In other words, the map contains a single unique entry for all numerals from 0-255. Thus we can conclude that this is very obviously a substitution cipher map, i.e. the key that decides which characters map to which characters in the substitution cipher.

We can now load the contents of the encrypted.bin file and substitute the characters in the file with the characters from the substitution cipher key map. This can be scripted in Python as shown below.

encoded = 'CTGAAATGTTCCGCGAGCCGAACCGATTCACCGCCTAGAAACGTATTGTGCTGGTGTGCGGCGGTTAGAGATATTAGGTAGCGCCGTTACTCTAACATTTCGAATCAACCTTTCAGGGGAGTCACTGCCATCGTAAGTAGAGTACTTAGCATCGATGGCCATGCCTACTAATTACAGGCTGAATGACACTAAACCTTAGTTCACTGACCCGTTTTGTCATGTACTCTTGTGGTATGGGTCTTCAAATTGATCTGATTGGGAAGATAGAAAAACGGCTCTATCCTGGGTCGAGCCTCCCATGAAGCAGTCAAGGGGCCGCGAGGACTTCGATACTTGCCCTGCTCGAGCACATTTTAAAGCTTATTCCACATACTAGACTTACCCCCCGGCGTGTCGTACTGGAAGGTTAAACCTCTTGAGTTGATCTGACAACCTAGACGCGTGCCACGTTGTGTGGGATAGGTCACTCTCATTTCCACGAGGGACCAGAACCTTTGGCAATCCAGTTATTCTGCACTCGTGGCCGCCTCTCCTGGCAGGGGACCGGTAAGTTTGCGTATTCGCCGGGGAGTGGAGACGGATCGTCGTACACTGTTTCGAAAATTTTTGAGGATGGAGAGCAGAGCTATTGGATAAACGCTTGTACAGGTTCAATACTATTAGCAACGTGCCACCGGCACAGCTATCTCTGTTTCGCATGAAAGAGCCGTTAATCACGACGTTTAATCGAAACACATACCGATGGTCTACGAATATTATATCCGATACTAAGTCGGCCGCCGCAGTCCAGACGCCATATCGCTTTGAAGACCCCAAGGCGAACATTAACCGGTACGAGCAACTGCGGAGTGCCCTGCAATAGTCCGTCTGTAAAGGGCCCAGGCTAGGGCAAATAGTCCCTAAAACTAGAGATGGTCAACCGCTATGTGGGGCATTCTCCGTGAGACTCAGCCGTATTACAGTGAGCGTATTCCCAAACTCCCCTTCTGTGTATGACCAGTGTCGCTGCAAATGGACCGAGCAG'
decoder = { 'A': '00', 'C': '01', 'G': '10', 'T': '11' }
decoded = ''.join([decoder[c] for c in encoded])

octets = [int(decoded[i:i+8], 2) for i in range(0, len(decoded), 8)]

with open('encrypted.bin', 'rb') as f:
    print ''.join([chr(octets[ord(c)]) for c in f.read()])

We can now run our script to decode the ciphertext.

And there you have it – the challenge has been solved!

Leave a Reply