Category:Encryption/XOR
You are here | XOR
|
Description
- XOR means exclusive OR and is a logical operation that can be used to modify bits.
- The XOR cipher is a reversible cipher.
Here is an example:
hex | bin | |||||||
---|---|---|---|---|---|---|---|---|
x | 0x41 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |
y | 0x3c | 0 | 1 | 1 | 1 | 1 | 0 | 0 |
x ^ y | 0x7d | 1 | 1 | 1 | 1 | 1 | 0 | 1 |
Example
Single-byte XOR
Given the following message to encrypt with XOR:
>>> s = "MY SECRET MESSAGE"
We first convert each letter in hexadecimal:
>>> h = [hex(ord(i)) for i in s] >>> h ['0x4d', '0x59', '0x20', '0x53', '0x45', '0x43', '0x52', '0x45', '0x54', '0x20', '0x4d', '0x45', '0x53', '0x53', '0x41', '0x47', '0x45']
Now we XOR all items with 0x3c, our key:
>>> x = [hex(int(i, 16) ^ 0x3c) for i in h] ['0x71', '0x65', '0x1c', '0x6f', '0x79', '0x7f', '0x6e', '0x79', '0x68', '0x1c', '0x71', '0x79', '0x6f', '0x6f', '0x7d', '0x7b', '0x79']
And we retrieve the corresponding ASCII characters:
>>> e = [chr(int(i, 16)) for i in x] >>> e ['q', 'e', '\x1c', 'o', 'y', '\x7f', 'n', 'y', 'h', '\x1c', 'q', 'y', 'o', 'o', '}', '{', 'y']
NULL-preserving XOR
NULL-preserving XOR works the same way XOR does except that bytes that are NULL (0x00) or corresponding to the XOR key (e.g. 0x3c) are not XOR'ed.
Brute Forcing
Single-byte XOR
You can use the following python script to generate all possible 1-byte encoded XOR strings based on the plain string "This program" and use Yara to detect the presence of XOR encrypted resources in malware.
#!/usr/bin/env python
s = "This program"
for ko in range(255):
kh = hex(ko+1)
print "rule resource_XOR_%s" % kh
print "{"
print " meta:"
print ' description = "Resource XOR %s"' % kh
print ""
print " strings:"
print " $a = {%s}" % ' '.join([format(int(hex(ord(i)),16) ^ int(kh, 16), 'X').zfill(2) for i in s])
print ""
print " condition:"
print " any of them"
print "}"
These Yara signatures (capabilities.yara) can easily be used in combination with pescanner:
$ ./pescanner.py Lab12-02.exe ################################################################################ Record 0 ################################################################################ Meta-data ================================================================================ File: /data/documents/malware-analysis/BinaryCollection/Chapter_12L/Lab12-02.exe Size: 53248 bytes Type: MD5: e2bf42217a67e46433da8b6f4507219e SHA1: daf263702f11dc0430d30f9bf443e7885cf91fcb ssdeep: Date: 0x4D9F4BCF [Fri Apr 8 17:54:23 2011 UTC] EP: 0x401adb .text 0/4 CRC: Claimed: 0x0, Actual: 0x195a9 [SUSPICIOUS] Packers: Microsoft Visual C++ v6.0 Signature scans ================================================================================ YARA: resource_XOR_0x41 0x60d2L => 152928326131332e2633202c Resource entries ================================================================================ Name RVA Size Lang Sublang Type -------------------------------------------------------------------------------- UNICODE 0x6084 0x6000 LANG_NEUTRAL SUBLANG_NEUTRAL Suspicious IAT alerts ================================================================================ WriteProcessMemory VirtualAllocEx ReadProcessMemory CreateProcessA Sections ================================================================================ Name VirtAddr VirtSize RawSize Entropy -------------------------------------------------------------------------------- .text 0x1000 0x2e96 0x3000 6.402917 .rdata 0x4000 0x8f2 0x1000 3.550092 .data 0x5000 0x7dc 0x1000 0.761837 [SUSPICIOUS] .rsrc 0x6000 0x6084 0x7000 4.473353
NULL-preserving XOR
You can use the following python script to generate all possible 1-byte NULL-preserving XOR encrypted strings based on the plain string "This program" and use Yara to detect the presence of XOR encrypted resources in malware.
#!/usr/bin/env python
s = "This program"
for ko in range(255):
kh = hex(ko+1)
h = []
# Test for each letter in the string
for ba in s:
# Letter converted to hex
bh = hex(ord(ba))
# if hex-letter is NULL or the XOR key, it is left without modification
# As there is no NULL byte in our string, we skip the test
if bh == kh:
h.append(format(ord(ba), 'X').zfill(2))
else:
h.append(format(int(bh, 16) ^ int(kh, 16), 'X').zfill(2))
print "rule resource_NULL_preserving_XOR_%s" % kh
print "{"
print " meta:"
print ' description = "Resource NULL-Preserving XOR %s"' % kh
print ""
print " strings:"
print " $a = {%s}" % ' '.join(h)
print ""
print " condition:"
print " any of them"
print "}"
XOR in assembly code
Recognizing XOR
All instances of xor in the disassembled code do not identify XOR encryption.
- Indeed, xor might be used to clear registers (e.g. xor eax, eax).
- But in these forms, XOR might indicate encoding:
xor edx, 0x12 ; XOR with a constant
mov edx, 0x12
xor eax, edx ; xor of 2 distinct registers, one of which referring to a constant
Reversing XOR
As XOR is reversible, it's easy to reverse. Here is an example:
Assembly | Reversing code (python) |
---|---|
xor byte ptr [rax], 64
xor byte ptr [rax], 0xf2
xor byte ptr [rax], 0xb3
cmp byte ptr [rax], 48
|
48 ^ 0xb3 ^ 0xf2 ^ 64
|
For more examples, refer to The-FLARE-On-Challenge-01/Challenge-6.
Tools
Tool | Description |
---|---|
brutexor (iheartxor) | brutexor (also called iheartxor) by Alexander Hanel brute-forces all possible 1-byte XOR key values and examines the file for strings that might have been encoded with these keys. |
McAfee Unbup (see xor.pl) | xor.pl is a simple bitwise xor script written in Perl |
NoMoreXOR | Tool by Glenn P. Edwards Jr. to help guess a files 256 byte XOR key by using frequency analysis. |
translate.py | Python script written by Didier Stevens to perform bitwise operations on files (like XOR, ROL/ROR, …). You specify the bitwise operation to perform as a Python expression, and pass it as a command-line argument. |
unxor | |
xorBruteForcer | |
XORSearch | searches for a XOR, ROL, ROT or SHIFT encoded strings in a file using brute-force |
XORStrings | |
Xortool |
Pages in category "Encryption/XOR"
The following 12 pages are in this category, out of 12 total.