Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
108 lines (84 sloc) 2.9 KB
'''
KeyBoy C2 traffic pcap decoder
From: It's Parliamentary: KeyBoy and the targeting of the Tibetan Community
Permalink: https://citizenlab.org/2016/11/parliament-keyboy/
Adam Hulcoop / September 19, 2016
adam.hulcoop[@]citizenlab.ca
32 bit support only [64bit can use manual override]
'''
import scapy
import argparse
import logging
import sys,getopt
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.all import TCP,rdpcap,Raw
def egcd(a, b):
if a == 0:
return (b, 0, 1)
else:
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)
def modinv(a, m):
g, x, y = egcd(a, m)
if g != 1:
raise Exception('modular inverse does not exist')
else:
return x % m
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Decode KeyBoy C2 traffic from pcap file')
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('-k','--key',type=int, help="Manually provide C2 decode key")
group.add_argument('-b','--binary',help="KeyBoy binary")
parser.add_argument('PCAPF', help='PCAP File containing c2 traffic')
parser.add_argument('--verbose','-v',action='store_true',help='Enable verbose output')
args = parser.parse_args()
if args.verbose:
logging.basicConfig(format='%(message)s',level=logging.DEBUG)
else:
logging.basicConfig(format='%(message)s',level=logging.WARNING)
print "============================"
print "{KeyBoy C2 Traffic decoder}"
print "============================"
print ""
if args.binary:
with open(args.binary,'rb') as keyboy_file:
keyboy_file.seek(0,2)
num_bytes_kb = keyboy_file.tell()
count =0
for i in range(num_bytes_kb):
keyboy_file.seek(i)
sig_p1 = keyboy_file.read(4)
sig_const = keyboy_file.read(1)
sig_p2 = keyboy_file.read(7)
if ( (sig_p1 == b"\x8a\x04\x73\xb1") or (sig_p1 == b"\x8a\x04\x1e\xb1") ):
if ( (sig_p2 == b"\xf6\xe9\x88\x04\x73\x53\x46") or (sig_p2 == b"\xf6\xe9\x88\x04\x1e\x8b\xc3") ):
#sig_const should be the encoding constant
#print "Found const: 0x%x" % ord(sig_const)
logging.debug("Found constant: 0x%x" % ord(sig_const))
encode_val = ord(sig_const)
count += 1
break
if count < 1 :
logging.warn("Didn't find signature\nQuitting..")
sys.exit(1)
else:
logging.debug( "Computing decode value...")
inv = modinv(encode_val,256)
logging.debug("Found decoding multiplier (inverse): %s" % hex(inv))
else:
logging.debug("Using manually specified decoding multiplier (inverse): %s" % hex(args.key))
inv = args.key
logging.warn ("Searching PCAP for RAW TCP packets and decoding...")
logging.warn("")
data =''
p = rdpcap(args.PCAPF)
for pkt in p:
if( pkt.haslayer(TCP)):
if( pkt.haslayer(Raw)):
ba = bytearray(pkt.getlayer(Raw).load)
for byte in ba:
if byte == 0:
data += ''
else:
data += chr(int((byte*inv) & 255))
logging.warn(data)