Decoding XOR payload using first few bytes as key

I recently came across the need to decode an exclusive or (XOR) payload. In my case, the key to de-obfuscating the traffic was the first three bytes of each packets payload. While it is trivial to decode each payload, it was not reasonable for a large number of packets.

For testing purposes, create a packet:

$ scapy
Welcome to Scapy (2.1.0)
>>> p = (IP(ttl=10)/TCP(sport=1024,dport=443,flags="S")/"   WHATSTHESECRET0000ABCD0000ABCD0000ABCD")
>>> wrpcap("p.pcap", p)
>>> quit()

Should see something similar to this:

04:29:31.255470 IP 127.0.0.1.1024 > 127.0.0.1.443: Flags [S], seq 0:41, win 8192, length 41
        0x0000:  4500 0051 0001 0000 0a06 b2a4 7f00 0001  E..Q............
        0x0010:  7f00 0001 0400 01bb 0000 0000 0000 0000  ................
        0x0020:  5002 2000 751d 0000 2020 2057 4841 5453  P...u......WHATS
        0x0030:  5448 4553 4543 5245 5430 3030 3041 4243  THESECRET0000ABC
        0x0040:  4430 3030 3041 4243 4430 3030 3041 4243  D0000ABCD0000ABC
        0x0050:  44                                       D

Next, the payload is XOR’d using the first three bytes of the payload for the entire payload. If you note the first tcpdump, the three bytes of the payload were left empty, here I am placing the key that will be used to XOR the rest of the payload within the first three bytes of the payload.

The payload has been obfuscated using the key ‘the’.

Next we can use the script below or here to decode all of the packets. The script is not intelligent enough to know which need to be de-obfuscated so it is best to probably filter these into a new PCAP. Secondly, the script requires Scapy to be installed.

#! /usr/bin/python

# Script to parse a PCAP and XOR data based on a byte offset
# Requires Scapy
# 0.1 - 07172012
# Default is two bytes, change at line 35
# Stephen Reese and Chris Gragsone
#
# todo: add two more args, offset length and static offset option

from scapy.all import *
import sys

# Get input and output files from command line
if len(sys.argv) < 2:
        print "Usage: decodexorpayload.py [input pcap file]"
        sys.exit(1)

# Assign variable names for input and output files
infile = sys.argv[1]

def many_byte_xor(buf, key):
    buf = bytearray(buf)
    key = bytearray(key)
    key_len = len(key)
    for i, bufbyte in enumerate(buf):
        buf[i] = bufbyte ^ key[i % key_len]
    return str(buf)

def process_packets():
    pkts = rdpcap(infile)
    cooked=[]
    for p in pkts:
        # You may have to adjust the payload depth here:
        # i.e. p.payload.payload.payload
        pkt_payload = str(p.payload.payload)
        pkt_offset = str(p.payload.payload)[:3]
        if pkt_payload and pkt_offset:
              pmod=p
              # You may have to adjust the payload depth here:
              p.payload.payload=many_byte_xor(pkt_payload, pkt_offset)
              cooked.append(pmod)

    wrpcap("dump.pcap", cooked)

process_packets()

After script completion, viewing the packet does indeed show the de-obfuscated packet:

reading from file dump.pcap, link-type RAW (Raw IP)
04:24:44.415262 IP 127.0.0.1.1024 > 127.0.0.1.443: Flags [S], seq 0:41, win 8192, length 41
        0x0000:  4500 0051 0001 0000 0a06 b2a4 7f00 0001  E..Q............
        0x0010:  7f00 0001 0400 01bb 0000 0000 0000 0000  ................
        0x0020:  5002 2000 751d 0000 0000 0057 4841 5453  P...u......WHATS
        0x0030:  5448 4553 4543 5245 5430 3030 3041 4243  THESECRET0000ABC
        0x0040:  4430 3030 3041 4243 4430 3030 3041 4243  D0000ABCD0000ABC
        0x0050:  44                                       D

There are a number of features that could be added and of course the code can probably be improved upon. Have some ideas? Leave a comment below.

This entry was posted in network, security and tagged , . Bookmark the permalink.

4 Responses to Decoding XOR payload using first few bytes as key

  1. Vinoth says:

    I had extracted the hexadecimal byte sequence of the packet payload using libpcap. I have to perform byte matching to extract substrings and tokens doyou have any idea. Help me sir.

  2. Per the payload you described, that *may* be a browser or toolbar testing a site against Google’s Safe Browsing API see https://developers.google.com/safe-browsing/developers_guide_v2. The portion that appears obfuscated is probably their one-way hash of the domain or URI in question. If this is the case, you will need to matching hash value as they use SHA256 to determine the URI in question. That said, ymmv and this is only an opinion.

  3. Vinoth says:

    Sir how to extract strings and tokens from payload hex array

  4. I would use Scapy to extract the payload. Next, extract the strings or whatever data from said payload and parse it as you see fit.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>