Obfuscation is a tool employed by many malware writers and delivery agents. As always, the easier it is, the more attractive it is to those out to do harm; simple and easy are king in this world. XOR happens to meet both of these requirements - it is dead simple and since it exists as a fundamental operation at almost every level of computer and system architectures, it is extremely easy to use. Another of the popular tools used is padding or the addition of superfluous bytes to the beginning, middle or end of an artifact, to move the content starting point, making it difficult to detect, to hide start of content markers or to distort hash signatures.

XOR is a simple to understand and use function that is the basis for all cryptography. It is a way of encoding content so that it looks like gibberish and as such can’t be detected. It is done with a “key” that can be one byte in length up to a key the length of the content itself. The longer the key is, the higher the difficulty in decoding or cracking it (Fidelis XPS can discover XOR encryption keys of longer than length one, with or without padding - at line speed). Padding is the addition of extra bytes of filler content, usually to the beginning or end of the content but sometimes in the middle. So that is what XOR and padding are and how they are used for malicious purposes. Now we'll take a moment to dig in and understand this fundamental topic further.

XOR or 'exclusive OR' is a logical operation. Think of it like a box with two inputs and one output. Each input and the output can have only one of two states: true or false. True can be represented by a binary one and a false can be represented by a binary zero. If one and only one of the inputs is true then the output is true. If both inputs are false or both inputs are true, then the output is false. Said another way, XOR is true if an odd number of its arguments are true and false otherwise. In truth table format where A and B are the inputs and Y is the output, we see:

A B | Y

------------

0 0 | 0

0 1 | 1

1 0 | 1

1 1 | 0

In plain English, if the inputs are the same, the output is false and if the inputs are different, the output is true. So now we know what XOR is but we need to take a look at it in use to understand why and how people use it to implement basic encryption.

As previously mentioned, the reason why XOR is used is two-fold. First, the logical XOR operation has the property that the same key applied again with another XOR operation undoes the encryption. This makes it very easy to use. The second reason it is used is that XOR is one of the fastest operations a computer can do. It's implemented in electronics at the gate level and can be done extremely quickly and by using very few system resources. In fact, this is such a fundamental operation that most computers have an XOR instruction as part of their opcode or machine language set. This means that even for very long keys, it is extremely quick to perform the operations. The bad news is that it's not very good with encryption because the keys can be guessed by brute forcing all combinations - again being quick to implement it doesn't take long to iterate and since the input space is 8-bit characters, there are only 256 combinations to try for a single byte. The longer the key, the longer the guessing game takes (one byte = 256 combinations, two bytes = 256*256 = 65,536 combinations and in general, n bytes take 256^{n} tries in the worst case) and at line speed.

Padding is just the insertion of extra bits or bytes in front of something to hide it. If you know you added four bytes at the beginning of an artifact, after that file is transferred it won't be recognizable anymore and by extracting those four bytes at the beginning of the file once the transfer is complete, you get the original file again. Anything looking for a particular file signature that doesn't know to begin looking four bytes in will only see your padding values and be unable to recognize the original file type. When you combine basic padding with the XOR encryption described above, you get a fast, easy and simple way to hide from many in-line and line-speed appliances and also from many software security solutions.

As an example of how this looks in the real world, let's look at the letter A. It has ASCII code 65 in decimal which is 01000001 in binary. You can do these conversions quickly by either looking up an ASCII table (provided at the end of this document) which sometimes has the decimal (base 10), hexadecimal (base 16) and binary (base two) representations or by opening the Windows calculator, clicking on View and then select Programmer. Type in the number in calculator with the Dec selector on the left checked and then click on one of the other bases, like Bin for binary to show the number in that base.

Taking the ASCII code for A, we can take each binary digit and exclusive OR it with a "key." Let's choose a random value to use for our key, say the decimal number 15 or 00001111 in binary. So we'll do the exclusive OR and see what we get:

0 1 0 0 0 0 0 1 Letter A

0 0 0 0 1 1 1 1 Key = 15

-----------------------

0 1 0 0 1 1 1 0 Answer = 78 or ASCII character N

This operation is applied bit by bit. In the letter A, starting at the right-most bit which is a one, the key also has a one in this position. Using the truth table above, we see that a one and a one on the inputs results in a zero on the output so the Answer has a zero in the right-most bit position. We move left one bit at a time, repeat the process and get the Answer string. Something interesting happens if you apply the exact same key with another XOR operation:

0 1 0 0 1 1 1 0 Original answer of 78 or ASCII character N

0 0 0 0 1 1 1 1 Key = 15

-----------------------

0 1 0 0 0 0 01 Answer = 65 or Letter A

In fact, two XOR operations with the same key always return the original value! This is the basic premise of a shared-key (symmetric) encryption.

What we have demonstrated here so far is a single byte XOR key. Let's take a look at a short message and a two byte key.

This time our message will be longer than a single character, let's use the word: SECRET. In ASCII this is 83 69 67 82 69 84. The key we'll choose is the two letter combination GD or in ASCII, 71 68. Since there are more than two letters in the message, we'll repeat the key over and over - we need one byte of key for each byte of message:

83 69 67 82 69 84

ASCII Message: SECRET 1010011 1000101 1000011 1010010 1000101 1010100

Key (repeated): GDGDGD 1000111 1000100 1000111 1000100 1000111 1000100

--------------------------------------------------------------------------------

XOR result (cipher text) 0010100 0000001 0000100 0010110 0000010 0010000

Decimal equivalent 20 1 4 22 2 16

(none are printable characters)

If we apply key again, as expected we get the original message back:

XOR result (cipher text) 0010100 0000001 0000100 0010110 0000010 0010000

Key (repeated): GDGDGD 1000111 1000100 1000111 1000100 1000111 1000100

---------------------------------------------------------------------------------

ASCII Message: SECRET 1010011 1000101 1000011 1010010 1000101 1010100

Had we applied only one byte of the key, the G for example, every other character would have been decoded:

XOR result (cipher text) 0010100 0000001 0000100 0010110 0000010 0010000

Key (repeated): GGGGGG 1000111 1000111 1000111 1000111 1000111 1000111

---------------------------------------------------------------------------------

ASCII Message: SFCQEW 1010011 1000110 1000011 1010001 1000101 1010111

As we see, only every other character is correctly decoded as the second byte of the key is wrong. Note there is no limit to the size of the key; you can use as many characters in the key as you have letters in the plaintext message. You can easily see how many guesses there are to getting an eight-byte key and why it can’t (as yet) be done at line speed, even with some very clever programmers.

Being able to see that a file has padding, that it is XOR encoded/encrypted and to undo that encryption at line speeds is a quality you should look for in any solution purporting to detect malware, malicious activity, data exfiltration and other security concerns. If you can't see the payloads then you can't make decisions on them and that traffic is hidden to you.

**Additional Materials **

**ASCII Table in Decimal, Hexadecimal and Octal**

**ASCII Table Providing Direct Binary Output**

Note: A is 65 decimal = 1000001 so you read the left-most three bits from the top row and the right-most four bits from the left columns, left to right for the seven-bit ASCII code. Put a zero in the left most bit if your key is a true 8-bit value.

-Darian Lewis