''' 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)