Category:Encryption/XOR

From aldeid
Jump to navigation Jump to search
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']
Note
Notice that the XOR cipher resulted in bytes that are not printable (in yellow).

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