{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "## Decoding a File Encoded Using an Unknown Encoding Algorithm/Methodology\n", "\n", "**Author**: \n", "
\n", "Twitter: https://twitter.com/MalwareRE\n", "
\n", "GitHub: https://github.com/MalwareRE\n", "

\n", "**References**:\n", "
\n", "https://twitter.com/cyb3rops/status/1270402099025715200\n", "
\n", "https://twitter.com/MalwareRE/status/1270484644178386944\n", "

\n", "**Notebooks Hosted on Binder:**\n", "
\n", "https://mybinder.org/v2/gh/malwarere/notebooks/master\n", "

\n", "**Summary:**\n", "This notebook walks through the thought process and two approaches used to decode an encoded file shared by Florian Roth (@cyb3rops) in the following tweet: https://twitter.com/cyb3rops/status/1270402099025715200. After decoding the file and sharing the decoding XOR-ADD key (https://twitter.com/MalwareRE/status/1270484644178386944), I was asked by multiple folks to share my approach and thought process that went into decoding the file. I tried to fit my approach in a series of tweet but decided to capture everything in a single interactive notebook instead (be sure to use the Binder link above and in my GitHub repo to launch/run an interactive version of this notebook). I was not able to carve out enough time to perfect the approach, code, contents, etc. shared in this notebook (will hopefully find time to revisit this notebook) so treat everything as raw, imperfect and optimizable (feedback, suggestions and comments are always welcomed and appreciated). With that being said let's get started!\n", "

\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "# we will use this function later in this notebook\n", "import pandas as pd\n", "import matplotlib\n", "\n", "def hex_dump(data):\n", " #Hex Dump\n", " line_num = 0\n", " line_width = 46\n", " for byte_array in [data[i:i+16] for i in range(0, len(data), 16)]: #or use islice\n", " s_hex = \" \".join([f\"{b:02x}\" for b in byte_array]) \n", " s_ascii = \"\".join([chr(b) if 32 <= b <= 127 else \".\" for b in byte_array])\n", " print(f\"{line_num * 16:08x} {s_hex:<{line_width}} {s_ascii}\")\n", " line_num += 1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "First thing first, let's check out the header of the file shared by Florian." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "00000000 a9 a4 6e fe f3 fe fe fe f2 fe fe fe ff ff fe fe ..n.............\n", "00000010 46 fe fe fe fe fe fe fe be fe fe fe fe fe fe fe F...............\n", "00000020 fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe ................\n", "00000030 fe fe fe fe fe fe fe fe fe fe fe fe 1e fe fe fe ................\n", "00000040 e8 df 44 e8 fe 42 f5 29 dd 46 fd aa 29 dd a2 96 ..D..B.).F..)...\n", "00000050 95 83 de 8e 8c 8f 97 8c 9d 89 de 93 9d 88 88 8f ................\n", "00000060 82 de 9c 91 de 8c 81 88 de 95 88 de b2 af a3 de ................\n", "00000070 89 8f 92 91 c8 e9 e9 f4 d2 fe fe fe fe fe fe fe ................\n", "00000080 13 fc 59 e2 57 93 03 b7 57 93 03 b7 57 93 03 b7 ..Y.W...W...W...\n", "00000090 48 db 90 b7 40 93 03 b7 48 db 8e b7 29 93 03 b7 H...@...H...)...\n", "000000a0 48 db 87 b7 61 93 03 b7 7e 51 76 b7 4a 93 03 b7 H...a...~Qv.J...\n", "000000b0 57 93 0c b7 23 93 03 b7 48 db 85 b7 50 93 03 b7 W...#...H...P...\n", "000000c0 48 db 9d b7 50 93 03 b7 48 db 9c b7 50 93 03 b7 H...P...H...P...\n", "000000d0 ac 95 93 96 57 93 03 b7 fe fe fe fe fe fe fe fe ....W...........\n", "000000e0 ae b1 fe fe aa fd f1 fe cf 61 16 a7 fe fe fe fe .........a......\n", "000000f0 fe fe fe fe 1e fe fc dd eb fd f5 fe fe 1c fe fe ................\n", "00000100 fe 90 fe fe fe fe fe fe 2c c6 fe fe fe ee fe fe ........,.......\n", "00000110 fe fe fd fe fe fe fe ee fe ee fe fe fe fc fe fe ................\n", "00000120 f1 fe fe fe fe fe fe fe f1 fe fe fe fe fe fe fe ................\n", "00000130 fe 5e fd fe fe f2 fe fe 9a 87 fd fe fc fe be fd .^..............\n", "00000140 fe fe ee fe fe ee fe fe fe fe ee fe fe ee fe fe ................\n", "00000150 fe fe fe fe ee fe fe fe 8e c7 fd fe ad fe fe fe ................\n", "00000160 52 c9 fd fe 86 fe fe fe fe 8e fd fe 42 fd fe fe R...........B...\n", "00000170 fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe ................\n", "00000180 fe 7e fd fe 76 ea fe fe 1e fd fd fe da fe fe fe .~..v...........\n", "00000190 fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe ................\n", "000001a0 fe fe fe fe fe fe fe fe 56 dc fd fe be fe fe fe ........V.......\n", "000001b0 fe fe fe fe fe fe fe fe fe fe fd fe 56 fd fe fe ............V...\n", "000001c0 fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe ................\n", "000001d0 fe fe fe fe fe fe fe fe c8 82 91 86 82 fe fe fe ................\n", "000001e0 49 1d fe fe fe ee fe fe fe 1c fe fe fe f2 fe fe I...............\n", "000001f0 fe fe fe fe fe fe fe fe fe fe fe fe de fe fe 9e ................\n", "00000200 c8 8c 92 9d 82 9d fe fe 3d c7 fe fe fe fe fd fe ........=.......\n", "00000210 fe c6 fe fe fe 10 fe fe fe fe fe fe fe fe fe fe ................\n", "00000220 fe fe fe fe be fe fe be c8 92 9d 82 9d fe fe fe ................\n", "00000230 ba ca fe fe fe be fd fe fe ec fe fe fe d8 fd fe ................\n", "00000240 fe fe fe fe fe fe fe fe fe fe fe fe be fe fe 3e ...............>\n", "00000250 c8 8c 83 8c 93 fe fe fe 42 fd fe fe fe 8e fd fe ........B.......\n", "00000260 fe fc fe fe fe ce fd fe fe fe fe fe fe fe fe fe ................\n", "00000270 fe fe fe fe be fe fe be c8 8c 91 8a 8f 93 fe fe ................\n", "00000280 90 e6 fe fe fe 7e fd fe fe e4 fe fe fe cc fd fe .....~..........\n", "\n" ] } ], "source": [ "ciphertext = (b'\\xA9\\xA4\\x6E\\xFE\\xF3\\xFE\\xFE\\xFE\\xF2\\xFE\\xFE\\xFE\\xFF\\xFF\\xFE\\xFE'\n", "b'\\x46\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xBE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE'\n", "b'\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE'\n", "b'\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\x1E\\xFE\\xFE\\xFE'\n", "b'\\xE8\\xDF\\x44\\xE8\\xFE\\x42\\xF5\\x29\\xDD\\x46\\xFD\\xAA\\x29\\xDD\\xA2\\x96'\n", "b'\\x95\\x83\\xDE\\x8E\\x8C\\x8F\\x97\\x8C\\x9D\\x89\\xDE\\x93\\x9D\\x88\\x88\\x8F'\n", "b'\\x82\\xDE\\x9C\\x91\\xDE\\x8C\\x81\\x88\\xDE\\x95\\x88\\xDE\\xB2\\xAF\\xA3\\xDE'\n", "b'\\x89\\x8F\\x92\\x91\\xC8\\xE9\\xE9\\xF4\\xD2\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE'\n", "b'\\x13\\xFC\\x59\\xE2\\x57\\x93\\x03\\xB7\\x57\\x93\\x03\\xB7\\x57\\x93\\x03\\xB7'\n", "b'\\x48\\xDB\\x90\\xB7\\x40\\x93\\x03\\xB7\\x48\\xDB\\x8E\\xB7\\x29\\x93\\x03\\xB7'\n", "b'\\x48\\xDB\\x87\\xB7\\x61\\x93\\x03\\xB7\\x7E\\x51\\x76\\xB7\\x4A\\x93\\x03\\xB7'\n", "b'\\x57\\x93\\x0C\\xB7\\x23\\x93\\x03\\xB7\\x48\\xDB\\x85\\xB7\\x50\\x93\\x03\\xB7'\n", "b'\\x48\\xDB\\x9D\\xB7\\x50\\x93\\x03\\xB7\\x48\\xDB\\x9C\\xB7\\x50\\x93\\x03\\xB7'\n", "b'\\xAC\\x95\\x93\\x96\\x57\\x93\\x03\\xB7\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE'\n", "b'\\xAE\\xB1\\xFE\\xFE\\xAA\\xFD\\xF1\\xFE\\xCF\\x61\\x16\\xA7\\xFE\\xFE\\xFE\\xFE'\n", "b'\\xFE\\xFE\\xFE\\xFE\\x1E\\xFE\\xFC\\xDD\\xEB\\xFD\\xF5\\xFE\\xFE\\x1C\\xFE\\xFE'\n", "b'\\xFE\\x90\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\x2C\\xC6\\xFE\\xFE\\xFE\\xEE\\xFE\\xFE'\n", "b'\\xFE\\xFE\\xFD\\xFE\\xFE\\xFE\\xFE\\xEE\\xFE\\xEE\\xFE\\xFE\\xFE\\xFC\\xFE\\xFE'\n", "b'\\xF1\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xF1\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE'\n", "b'\\xFE\\x5E\\xFD\\xFE\\xFE\\xF2\\xFE\\xFE\\x9A\\x87\\xFD\\xFE\\xFC\\xFE\\xBE\\xFD'\n", "b'\\xFE\\xFE\\xEE\\xFE\\xFE\\xEE\\xFE\\xFE\\xFE\\xFE\\xEE\\xFE\\xFE\\xEE\\xFE\\xFE'\n", "b'\\xFE\\xFE\\xFE\\xFE\\xEE\\xFE\\xFE\\xFE\\x8E\\xC7\\xFD\\xFE\\xAD\\xFE\\xFE\\xFE'\n", "b'\\x52\\xC9\\xFD\\xFE\\x86\\xFE\\xFE\\xFE\\xFE\\x8E\\xFD\\xFE\\x42\\xFD\\xFE\\xFE'\n", "b'\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE'\n", "b'\\xFE\\x7E\\xFD\\xFE\\x76\\xEA\\xFE\\xFE\\x1E\\xFD\\xFD\\xFE\\xDA\\xFE\\xFE\\xFE'\n", "b'\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE'\n", "b'\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\x56\\xDC\\xFD\\xFE\\xBE\\xFE\\xFE\\xFE'\n", "b'\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFD\\xFE\\x56\\xFD\\xFE\\xFE'\n", "b'\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE'\n", "b'\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xC8\\x82\\x91\\x86\\x82\\xFE\\xFE\\xFE'\n", "b'\\x49\\x1D\\xFE\\xFE\\xFE\\xEE\\xFE\\xFE\\xFE\\x1C\\xFE\\xFE\\xFE\\xF2\\xFE\\xFE'\n", "b'\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xDE\\xFE\\xFE\\x9E'\n", "b'\\xC8\\x8C\\x92\\x9D\\x82\\x9D\\xFE\\xFE\\x3D\\xC7\\xFE\\xFE\\xFE\\xFE\\xFD\\xFE'\n", "b'\\xFE\\xC6\\xFE\\xFE\\xFE\\x10\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE'\n", "b'\\xFE\\xFE\\xFE\\xFE\\xBE\\xFE\\xFE\\xBE\\xC8\\x92\\x9D\\x82\\x9D\\xFE\\xFE\\xFE'\n", "b'\\xBA\\xCA\\xFE\\xFE\\xFE\\xBE\\xFD\\xFE\\xFE\\xEC\\xFE\\xFE\\xFE\\xD8\\xFD\\xFE'\n", "b'\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xBE\\xFE\\xFE\\x3E'\n", "b'\\xC8\\x8C\\x83\\x8C\\x93\\xFE\\xFE\\xFE\\x42\\xFD\\xFE\\xFE\\xFE\\x8E\\xFD\\xFE'\n", "b'\\xFE\\xFC\\xFE\\xFE\\xFE\\xCE\\xFD\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE'\n", "b'\\xFE\\xFE\\xFE\\xFE\\xBE\\xFE\\xFE\\xBE\\xC8\\x8C\\x91\\x8A\\x8F\\x93\\xFE\\xFE'\n", "b'\\x90\\xE6\\xFE\\xFE\\xFE\\x7E\\xFD\\xFE\\xFE\\xE4\\xFE\\xFE\\xFE\\xCC\\xFD\\xFE')\n", "print()\n", "hex_dump(ciphertext)\n", "print()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Quick eyeballing (or frequency analysis) of the bytes above suggests that the file was possibly XOR encoded using 0xfe as XOR key. Let's XOR decode the encoded bytes above:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "00000000 57 5a 90 00 0d 00 00 00 0c 00 00 00 01 01 00 00 WZ..............\n", "00000010 b8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 ........@.......\n", "00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................\n", "00000030 00 00 00 00 00 00 00 00 00 00 00 00 e0 00 00 00 ................\n", "00000040 16 21 ba 16 00 bc 0b d7 23 b8 03 54 d7 23 5c 68 .!......#..T.#\\h\n", "00000050 6b 7d 20 70 72 71 69 72 63 77 20 6d 63 76 76 71 k} prqircw mcvvq\n", "00000060 7c 20 62 6f 20 72 7f 76 20 6b 76 20 4c 51 5d 20 | bo rv kv LQ] \n", "00000070 77 71 6c 6f 36 17 17 0a 2c 00 00 00 00 00 00 00 wqlo6...,.......\n", "00000080 ed 02 a7 1c a9 6d fd 49 a9 6d fd 49 a9 6d fd 49 .....m.I.m.I.m.I\n", "00000090 b6 25 6e 49 be 6d fd 49 b6 25 70 49 d7 6d fd 49 .%nI.m.I.%pI.m.I\n", "000000a0 b6 25 79 49 9f 6d fd 49 80 af 88 49 b4 6d fd 49 .%yI.m.I...I.m.I\n", "000000b0 a9 6d f2 49 dd 6d fd 49 b6 25 7b 49 ae 6d fd 49 .m.I.m.I.%{I.m.I\n", "000000c0 b6 25 63 49 ae 6d fd 49 b6 25 62 49 ae 6d fd 49 .%cI.m.I.%bI.m.I\n", "000000d0 52 6b 6d 68 a9 6d fd 49 00 00 00 00 00 00 00 00 Rkmh.m.I........\n", "000000e0 50 4f 00 00 54 03 0f 00 31 9f e8 59 00 00 00 00 PO..T...1..Y....\n", "000000f0 00 00 00 00 e0 00 02 23 15 03 0b 00 00 e2 00 00 .......#........\n", "00000100 00 6e 00 00 00 00 00 00 d2 38 00 00 00 10 00 00 .n.......8......\n", "00000110 00 00 03 00 00 00 00 10 00 10 00 00 00 02 00 00 ................\n", "00000120 0f 00 00 00 00 00 00 00 0f 00 00 00 00 00 00 00 ................\n", "00000130 00 a0 03 00 00 0c 00 00 64 79 03 00 02 00 40 03 ........dy....@.\n", "00000140 00 00 10 00 00 10 00 00 00 00 10 00 00 10 00 00 ................\n", "00000150 00 00 00 00 10 00 00 00 70 39 03 00 53 00 00 00 ........p9..S...\n", "00000160 ac 37 03 00 78 00 00 00 00 70 03 00 bc 03 00 00 .7..x....p......\n", "00000170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................\n", "00000180 00 80 03 00 88 14 00 00 e0 03 03 00 24 00 00 00 ............$...\n", "00000190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................\n", "000001a0 00 00 00 00 00 00 00 00 a8 22 03 00 40 00 00 00 .........\"..@...\n", "000001b0 00 00 00 00 00 00 00 00 00 00 03 00 a8 03 00 00 ................\n", "000001c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................\n", "000001d0 00 00 00 00 00 00 00 00 36 7c 6f 78 7c 00 00 00 ........6|ox|...\n", "000001e0 b7 e3 00 00 00 10 00 00 00 e2 00 00 00 0c 00 00 ................\n", "000001f0 00 00 00 00 00 00 00 00 00 00 00 00 20 00 00 60 ............ ..`\n", "00000200 36 72 6c 63 7c 63 00 00 c3 39 00 00 00 00 03 00 6rlc|c...9......\n", "00000210 00 38 00 00 00 ee 00 00 00 00 00 00 00 00 00 00 .8..............\n", "00000220 00 00 00 00 40 00 00 40 36 6c 63 7c 63 00 00 00 ....@..@6lc|c...\n", "00000230 44 34 00 00 00 40 03 00 00 12 00 00 00 26 03 00 D4...@.......&..\n", "00000240 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 c0 ............@...\n", "00000250 36 72 7d 72 6d 00 00 00 bc 03 00 00 00 70 03 00 6r}rm........p..\n", "00000260 00 02 00 00 00 30 03 00 00 00 00 00 00 00 00 00 .....0..........\n", "00000270 00 00 00 00 40 00 00 40 36 72 6f 74 71 6d 00 00 ....@..@6rotqm..\n", "00000280 6e 18 00 00 00 80 03 00 00 1a 00 00 00 32 03 00 n............2..\n", "\n" ] } ], "source": [ "xor_decoded = list()\n", "for c in ciphertext:\n", " xor_decoded.append(c ^ 0xFE)\n", "\n", "print()\n", "hex_dump(xor_decoded)\n", "print()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you have ever dealt with PE files in hexadecimal/binary format you would be able to recognize that the bytes above resemble a PE header structure (albeit an obfuscated one). Let's walk the structure to see if we can glean any useful information that can help us with decoding the file (the structure of the encoded PE header and certain visible bytes above suggest that we are not dealing with a Pascal, Delphi or an uncommon file type hence we can make certain assumptions about the presumed/potential location of certain bytes in the PE header, more on that below). I have already highlighted some of the interesting fields that can assist with creating a character mapping table that maps the highlighted bytes to their potential plaintext values. If we can map a decent number of bytes to their plaintext values, we might be able to learn something about the encoding methodology used to encode the file." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![https://github.com/MalwareRE/notebooks/raw/master/img/PE.png](https://github.com/MalwareRE/notebooks/raw/master/img/PE.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Legend & Highlighted Offsets:**\n", "- 0x00-0x01: 0x57 0x5a (IMAGE_DOS_HEADER.e_magic) maps to plaintext bytes 0x4d 0x5a\n", "- 0x02-0x03: 0x90 0x00 (IMAGE_DOS_HEADER.e_cblp) would usually map to 0x90 0x00 (could also be for example 0x50 0x00)\n", "- 0x04-0x05: 0xd0 0x00 (IMAGE_DOS_HEADER.e_cp) would usually map to 0x03 0x00\n", "- 0x08-0x09: 0x0c 0x00 (IMAGE_DOS_HEADER.e_cparhdr) would usually map to 0x04 0x00\n", "- 0x10-0x11: 0xb8 0x00 (IMAGE_DOS_HEADER.e_sp) would usually map to 0xb8 0x00\n", "- 0x18-0x19: 0x40 0x00 (IMAGE_DOS_HEADER.e_lfarlc) would usually map to 0x40 0x00\n", "- 0x3c-0x3f: 0xe0 0x00 0x00 0x00 (IMAGE_DOS_HEADER.e_lfanew) contains the file offset of NT Headers (aka PE signature), as shown above, offset 0xe0 does appear to contain the PE signature hence we can assume that 0xe0 maps to 0xe0\n", "- 0x4e-0x74: 0x5c .... .... 0x36 (part of DOS Stub) would usually map to \"This program cannot be run in DOS mode.\" (there are also a few 16-bit x86 real-mode machine code bytes before/after this offsets that we can safely use)\n", "- 0xd0-0xde: 0x52 0x6b 0x6d 0x68 (part of the Rich header) would usually map to 0x52 0x69 0x63 0x68 (\"Rich\")\n", "- 0xe0-0xe1: 0x50 0x4f 0x00 0x00 (IMAGE_NT_HEADERS.Signature) would usually map to 0x50 0x45 0x00 0x00 (\"PE\\0\\0\")\n", "- 0xe6-0xe7: 0xf0 0x00 (IMAGE_FILE_HEADER.NumberOfSections) contains\n", "- 0xf4-0xf5: 0xe0 0x00 (IMAGE_FILE_HEADER.SizeOfOptionalHeader) would usually map to 0xe0 0x00\n", "- 0xf8-0xf9: 0x15 0x03 (IMAGE_OPTIONAL_HEADER.Magic) would usually map to either 0xb1 0x01 (PE32) or 0xb1 0x02 (PE64), either way we can map 0x15 to 0xb1\n", "- 0x1d8-0x1dc: 0x36 0x7c 0x6f 0x78 0x7c would usually map to 0x2e 0x74 0x65 0x78 0x74 (\".text\"), note the presence of 0x7c at 2nd and 5th positions of the encoded bytes which would match the repeating t's in .text\n", "- 0x200-0x205: 0x36 0x72 0x6C 0x63 0x7C 0x63 would usually map to 0x2e 0x72 0x64 0x61 0x74 0x61 (\".rdata\"), note the presence of 0x63 at 4th and 6th positions of the encoded bytes which would match the repeating a's in .rdata\n", "- 0x228-0x22c: 0x36 0x6c 0x63 0x7c 0x63 would usually map to 0x2e 0x64 0x61 0x74 0x61 (\".data\")\n", "- 0x250-0x254: 0x36 0x72 0x7d 0x72 0x6d would usually map to 0x2e 0x72 0x73 0x72 0x63 (\".rsrc\"), we already know from above that the encoded byte 0x72 maps to 'r', there are two 0x72 at 2nd and 4th positions hence \".rsrc\" should be a safe guess\n", "- 0x278-0x27d: 0x36 0x72 0x6f 0x74 0x71 0x6d would usually map to 0x2e 0x72 0x65 0x6C 0x6f 0x63 (\".reloc\"), we have already mapped 'r', 'e' and 'c' above so \".reloc\" should be a safe guess\n", "- 0xf4-0xf5: 0xe0 0x00 (IMAGE_FILE_HEADER.NumberOfSections) should map to 0x05 0x00 since we have 5 decoded 5 section names above\n", "\n", "There are other fields in the PE header that we might be able to map with lower confidence if needed but for now let's use the character mappings we have discovered above to create a Pandas DataFrame named `df_all_known_mappings` (where the Ciphertext column contains bytes from the encoded file shared by Florian, XOR_Decoded column contains the XOR 0xFE decoded bytes used above and Plaintext column contains the plaintext bytes we have discovered above):\n" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Ciphertext XOR_Decoded Plaintext
00xfe0x00x0
10xff0x10xff
20xf40xa0xa
30xf20xc0x4
40xf30xd0x3
50xf10xf0x5
60xeb0x150xb
70xe90x170xd
80xde0x200x20
90xdd0x230x21
100xd60x280x28
110xd20x2c0x24
120xc80x360x2e
130xbe0x400x40
140xbc0x420x42
150xb20x4c0x44
160xb10x4f0x45
170xb10x4f0x45
180xae0x500x50
190xaf0x510x4f
200xac0x520x52
210xaa0x540x4c
220xa90x570x4d
230xa40x5a0x5a
240xa20x5c0x54
250xa30x5d0x53
260x9e0x600x60
270x9c0x620x62
280x9d0x630x61
290x960x680x68
300x970x690x67
310x950x6b0x69
320x920x6c0x64
330x930x6d0x63
340x910x6f0x65
350x8e0x700x70
360x8f0x710x6f
370x8c0x720x72
380x8a0x740x6c
390x880x760x6e
400x890x770x6d
410x860x780x78
420x820x7c0x74
430x830x7d0x73
440x810x7f0x75
450x6e0x900x90
460x3e0xc00xc0
470x290xd70xcd
480x1e0xe00xe0
" ], "text/plain": [ "" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d = {'Ciphertext': [0xFE, 0xFF, 0xEB, 0xE9, 0xDE, 0xDD, 0xD6, 0xC8, 0xBE, 0xBC, 0xB1, 0xAE, 0xAF, 0xAC, 0xAA, 0xA9, 0x9E, \n", " 0x9C, 0x9D, 0x96, 0x97, 0x8E, 0x8F, 0x8C, 0x8A, 0x88, 0x89, 0x86, 0x6E, 0x93, 0xF4, 0xF2, 0xF3, 0xF1, \n", " 0xD2, 0xB2, 0xB1, 0xA4, 0xA2, 0xA3, 0x95, 0x92, 0x91, 0x82, 0x83, 0x81, 0x3E, 0x29, 0x1E],\n", " 'XOR_Decoded': [0x00, 0x01, 0x15, 0x17, 0x20, 0x23, 0x28, 0x36, 0x40, 0x42, 0x4F, 0x50, 0x51, 0x52, 0x54, 0x57, 0x60, \n", " 0x62, 0x63, 0x68, 0x69, 0x70, 0x71, 0x72, 0x74, 0x76, 0x77, 0x78, 0x90, 0x6D, 0x0A, 0x0C, 0x0D, 0x0F, \n", " 0x2C, 0x4C, 0x4F, 0x5A, 0x5C, 0x5D, 0x6B, 0x6C, 0x6F, 0x7C, 0x7D, 0x7F, 0xC0, 0xD7, 0xE0], \n", " 'Plaintext': [0x00, 0xFF, 0x0B, 0x0D, 0x20, 0x21, 0x28, 0x2E, 0x40, 0x42, 0x45, 0x50, 0x4F, 0x52, 0x4C, 0x4D, 0x60, \n", " 0x62, 0x61, 0x68, 0x67, 0x70, 0x6F, 0x72, 0x6C, 0x6E, 0x6D, 0x78, 0x90, 0x63, 0x0A, 0x4, 0x3, 0x5, \n", " 0x24, 0x44, 0x45, 0x5A, 0x54, 0x53, 0x69, 0x64, 0x65, 0x74, 0x73, 0x75, 0xC0, 0xCD, 0xE0]}\n", "\n", "df_all_known_mappings = pd.DataFrame(data=d).sort_values(by=['XOR_Decoded']).reset_index(drop=True)\n", "df_all_known_mappings.style.format({'Ciphertext':\"{:#x}\", 'XOR_Decoded':\"{:#x}\", 'Plaintext':\"{:#x}\"})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Closer inspection of all XOR_Decoded-Plaintext pairs above revealed that the distance between the numbers in each pair ranges between 0 and 10. To get a better idea of the distance/difference/sub values, we can subtract each XOR_Decoded value from its corresponding Plaintext value and store the resulting value under a new column named Sub:\n" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
XOR_Decoded Plaintext Sub
00x00x00x0
10x10xff0xfe
20xa0xa0x0
30xc0x40xf8
40xd0x30xf6
50xf0x50xf6
60x150xb0xf6
70x170xd0xf6
80x200x200x0
90x230x210xfe
100x280x280x0
110x2c0x240xf8
120x360x2e0xf8
130x400x400x0
140x420x420x0
150x4c0x440xf8
160x4f0x450xf6
170x4f0x450xf6
180x500x500x0
190x510x4f0xfe
200x520x520x0
210x540x4c0xf8
220x570x4d0xf6
230x5a0x5a0x0
240x5c0x540xf8
250x5d0x530xf6
260x600x600x0
270x620x620x0
280x630x610xfe
290x680x680x0
300x690x670xfe
310x6b0x690xfe
320x6c0x640xf8
330x6d0x630xf6
340x6f0x650xf6
350x700x700x0
360x710x6f0xfe
370x720x720x0
380x740x6c0xf8
390x760x6e0xf8
400x770x6d0xf6
410x780x780x0
420x7c0x740xf8
430x7d0x730xf6
440x7f0x750xf6
450x900x900x0
460xc00xc00x0
470xd70xcd0xf6
480xe00xe00x0
" ], "text/plain": [ "" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df_all_known_mappings['Sub'] = (df_all_known_mappings['Plaintext'] - df_all_known_mappings['XOR_Decoded'] & 0xFF) # using 0xFF as mask, we can also use np.ubyte (or a list of ctypes c_ubyte's) to store bytes/chars as unsigned char\n", "df_all_known_mappings[['XOR_Decoded', 'Plaintext', 'Sub']].style.format({'XOR_Decoded':\"{:#x}\", 'Plaintext':\"{:#x}\", 'Sub':\"{:#x}\"})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A closer inspection of the values in the Sub column above revealed a repeating pattern consisting of 0xfe, 0xf8, 0xf6, and 0. Another notable observation is the relationship between the least-significant octet (LSO) of the values in the XOR_Decoded column and their corresponding values in the Sub column. To make the pattern in the Sub column more noticeable/visible, let's add a colormap to the dataframe (if you the colormap is not visible e.g. if you are viewing this on Github, try downloading a copy of this notebook or use the Binder link in the header of this notebook to launch an interactive version of this notebook):" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
XOR_Decoded Plaintext Sub
00x00x00x0
10x10xff0xfe
20xa0xa0x0
30xc0x40xf8
40xd0x30xf6
50xf0x50xf6
60x150xb0xf6
70x170xd0xf6
80x200x200x0
90x230x210xfe
100x280x280x0
110x2c0x240xf8
120x360x2e0xf8
130x400x400x0
140x420x420x0
150x4c0x440xf8
160x4f0x450xf6
170x4f0x450xf6
180x500x500x0
190x510x4f0xfe
200x520x520x0
210x540x4c0xf8
220x570x4d0xf6
230x5a0x5a0x0
240x5c0x540xf8
250x5d0x530xf6
260x600x600x0
270x620x620x0
280x630x610xfe
290x680x680x0
300x690x670xfe
310x6b0x690xfe
320x6c0x640xf8
330x6d0x630xf6
340x6f0x650xf6
350x700x700x0
360x710x6f0xfe
370x720x720x0
380x740x6c0xf8
390x760x6e0xf8
400x770x6d0xf6
410x780x780x0
420x7c0x740xf8
430x7d0x730xf6
440x7f0x750xf6
450x900x900x0
460xc00xc00x0
470xd70xcd0xf6
480xe00xe00x0
" ], "text/plain": [ "" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df_all_known_mappings[['XOR_Decoded', 'Plaintext', 'Sub']].style.format({'Ciphertext':\"{:#x}\", 'XOR_Decoded':\"{:#x}\", 'Plaintext':\"{:#x}\", 'Sub':\"{:#x}\"}).background_gradient(cmap='plasma')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As depicted above, there is a direct relationship between the least-significant octet (LSO) of the values in the XOR_Decoded column and their corresponding values in the Sub column. For example, if the LSO of the XOR_Decoded value is 4 (e.g. in 0x04, 0x14, 0x24, etc.) then by adding 0xF8 (or its signed char equivalent -0x8) to the XOR_Decoded value we can obtain its plaintext value!\n", "\n", "**Formula:**\n", "
\n", "Plaintext = XOR_Decoded + Sub\n", "

\n", "**Example:**\n", "
\n", "XOR_Decoded: 0x54\n", "
\n", "LSO: 4  --> Sub: 0xf8\n", "
\n", "Plaintext = 0x54 + 0xf8 = 0x4c\n", "

\n", "The observed relationship between the LSO and Sub values are captured in the table below (note the repeating and symmetrical pattern between 0x0-0x7 and then again 0x8-0xf):\n", "\n", "\n", "| LS Octet \t| Sub Value \t|\n", "|:--------:\t|:---------:\t|\n", "| 0 \t| 0 \t|\n", "| 1 \t| 0xfe \t|\n", "| 2 \t| 0 \t|\n", "| 3 \t| 0xfe \t|\n", "| 4 \t| 0xf8 \t|\n", "| 5 \t| 0xf6 \t|\n", "| 6 \t| 0xf8 \t|\n", "| 7 \t| 0xf6 \t|\n", "| -------- \t| --------- \t|\n", "| 8 \t| 0 \t|\n", "| 9 \t| 0xfe \t|\n", "| 0xa \t| 0 \t|\n", "| 0xb \t| 0xfe \t|\n", "| 0xc \t| 0xf8 \t|\n", "| 0xd \t| 0xf6 \t|\n", "| 0xe \t| Unknown \t|\n", "| 0xf \t| 0xf6 \t|\n", "\n", "\n", "Since our known character mapping table does not contain an XOR_Decoded value that ends with the octet 0xe (i.e. LSO set to 0xe), the Sub value for 0xe is intentionally set to Unknown in the table above; however, using symmetry to our advantage, we can see that the Sub value of 0xe is most likely identical to that of 6 (i.e. 0xf8 from the table above).\n", "\n", "At this point we can use the LSO-Sum mapping in the table above to generate a new dataframe that maps ***all*** possible XOR_Decoded bytes (i.e. 0x00-0xFF) to their corresponding Sum values and better yet, to their corresponding plaintext values!" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
XOR_Decoded Plaintext Sub
00x00x00x0
10x10xff0xfe
20x20x20x0
30x30x10xfe
40x40xfc0xf8
50x50xfb0xf6
60x60xfe0xf8
70x70xfd0xf6
80x80x80x0
90x90x70xfe
100xa0xa0x0
110xb0x90xfe
120xc0x40xf8
130xd0x30xf6
140xe0x60xf8
150xf0x50xf6
160x100x100x0
170x110xf0xfe
180x120x120x0
190x130x110xfe
200x140xc0xf8
210x150xb0xf6
220x160xe0xf8
230x170xd0xf6
240x180x180x0
250x190x170xfe
260x1a0x1a0x0
270x1b0x190xfe
280x1c0x140xf8
290x1d0x130xf6
300x1e0x160xf8
310x1f0x150xf6
320x200x200x0
330x210x1f0xfe
340x220x220x0
350x230x210xfe
360x240x1c0xf8
370x250x1b0xf6
380x260x1e0xf8
390x270x1d0xf6
400x280x280x0
410x290x270xfe
420x2a0x2a0x0
430x2b0x290xfe
440x2c0x240xf8
450x2d0x230xf6
460x2e0x260xf8
470x2f0x250xf6
480x300x300x0
490x310x2f0xfe
500x320x320x0
510x330x310xfe
520x340x2c0xf8
530x350x2b0xf6
540x360x2e0xf8
550x370x2d0xf6
560x380x380x0
570x390x370xfe
580x3a0x3a0x0
590x3b0x390xfe
600x3c0x340xf8
610x3d0x330xf6
620x3e0x360xf8
630x3f0x350xf6
640x400x400x0
650x410x3f0xfe
660x420x420x0
670x430x410xfe
680x440x3c0xf8
690x450x3b0xf6
700x460x3e0xf8
710x470x3d0xf6
720x480x480x0
730x490x470xfe
740x4a0x4a0x0
750x4b0x490xfe
760x4c0x440xf8
770x4d0x430xf6
780x4e0x460xf8
790x4f0x450xf6
800x500x500x0
810x510x4f0xfe
820x520x520x0
830x530x510xfe
840x540x4c0xf8
850x550x4b0xf6
860x560x4e0xf8
870x570x4d0xf6
880x580x580x0
890x590x570xfe
900x5a0x5a0x0
910x5b0x590xfe
920x5c0x540xf8
930x5d0x530xf6
940x5e0x560xf8
950x5f0x550xf6
960x600x600x0
970x610x5f0xfe
980x620x620x0
990x630x610xfe
1000x640x5c0xf8
1010x650x5b0xf6
1020x660x5e0xf8
1030x670x5d0xf6
1040x680x680x0
1050x690x670xfe
1060x6a0x6a0x0
1070x6b0x690xfe
1080x6c0x640xf8
1090x6d0x630xf6
1100x6e0x660xf8
1110x6f0x650xf6
1120x700x700x0
1130x710x6f0xfe
1140x720x720x0
1150x730x710xfe
1160x740x6c0xf8
1170x750x6b0xf6
1180x760x6e0xf8
1190x770x6d0xf6
1200x780x780x0
1210x790x770xfe
1220x7a0x7a0x0
1230x7b0x790xfe
1240x7c0x740xf8
1250x7d0x730xf6
1260x7e0x760xf8
1270x7f0x750xf6
1280x800x800x0
1290x810x7f0xfe
1300x820x820x0
1310x830x810xfe
1320x840x7c0xf8
1330x850x7b0xf6
1340x860x7e0xf8
1350x870x7d0xf6
1360x880x880x0
1370x890x870xfe
1380x8a0x8a0x0
1390x8b0x890xfe
1400x8c0x840xf8
1410x8d0x830xf6
1420x8e0x860xf8
1430x8f0x850xf6
1440x900x900x0
1450x910x8f0xfe
1460x920x920x0
1470x930x910xfe
1480x940x8c0xf8
1490x950x8b0xf6
1500x960x8e0xf8
1510x970x8d0xf6
1520x980x980x0
1530x990x970xfe
1540x9a0x9a0x0
1550x9b0x990xfe
1560x9c0x940xf8
1570x9d0x930xf6
1580x9e0x960xf8
1590x9f0x950xf6
1600xa00xa00x0
1610xa10x9f0xfe
1620xa20xa20x0
1630xa30xa10xfe
1640xa40x9c0xf8
1650xa50x9b0xf6
1660xa60x9e0xf8
1670xa70x9d0xf6
1680xa80xa80x0
1690xa90xa70xfe
1700xaa0xaa0x0
1710xab0xa90xfe
1720xac0xa40xf8
1730xad0xa30xf6
1740xae0xa60xf8
1750xaf0xa50xf6
1760xb00xb00x0
1770xb10xaf0xfe
1780xb20xb20x0
1790xb30xb10xfe
1800xb40xac0xf8
1810xb50xab0xf6
1820xb60xae0xf8
1830xb70xad0xf6
1840xb80xb80x0
1850xb90xb70xfe
1860xba0xba0x0
1870xbb0xb90xfe
1880xbc0xb40xf8
1890xbd0xb30xf6
1900xbe0xb60xf8
1910xbf0xb50xf6
1920xc00xc00x0
1930xc10xbf0xfe
1940xc20xc20x0
1950xc30xc10xfe
1960xc40xbc0xf8
1970xc50xbb0xf6
1980xc60xbe0xf8
1990xc70xbd0xf6
2000xc80xc80x0
2010xc90xc70xfe
2020xca0xca0x0
2030xcb0xc90xfe
2040xcc0xc40xf8
2050xcd0xc30xf6
2060xce0xc60xf8
2070xcf0xc50xf6
2080xd00xd00x0
2090xd10xcf0xfe
2100xd20xd20x0
2110xd30xd10xfe
2120xd40xcc0xf8
2130xd50xcb0xf6
2140xd60xce0xf8
2150xd70xcd0xf6
2160xd80xd80x0
2170xd90xd70xfe
2180xda0xda0x0
2190xdb0xd90xfe
2200xdc0xd40xf8
2210xdd0xd30xf6
2220xde0xd60xf8
2230xdf0xd50xf6
2240xe00xe00x0
2250xe10xdf0xfe
2260xe20xe20x0
2270xe30xe10xfe
2280xe40xdc0xf8
2290xe50xdb0xf6
2300xe60xde0xf8
2310xe70xdd0xf6
2320xe80xe80x0
2330xe90xe70xfe
2340xea0xea0x0
2350xeb0xe90xfe
2360xec0xe40xf8
2370xed0xe30xf6
2380xee0xe60xf8
2390xef0xe50xf6
2400xf00xf00x0
2410xf10xef0xfe
2420xf20xf20x0
2430xf30xf10xfe
2440xf40xec0xf8
2450xf50xeb0xf6
2460xf60xee0xf8
2470xf70xed0xf6
2480xf80xf80x0
2490xf90xf70xfe
2500xfa0xfa0x0
2510xfb0xf90xfe
2520xfc0xf40xf8
2530xfd0xf30xf6
2540xfe0xf60xf8
2550xff0xf50xf6
" ], "text/plain": [ "" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "lso_sub_mapping = {\n", " 0: 0,\n", " 1: 0xfe,\n", " 2: 0,\n", " 3: 0xfe,\n", " 4: 0xf8,\n", " 5: 0xf6,\n", " 6: 0xf8,\n", " 7: 0xf6,\n", "\n", " 8: 0,\n", " 9: 0xfe,\n", " 0xa: 0,\n", " 0xb: 0xfe,\n", " 0xc: 0xf8,\n", " 0xd: 0xf6,\n", " 0xe: 0xf8,\n", " 0xf: 0xf6\n", "}\n", "\n", "sub_bytes = list()\n", "plaintext_bytes = list()\n", "\n", "for xor_decoded_byte in range(0, 256):\n", " sub_byte = lso_sub_mapping[xor_decoded_byte & 0xf]\n", " sub_bytes.append(sub_byte)\n", " plaintext_byte = (xor_decoded_byte + sub_byte ) & 0xFF # AND with 0xFF to discard carry out\n", " plaintext_bytes.append(plaintext_byte)\n", "\n", "d = {'XOR_Decoded': range(0, 256), 'Plaintext':plaintext_bytes, 'Sub': sub_bytes}\n", "df_final = pd.DataFrame.from_dict(data=d,dtype='int').sort_values(by=['XOR_Decoded']).reset_index(drop=True)\n", "\n", "df_final.style.format({'XOR_Decoded':\"{:#x}\", 'Plaintext':\"{:#x}\", 'Sub':\"{:#x}\"}).background_gradient(cmap='plasma')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As depicted above, the repeating Sub pattern is now easier to spot. Now let's bring back the Ciphertext column to view the full mapping between all Ciphertext, XOR_Decoded and Plaintext values!" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Ciphertext XOR_Decoded Plaintext Sub
00x00xfe0xf60xf8
10x10xff0xf50xf6
20x20xfc0xf40xf8
30x30xfd0xf30xf6
40x40xfa0xfa0x0
50x50xfb0xf90xfe
60x60xf80xf80x0
70x70xf90xf70xfe
80x80xf60xee0xf8
90x90xf70xed0xf6
100xa0xf40xec0xf8
110xb0xf50xeb0xf6
120xc0xf20xf20x0
130xd0xf30xf10xfe
140xe0xf00xf00x0
150xf0xf10xef0xfe
160x100xee0xe60xf8
170x110xef0xe50xf6
180x120xec0xe40xf8
190x130xed0xe30xf6
200x140xea0xea0x0
210x150xeb0xe90xfe
220x160xe80xe80x0
230x170xe90xe70xfe
240x180xe60xde0xf8
250x190xe70xdd0xf6
260x1a0xe40xdc0xf8
270x1b0xe50xdb0xf6
280x1c0xe20xe20x0
290x1d0xe30xe10xfe
300x1e0xe00xe00x0
310x1f0xe10xdf0xfe
320x200xde0xd60xf8
330x210xdf0xd50xf6
340x220xdc0xd40xf8
350x230xdd0xd30xf6
360x240xda0xda0x0
370x250xdb0xd90xfe
380x260xd80xd80x0
390x270xd90xd70xfe
400x280xd60xce0xf8
410x290xd70xcd0xf6
420x2a0xd40xcc0xf8
430x2b0xd50xcb0xf6
440x2c0xd20xd20x0
450x2d0xd30xd10xfe
460x2e0xd00xd00x0
470x2f0xd10xcf0xfe
480x300xce0xc60xf8
490x310xcf0xc50xf6
500x320xcc0xc40xf8
510x330xcd0xc30xf6
520x340xca0xca0x0
530x350xcb0xc90xfe
540x360xc80xc80x0
550x370xc90xc70xfe
560x380xc60xbe0xf8
570x390xc70xbd0xf6
580x3a0xc40xbc0xf8
590x3b0xc50xbb0xf6
600x3c0xc20xc20x0
610x3d0xc30xc10xfe
620x3e0xc00xc00x0
630x3f0xc10xbf0xfe
640x400xbe0xb60xf8
650x410xbf0xb50xf6
660x420xbc0xb40xf8
670x430xbd0xb30xf6
680x440xba0xba0x0
690x450xbb0xb90xfe
700x460xb80xb80x0
710x470xb90xb70xfe
720x480xb60xae0xf8
730x490xb70xad0xf6
740x4a0xb40xac0xf8
750x4b0xb50xab0xf6
760x4c0xb20xb20x0
770x4d0xb30xb10xfe
780x4e0xb00xb00x0
790x4f0xb10xaf0xfe
800x500xae0xa60xf8
810x510xaf0xa50xf6
820x520xac0xa40xf8
830x530xad0xa30xf6
840x540xaa0xaa0x0
850x550xab0xa90xfe
860x560xa80xa80x0
870x570xa90xa70xfe
880x580xa60x9e0xf8
890x590xa70x9d0xf6
900x5a0xa40x9c0xf8
910x5b0xa50x9b0xf6
920x5c0xa20xa20x0
930x5d0xa30xa10xfe
940x5e0xa00xa00x0
950x5f0xa10x9f0xfe
960x600x9e0x960xf8
970x610x9f0x950xf6
980x620x9c0x940xf8
990x630x9d0x930xf6
1000x640x9a0x9a0x0
1010x650x9b0x990xfe
1020x660x980x980x0
1030x670x990x970xfe
1040x680x960x8e0xf8
1050x690x970x8d0xf6
1060x6a0x940x8c0xf8
1070x6b0x950x8b0xf6
1080x6c0x920x920x0
1090x6d0x930x910xfe
1100x6e0x900x900x0
1110x6f0x910x8f0xfe
1120x700x8e0x860xf8
1130x710x8f0x850xf6
1140x720x8c0x840xf8
1150x730x8d0x830xf6
1160x740x8a0x8a0x0
1170x750x8b0x890xfe
1180x760x880x880x0
1190x770x890x870xfe
1200x780x860x7e0xf8
1210x790x870x7d0xf6
1220x7a0x840x7c0xf8
1230x7b0x850x7b0xf6
1240x7c0x820x820x0
1250x7d0x830x810xfe
1260x7e0x800x800x0
1270x7f0x810x7f0xfe
1280x800x7e0x760xf8
1290x810x7f0x750xf6
1300x820x7c0x740xf8
1310x830x7d0x730xf6
1320x840x7a0x7a0x0
1330x850x7b0x790xfe
1340x860x780x780x0
1350x870x790x770xfe
1360x880x760x6e0xf8
1370x890x770x6d0xf6
1380x8a0x740x6c0xf8
1390x8b0x750x6b0xf6
1400x8c0x720x720x0
1410x8d0x730x710xfe
1420x8e0x700x700x0
1430x8f0x710x6f0xfe
1440x900x6e0x660xf8
1450x910x6f0x650xf6
1460x920x6c0x640xf8
1470x930x6d0x630xf6
1480x940x6a0x6a0x0
1490x950x6b0x690xfe
1500x960x680x680x0
1510x970x690x670xfe
1520x980x660x5e0xf8
1530x990x670x5d0xf6
1540x9a0x640x5c0xf8
1550x9b0x650x5b0xf6
1560x9c0x620x620x0
1570x9d0x630x610xfe
1580x9e0x600x600x0
1590x9f0x610x5f0xfe
1600xa00x5e0x560xf8
1610xa10x5f0x550xf6
1620xa20x5c0x540xf8
1630xa30x5d0x530xf6
1640xa40x5a0x5a0x0
1650xa50x5b0x590xfe
1660xa60x580x580x0
1670xa70x590x570xfe
1680xa80x560x4e0xf8
1690xa90x570x4d0xf6
1700xaa0x540x4c0xf8
1710xab0x550x4b0xf6
1720xac0x520x520x0
1730xad0x530x510xfe
1740xae0x500x500x0
1750xaf0x510x4f0xfe
1760xb00x4e0x460xf8
1770xb10x4f0x450xf6
1780xb20x4c0x440xf8
1790xb30x4d0x430xf6
1800xb40x4a0x4a0x0
1810xb50x4b0x490xfe
1820xb60x480x480x0
1830xb70x490x470xfe
1840xb80x460x3e0xf8
1850xb90x470x3d0xf6
1860xba0x440x3c0xf8
1870xbb0x450x3b0xf6
1880xbc0x420x420x0
1890xbd0x430x410xfe
1900xbe0x400x400x0
1910xbf0x410x3f0xfe
1920xc00x3e0x360xf8
1930xc10x3f0x350xf6
1940xc20x3c0x340xf8
1950xc30x3d0x330xf6
1960xc40x3a0x3a0x0
1970xc50x3b0x390xfe
1980xc60x380x380x0
1990xc70x390x370xfe
2000xc80x360x2e0xf8
2010xc90x370x2d0xf6
2020xca0x340x2c0xf8
2030xcb0x350x2b0xf6
2040xcc0x320x320x0
2050xcd0x330x310xfe
2060xce0x300x300x0
2070xcf0x310x2f0xfe
2080xd00x2e0x260xf8
2090xd10x2f0x250xf6
2100xd20x2c0x240xf8
2110xd30x2d0x230xf6
2120xd40x2a0x2a0x0
2130xd50x2b0x290xfe
2140xd60x280x280x0
2150xd70x290x270xfe
2160xd80x260x1e0xf8
2170xd90x270x1d0xf6
2180xda0x240x1c0xf8
2190xdb0x250x1b0xf6
2200xdc0x220x220x0
2210xdd0x230x210xfe
2220xde0x200x200x0
2230xdf0x210x1f0xfe
2240xe00x1e0x160xf8
2250xe10x1f0x150xf6
2260xe20x1c0x140xf8
2270xe30x1d0x130xf6
2280xe40x1a0x1a0x0
2290xe50x1b0x190xfe
2300xe60x180x180x0
2310xe70x190x170xfe
2320xe80x160xe0xf8
2330xe90x170xd0xf6
2340xea0x140xc0xf8
2350xeb0x150xb0xf6
2360xec0x120x120x0
2370xed0x130x110xfe
2380xee0x100x100x0
2390xef0x110xf0xfe
2400xf00xe0x60xf8
2410xf10xf0x50xf6
2420xf20xc0x40xf8
2430xf30xd0x30xf6
2440xf40xa0xa0x0
2450xf50xb0x90xfe
2460xf60x80x80x0
2470xf70x90x70xfe
2480xf80x60xfe0xf8
2490xf90x70xfd0xf6
2500xfa0x40xfc0xf8
2510xfb0x50xfb0xf6
2520xfc0x20x20x0
2530xfd0x30x10xfe
2540xfe0x00x00x0
2550xff0x10xff0xfe
" ], "text/plain": [ "" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df_final.insert(loc=0, column='Ciphertext', value=df_final['XOR_Decoded'] ^ 0xFE)\n", "\n", "df_final = df_final.sort_values(by=['Ciphertext']).reset_index(drop=True)\n", "\n", "df_final.style.format({'Ciphertext':\"{:#x}\", 'XOR_Decoded':\"{:#x}\", 'Plaintext':\"{:#x}\", 'Sub':\"{:#x}\"}).background_gradient(cmap='plasma')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As this point, we have a table that maps each ciphertext/encoded value to its corresponding plaintext value. Let's grab the first 4 bytes of the file shared by Florian and use the mapping table above to decode the bytes:\n", "\n", "**Ciphertext** = 0xa9 0xa4 0x6e 0xfe\n", "
\n", "0xa9 --> 0x4d\n", "
\n", "0xa4 --> 0x5a\n", "
\n", "0x6e --> 0x90\n", "
\n", "0xfe --> 0x00\n", "

\n", "**Plaintext** = 0x4d 0x5a 0x90 0x00 (MZ\\x90\\x00), ***SUCCESS!***\n", "


\n", "Now let's use the char mapping/lookup table to decode the first 256 bytes of the encoded file:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "[+] Shared by Florian:\n", "\n", "00000000 a9 a4 6e fe f3 fe fe fe f2 fe fe fe ff ff fe fe ..n.............\n", "00000010 46 fe fe fe fe fe fe fe be fe fe fe fe fe fe fe F...............\n", "00000020 fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe ................\n", "00000030 fe fe fe fe fe fe fe fe fe fe fe fe 1e fe fe fe ................\n", "00000040 e8 df 44 e8 fe 42 f5 29 dd 46 fd aa 29 dd a2 96 ..D..B.).F..)...\n", "00000050 95 83 de 8e 8c 8f 97 8c 9d 89 de 93 9d 88 88 8f ................\n", "00000060 82 de 9c 91 de 8c 81 88 de 95 88 de b2 af a3 de ................\n", "00000070 89 8f 92 91 c8 e9 e9 f4 d2 fe fe fe fe fe fe fe ................\n", "00000080 13 fc 59 e2 57 93 03 b7 57 93 03 b7 57 93 03 b7 ..Y.W...W...W...\n", "00000090 48 db 90 b7 40 93 03 b7 48 db 8e b7 29 93 03 b7 H...@...H...)...\n", "000000a0 48 db 87 b7 61 93 03 b7 7e 51 76 b7 4a 93 03 b7 H...a...~Qv.J...\n", "000000b0 57 93 0c b7 23 93 03 b7 48 db 85 b7 50 93 03 b7 W...#...H...P...\n", "000000c0 48 db 9d b7 50 93 03 b7 48 db 9c b7 50 93 03 b7 H...P...H...P...\n", "000000d0 ac 95 93 96 57 93 03 b7 fe fe fe fe fe fe fe fe ....W...........\n", "000000e0 ae b1 fe fe aa fd f1 fe cf 61 16 a7 fe fe fe fe .........a......\n", "000000f0 fe fe fe fe 1e fe fc dd eb fd f5 fe fe 1c fe fe ................\n", "\n", "\n", "[+] Decoded:\n", "\n", "00000000 4d 5a 90 00 03 00 00 00 04 00 00 00 ff ff 00 00 MZ..............\n", "00000010 b8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 ........@.......\n", "00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................\n", "00000030 00 00 00 00 00 00 00 00 00 00 00 00 e0 00 00 00 ................\n", "00000040 0e 1f ba 0e 00 b4 09 cd 21 b8 01 4c cd 21 54 68 ........!..L.!Th\n", "00000050 69 73 20 70 72 6f 67 72 61 6d 20 63 61 6e 6e 6f is program canno\n", "00000060 74 20 62 65 20 72 75 6e 20 69 6e 20 44 4f 53 20 t be run in DOS \n", "00000070 6d 6f 64 65 2e 0d 0d 0a 24 00 00 00 00 00 00 00 mode....$.......\n", "00000080 e3 02 9d 14 a7 63 f3 47 a7 63 f3 47 a7 63 f3 47 .....c.G.c.G.c.G\n", "00000090 ae 1b 66 47 b6 63 f3 47 ae 1b 70 47 cd 63 f3 47 ..fG.c.G..pG.c.G\n", "000000a0 ae 1b 77 47 95 63 f3 47 80 a5 88 47 ac 63 f3 47 ..wG.c.G...G.c.G\n", "000000b0 a7 63 f2 47 d3 63 f3 47 ae 1b 79 47 a6 63 f3 47 .c.G.c.G..yG.c.G\n", "000000c0 ae 1b 61 47 a6 63 f3 47 ae 1b 62 47 a6 63 f3 47 ..aG.c.G..bG.c.G\n", "000000d0 52 69 63 68 a7 63 f3 47 00 00 00 00 00 00 00 00 Rich.c.G........\n", "000000e0 50 45 00 00 4c 01 05 00 2f 95 e8 57 00 00 00 00 PE..L.../..W....\n", "000000f0 00 00 00 00 e0 00 02 21 0b 01 09 00 00 e2 00 00 .......!........\n", "\n", "\n" ] } ], "source": [ "plaintext = list()\n", "ciphertext = (b'\\xA9\\xA4\\x6E\\xFE\\xF3\\xFE\\xFE\\xFE\\xF2\\xFE\\xFE\\xFE\\xFF\\xFF\\xFE\\xFE'\n", "b'\\x46\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xBE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE'\n", "b'\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE'\n", "b'\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\x1E\\xFE\\xFE\\xFE'\n", "b'\\xE8\\xDF\\x44\\xE8\\xFE\\x42\\xF5\\x29\\xDD\\x46\\xFD\\xAA\\x29\\xDD\\xA2\\x96'\n", "b'\\x95\\x83\\xDE\\x8E\\x8C\\x8F\\x97\\x8C\\x9D\\x89\\xDE\\x93\\x9D\\x88\\x88\\x8F'\n", "b'\\x82\\xDE\\x9C\\x91\\xDE\\x8C\\x81\\x88\\xDE\\x95\\x88\\xDE\\xB2\\xAF\\xA3\\xDE'\n", "b'\\x89\\x8F\\x92\\x91\\xC8\\xE9\\xE9\\xF4\\xD2\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE'\n", "b'\\x13\\xFC\\x59\\xE2\\x57\\x93\\x03\\xB7\\x57\\x93\\x03\\xB7\\x57\\x93\\x03\\xB7'\n", "b'\\x48\\xDB\\x90\\xB7\\x40\\x93\\x03\\xB7\\x48\\xDB\\x8E\\xB7\\x29\\x93\\x03\\xB7'\n", "b'\\x48\\xDB\\x87\\xB7\\x61\\x93\\x03\\xB7\\x7E\\x51\\x76\\xB7\\x4A\\x93\\x03\\xB7'\n", "b'\\x57\\x93\\x0C\\xB7\\x23\\x93\\x03\\xB7\\x48\\xDB\\x85\\xB7\\x50\\x93\\x03\\xB7'\n", "b'\\x48\\xDB\\x9D\\xB7\\x50\\x93\\x03\\xB7\\x48\\xDB\\x9C\\xB7\\x50\\x93\\x03\\xB7'\n", "b'\\xAC\\x95\\x93\\x96\\x57\\x93\\x03\\xB7\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE\\xFE'\n", "b'\\xAE\\xB1\\xFE\\xFE\\xAA\\xFD\\xF1\\xFE\\xCF\\x61\\x16\\xA7\\xFE\\xFE\\xFE\\xFE'\n", "b'\\xFE\\xFE\\xFE\\xFE\\x1E\\xFE\\xFC\\xDD\\xEB\\xFD\\xF5\\xFE\\xFE\\x1C\\xFE\\xFE')\n", "\n", "for c in ciphertext:\n", " plaintext.append(df_final.iloc[c]['Plaintext'] & 0xFF)\n", "\n", "print('\\n[+] Shared by Florian:\\n')\n", "hex_dump(ciphertext)\n", "print('\\n\\n[+] Decoded:\\n')\n", "hex_dump(plaintext)\n", "print('\\n')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "At this point I was still curious to know if there was anything else to the XOR+ADD operation logic so I wrote a tiny brute force script to implement a simple known-plaintext attack (KPA) tool. Instead of using the whole file or even the first 256 bytes header shown above I decided to only use the first 4 bytes of the encoded file as ciphertext to speed up the brute force process.\n", "

\n", "**Ciphertext:** 0xa9 0xa4 0x6e 0xfe\n", "
\n", "**Known plaintext:** 0x4d 0x5a 0x90 0x00 (just an educated guess, the last two bytes could vary)\n", "\n", "Using the values above, I wrote a script that uses all combinations of single-byte XOR keys and ADD keys to decode the ciphertext value above (can be optimized but left unrolled for readability).\n", "\n", "**1st attempt**: XOR Key: 0x01, ADD Key: 0x01\n", "
\n", "**2nd attempt**: XOR Key: 0x01, ADD Key: 0x02\n", "
\n", "**3rd attempt**: XOR Key: 0x01, ADD Key: 0x03\n", "
\n", "...\n", "
\n", "...\n", "
\n", "**5608th attempt:** XOR Key: 0xff, ADD Key: 0xfd\n", "
\n", "**5609th attempt:** XOR Key: 0xff, ADD Key: 0xfe\n", "
\n", "**5610th attempt:** XOR Key: 0xff, ADD Key: 0xff\n", "

\n", "After each decoding attempt, the script compares the decoded value with the known plaintext value to assess the success of the decoding process (i.e. if the decoded and known plaintext values match then we have the correct XOR and ADD key). While I was at it, I also wrote an XOR-SUB routine.\n" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "[*] (c ^ xor_key) + add_key:\n", "\t[+] (c ^ 0X5B) + 0X5B\n", "\t[+] (c ^ 0X7B) + 0X7B\n", "\t[+] (c ^ 0XDB) + 0XDB\n", "\t[+] (c ^ 0XFB) + 0XFB\n", "\n", "[*] (c ^ xor_key) - sub_key:\n", "\t[+] (c ^ 0X5B) - 0XA5\n", "\t[+] (c ^ 0X7B) - 0X85\n", "\t[+] (c ^ 0XDB) - 0X25\n", "\t[+] (c ^ 0XFB) - 0X5\n", "\n" ] } ], "source": [ "cipher = '\\xA9\\xA4\\x6E\\xFE'\n", "plaintext = '\\x4d\\x5a\\x90\\x00'\n", "\n", "# XOR-ADD Routine\n", "print('\\n[*] (c ^ xor_key) + add_key:')\n", "for xor_key in range(1, 256): #no need to XOR with 0\n", " for add_key in range(1, 256): #no need attemp add 0\n", " if ''.join(chr(((ord(c) ^ xor_key) + add_key) & 0xFF) for c in cipher) == plaintext:\n", " print('\\t[+] (c ^ {0:#2X}) + {1:#2X}'.format(xor_key, add_key))\n", "\n", "# XOR-SUB Routine\n", "print('\\n[*] (c ^ xor_key) - sub_key:')\n", "for xor_key in range(1, 256):\n", " for sub_key in range(1, 256):\n", " if ''.join(chr(((ord(c) ^ xor_key) - sub_key) & 0xFF) for c in cipher) == plaintext:\n", " print('\\t[+] (c ^ {0:#2X}) - {1:#2X}'.format(xor_key, sub_key))\n", "print()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As shown above, for the XOR-ADD operation 0x5B, 0x7B, 0xDB and 0xFB are all valid and matching XOR and ADD key values (i.e. all 4 matching keys pairs can be used to XOR-ADD decode the encoded file). There is certainly a relationship between the Sub pattern described in the sections above and the matching XOR-ADD keys above (especially considering XOR is technically a modulo-2 addition) but more research and analysis is required to discover the relationship.\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.0" } }, "nbformat": 4, "nbformat_minor": 4 }