├── README.md ├── xorbot.rb ├── blackenergy.py ├── config_jRAT.py ├── spyeye_config.py ├── darkcomet.py ├── wirenet.py ├── bozok_config.py ├── pandora2_config.py ├── cloger7_config.py ├── KimJongRAT.py └── xtremerat_config.py /README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /xorbot.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby1.9.1 2 | # Malware.lu 3 | 4 | malwareFile = File.open(ARGV[0], 'r') 5 | malwareFile.seek(0xee60, IO::SEEK_SET) 6 | key = malwareFile.sysread(0x7) 7 | 8 | file = File.open(ARGV[0], 'r') 9 | file.seek(0x0, IO::SEEK_SET) 10 | str = file.sysread(File.stat(ARGV[0]).size) 11 | i=0 12 | 13 | str.each_byte { |x| 14 | while i != 7 do 15 | x = x ^ key[i].ord 16 | i=i+1 17 | end 18 | putc ~x 19 | i=0 20 | } 21 | -------------------------------------------------------------------------------- /blackenergy.py: -------------------------------------------------------------------------------- 1 | # Malware.lu 2 | import sys 3 | import string 4 | 5 | def arc4(key, data): 6 | x = 0 7 | box = range(256) 8 | for i in range(256): 9 | box[i] = (box[i] ^ ord(key[i % len(key)])) % 256 10 | 11 | x = y = 0 12 | out = [] 13 | for char in data: 14 | x = (x + 1) % 256 15 | y = (y + box[x]) % 256 16 | box[x], box[y] = box[y], box[x] 17 | out.append(chr(ord(char) ^ box[(box[x] + box[y]) % 256])) 18 | 19 | return ''.join(out) 20 | 21 | if __name__ == "__main__": 22 | fp = open(sys.argv[1]) 23 | fp.seek(0x10) 24 | key = fp.read(0x10) 25 | data = fp.read() 26 | data = arc4(key, data) 27 | sys.stdout.write(data) 28 | -------------------------------------------------------------------------------- /config_jRAT.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Malware.lu 4 | import sys,zipfile 5 | from Crypto.Cipher import DES3 6 | from curses.ascii import isprint 7 | 8 | def printable(input): 9 | return ''.join(char for char in input if isprint(char)) 10 | 11 | def unzip_file(file, data): 12 | zfile = zipfile.ZipFile(file) 13 | i = 0 14 | for name in "key.dat", "config.dat": 15 | data.append(zfile.read(name)) 16 | i+=1 17 | 18 | if __name__ == "__main__": 19 | data=[] 20 | unzip_file(sys.argv[1], data) 21 | 22 | cipher = DES3.new(data[0]) 23 | output = cipher.decrypt(data[1]) 24 | print(printable(output).replace("SPLIT", "\n")) 25 | -------------------------------------------------------------------------------- /spyeye_config.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # darkcomet_config.py 3 | # From https://bitbucket.org/r3shl4k1sh/spyeyeconfdec/src/7b33218efe66af844a1f6c18ea308caf08fbd818/SpyEyeConfDec.py 4 | 5 | import os, sys, argparse 6 | 7 | args = 0 8 | 9 | def TakeArgs(): 10 | global args 11 | 12 | parser = argparse.ArgumentParser(description = "Decrypt the config.bin file of common SpyEye Trojan.") 13 | parser.add_argument("EncryptedFile", type=argparse.FileType('rb'), help="The config.bin file path") 14 | parser.add_argument("DecryptedFile", type=argparse.FileType('wb'), help="The decrypted file path") 15 | #parser.add_argument("XORbyte", help="The XOR byte used to decrypt the file [usually 0x4C]") 16 | 17 | args = parser.parse_args() 18 | 19 | 20 | def main(): 21 | 22 | xor = int(0xC4) 23 | EncData = bytearray(args.EncryptedFile.read()) 24 | 25 | counter = 0 26 | 27 | for idx, byte in reversed(list(enumerate(EncData))): 28 | if idx == 0: 29 | break 30 | var = byte ^ xor 31 | EncData[idx] = (var - EncData[idx -1]) & 0xFF 32 | 33 | 34 | args.DecryptedFile.write(EncData) 35 | 36 | args.DecryptedFile.close() 37 | args.EncryptedFile.close() 38 | 39 | 40 | if __name__ == "__main__": 41 | TakeArgs() 42 | main() 43 | -------------------------------------------------------------------------------- /darkcomet.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # darkcomet_config.py 3 | # From https://code.google.com/p/alienvault-labs-garage/downloads/detail?name=extract_config_from_binary.py 4 | 5 | import pefile 6 | import sys 7 | import random, base64, sys 8 | from binascii import * 9 | 10 | key = "#KCMDDC5#-890" 11 | 12 | 13 | def rc4crypt(data, key): 14 | x = 0 15 | box = range(256) 16 | for i in range(256): 17 | x = (x + box[i] + ord(key[i % len(key)])) % 256 18 | box[i], box[x] = box[x], box[i] 19 | x = 0 20 | y = 0 21 | out = [] 22 | for char in data: 23 | x = (x + 1) % 256 24 | y = (y + box[x]) % 256 25 | box[x], box[y] = box[y], box[x] 26 | out.append(chr(ord(char) ^ box[(box[x] + box[y]) % 256])) 27 | 28 | return ''.join(out) 29 | 30 | 31 | pe = pefile.PE(sys.argv[1]) 32 | 33 | config = {"GENCODE": "", "MUTEX": "", "NETDATA": "", "PWD": "", "SID": ""} 34 | 35 | rt_string_idx = [ 36 | entry.id for entry in 37 | pe.DIRECTORY_ENTRY_RESOURCE.entries].index(pefile.RESOURCE_TYPE['RT_RCDATA']) 38 | 39 | rt_string_directory = pe.DIRECTORY_ENTRY_RESOURCE.entries[rt_string_idx] 40 | 41 | for entry in rt_string_directory.directory.entries: 42 | if str(entry.name) in config.keys(): 43 | data_rva = entry.directory.entries[0].data.struct.OffsetToData 44 | size = entry.directory.entries[0].data.struct.Size 45 | 46 | data = pe.get_memory_mapped_image()[data_rva:data_rva + size] 47 | try: 48 | dec = rc4crypt(unhexlify(data), key) 49 | config[str(entry.name)] = dec 50 | except: 51 | print "Error during decrytion" 52 | 53 | print config -------------------------------------------------------------------------------- /wirenet.py: -------------------------------------------------------------------------------- 1 | # Malware.lu 2 | import sys 3 | from Crypto.Cipher import ARC4 4 | 5 | 6 | crypted = [ 7 | { 'name':'ConnectionString', 'adr': 0xf610, 'len': 0xff }, 8 | { 'name':'ProxyString', 'adr': 0xf510, 'len': 0xff }, 9 | { 'name':'Password', 'adr': 0xf4ec, 'len': 0x20 }, 10 | { 'name':'HostId', 'adr': 0xf4c4, 'len': 0x10 }, 11 | { 'name':'MutexName', 'adr': 0xf4b8, 'len': 0x8 }, 12 | { 'name':'InstallPath', 'adr': 0xf434, 'len': 0x80 }, 13 | { 'name':'StartupKeyName1', 'adr': 0xf420, 'len': 0x10 }, 14 | { 'name':'StartupKeyName2', 'adr': 0xf3f8, 'len': 0x26 }, 15 | { 'name':'KeyLoggerFileName', 'adr': 0xf374, 'len': 0x80 }, 16 | { 'name':'BoolSettingsByte', 'adr': 0xf370, 'len': 0x3 }, 17 | { 'name':'ConnectionType', 'adr': 0xf36c, 'len': 0x3 } 18 | ] 19 | 20 | 21 | options = { 22 | 'install_file': 1, 23 | 'lock_file?': 4, # not sure 24 | 'desktop_start': 8, 25 | 'xinit_start': 16, 26 | 'single_instance': 32, 27 | 'keylogger': 64, 28 | 'run_as_daemon': 128, 29 | } 30 | 31 | 32 | def isOption(set_bytes, val): 33 | return ((val & int(set_bytes)) == val) 34 | 35 | 36 | fp = open(sys.argv[1]) 37 | fp.seek(0xf4d8, 0) 38 | key = fp.read(16) 39 | 40 | 41 | for c in crypted: 42 | rc4 = ARC4.new(key) 43 | fp.seek(c['adr']) 44 | data = fp.read(c['len']) 45 | val = rc4.decrypt(data).split('\x00')[0] print "%s: %s" % (c['name'], val) 46 | 47 | 48 | if c['name'] == 'BoolSettingsByte': 49 | for name, o in options.iteritems(): 50 | print "%s: %s" % (name, isOption(val, o)) 51 | 52 | -------------------------------------------------------------------------------- /bozok_config.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding:utf-8 -*- 3 | # cloger7_config.py 4 | # _ _ 5 | # _ __ ___ __ _| |_ ____ _ _ __ ___ | |_ _ 6 | # | '_ ` _ \ / _` | \ \ /\ / / _` | '__/ _ \ | | | | | 7 | # | | | | | | (_| | |\ V V / (_| | | | __/_| | |_| | 8 | # |_| |_| |_|\__,_|_| \_/\_/ \__,_|_| \___(_)_|\__,_| 9 | 10 | 11 | import sys 12 | import os 13 | import argparse 14 | 15 | 16 | def find_package_info(bozok): 17 | bozok = bozok.read() 18 | return int(bozok.find("I\0N\0F\0")) 19 | 20 | 21 | def print_conf(filename): 22 | 23 | bozok = open(filename, "rb") 24 | 25 | bozok.seek(find_package_info(bozok), 0) 26 | 27 | result = {} 28 | parsed = bozok.read().strip().split("|") 29 | parsed = [p.replace("\0", "") for p in parsed] 30 | result["Server ID"] = parsed[0] 31 | result["mutex"] = parsed[1] 32 | result["filename"] = parsed[2] 33 | result["startup key"] = parsed[3] 34 | result["extension name"] = parsed[4] 35 | result["password"] = parsed[5] 36 | result["Install Server"] = parsed[6] 37 | result["Startup Server"] = parsed[7] 38 | result["Visible Mode"] = parsed[8] 39 | result["option4"] = parsed[9] 40 | result["option5"] = parsed[10] 41 | result["port"] = parsed[11] 42 | result["ip address"] = parsed[12] 43 | result["option6"] = parsed[13] 44 | if os.path.getsize(filename) > 100000: 45 | result["Include Extension"] = True 46 | 47 | for key in result: 48 | print(key+" : "+str(result[key])) 49 | 50 | bozok.close() 51 | 52 | 53 | def main(): 54 | 55 | 56 | parser = argparse.ArgumentParser(description = "Malware.lu Bozok config extractor") 57 | parser.add_argument('-d', '--decode', action='store_true', 58 | help="Print the configuration") 59 | parser.add_argument( dest="filename", 60 | help="Bozok binary file") 61 | try: 62 | r = parser.parse_args() 63 | 64 | if r.decode: 65 | print_conf(r.filename) 66 | else: 67 | parser.print_help() 68 | 69 | except Exception as e: 70 | print >> sys.stderr, "Exception", e 71 | 72 | if __name__ == '__main__': 73 | main() 74 | -------------------------------------------------------------------------------- /pandora2_config.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding:utf-8 -*- 3 | # pandora2_config.py 4 | # _ _ 5 | # _ __ ___ __ _| |_ ____ _ _ __ ___ | |_ _ 6 | # | '_ ` _ \ / _` | \ \ /\ / / _` | '__/ _ \ | | | | | 7 | # | | | | | | (_| | |\ V V / (_| | | | __/_| | |_| | 8 | # |_| |_| |_|\__,_|_| \_/\_/ \__,_|_| \___(_)_|\__,_| 9 | 10 | 11 | import sys 12 | import argparse 13 | 14 | 15 | def find_package_info(pandora): 16 | pandora = pandora.read() 17 | return int(pandora.find("\x00\x6C\x00\x6F\x00\x77\x00\x00\x00")) 18 | 19 | 20 | def print_conf(filename): 21 | 22 | malware = open(filename, "rb") 23 | 24 | malware.seek(find_package_info(malware), 0) 25 | 26 | result = {} 27 | parsed = malware.read().strip().split("##") 28 | result["ip address"] = parsed[0].replace("\x00\x6C\x00\x6F\x00\x77\x00\x00\x00", "") 29 | result["port"] = parsed[1] 30 | result["password"] = parsed[2] 31 | result["Server Directory"] = parsed[3] 32 | result["Server Filename"] = parsed[4] 33 | result["HKCU Startup key"] = parsed[5] 34 | result["Active Setup Registry Key"] = parsed[6] 35 | result["Install Server"] = parsed[7] 36 | result["Startup"] = parsed[8] 37 | result["ActiveX Startup"] = parsed[9] 38 | result["HKCU Startup"] = parsed[10] 39 | result["mutex"] = parsed[11] 40 | result["Usermode Unhooking"] = parsed[12] 41 | result["Melt Server"] = parsed[13] 42 | result["Activate Keylogger"] = parsed[14] 43 | result["Server ID"] = parsed[15] 44 | result["option1"] = parsed[16] 45 | result["Persistance"] = parsed[17] 46 | 47 | for key in result: 48 | print(key+" : "+str(result[key])) 49 | 50 | malware.close() 51 | 52 | 53 | def main(): 54 | 55 | 56 | parser = argparse.ArgumentParser(description = "Malware.lu Pandora2 config extractor") 57 | parser.add_argument('-d', '--decode', action='store_true', 58 | help="Print the configuration") 59 | parser.add_argument( dest="filename", 60 | help="Pandora2 binary file") 61 | try: 62 | r = parser.parse_args() 63 | 64 | if r.decode: 65 | print_conf(r.filename) 66 | else: 67 | parser.print_help() 68 | 69 | except Exception as e: 70 | print >> sys.stderr, "Exception", e 71 | 72 | if __name__ == '__main__': 73 | main() 74 | -------------------------------------------------------------------------------- /cloger7_config.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # cloger7_config.py 3 | # _ _ 4 | # _ __ ___ __ _| |_ ____ _ _ __ ___ | |_ _ 5 | # | '_ ` _ \ / _` | \ \ /\ / / _` | '__/ _ \ | | | | | 6 | # | | | | | | (_| | |\ V V / (_| | | | __/_| | |_| | 7 | # |_| |_| |_|\__,_|_| \_/\_/ \__,_|_| \___(_)_|\__,_| 8 | 9 | 10 | import sys,argparse,re,base64 11 | 12 | 13 | 14 | def print_conf(filename): 15 | malware = open(filename,"rb") 16 | 17 | clog = re.compile("@CLOG7@") 18 | parsed = [] 19 | for line in malware: 20 | parsed= clog.split(line) 21 | 22 | result = {} 23 | 24 | #result["code"] = parsed[0] 25 | result["mail_host"] = parsed[1] 26 | result["mail_port"] = parsed[2] 27 | result["mail_adress"] = base64.b64decode(parsed[3]) 28 | result["mail_pass"] = base64.b64decode(parsed[4]) 29 | result["mail_adress2"] = base64.b64decode(parsed[5]) 30 | result["ftp_adress"] = parsed[6] 31 | result["ftp_user"] = parsed[7] 32 | result["ftp_pass"] = parsed[8] 33 | result["temp_folder"] = parsed[9] 34 | result["disable_taskManager_enabled"] = parsed[10] 35 | result["unknown_option1"] = parsed[11] 36 | result["unknown_option2"] = parsed[12] 37 | result["unknown_option3"] = parsed[13] 38 | result["name_of_server"] = parsed[14]+".exe" 39 | result["addstartup_enabled"] = parsed[15] 40 | result["msgBoxStyle.information"] = parsed[16] 41 | result["msgBoxStyle.exclamation"] = parsed[17] 42 | result["msgBoxStyle.question"] = parsed[18] 43 | result["msgBoxStyle.critical"] = parsed[19] 44 | result["msgBox_message"] = parsed[20] 45 | result["msgBox_title"] = parsed[21] 46 | result["mutex"] = parsed[22] 47 | 48 | for key in result: 49 | print(key+" : "+result[key]) 50 | 51 | 52 | def main(): 53 | parser = argparse.ArgumentParser(description = "Malware.lu CLoger7 config extractor") 54 | parser.add_argument('-d', '--decode', action='store_true', 55 | help="Print the configuration") 56 | parser.add_argument( dest="filename", 57 | help="CLoger7 binary file") 58 | try: 59 | r = parser.parse_args() 60 | 61 | if r.decode: 62 | print_conf(r.filename) 63 | else: 64 | parser.print_help() 65 | 66 | except Exception as e: 67 | print >> sys.stderr, "Exception", e 68 | 69 | if __name__ == '__main__': 70 | main() -------------------------------------------------------------------------------- /KimJongRAT.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Malware.lu 4 | from Crypto.Cipher import ARC4 5 | import sys 6 | import argparse 7 | import magic 8 | import base64 9 | from urlparse import urlparse 10 | import os 11 | import os.path 12 | import requests 13 | 14 | def decode(data): 15 | key = data[:0x10] 16 | data = data[0x10:] 17 | # remove null byte in case 18 | data = data.strip('\x00') 19 | rc4 = ARC4.new(key) 20 | return rc4.decrypt(data) 21 | 22 | def get_magic(data): 23 | try: 24 | return magic.from_buffer(data) 25 | except Exception, e: 26 | print e 27 | return "" 28 | 29 | def extract_res(magictag, data, n = 0): 30 | i = -1 31 | res_end = 0 32 | while i < n: 33 | data = data[res_end:] 34 | res_start = data.index(magictag) + len(magictag) 35 | if res_start == None: 36 | break 37 | data = data[res_start:] 38 | res_end = data.index(magictag) + len(magictag) 39 | i += 1 40 | 41 | # out magic end 42 | data = data[:-0x8] 43 | return decode(data) 44 | 45 | def decode_file(data): 46 | return decode(data) 47 | 48 | def decode_config(data): 49 | data = data[-0x208:] 50 | return decode(data) 51 | 52 | def decode_b64(data): 53 | data = data.strip('\n') 54 | data = data.replace('.', '+') 55 | data = base64.b64decode(data) 56 | out = decode(data) 57 | return out 58 | 59 | 60 | def decode_network(url): 61 | uri_info = urlparse(url) 62 | uri = os.path.basename(uri_info.path) 63 | req = requests.get(url) 64 | data = req.text 65 | info = uri.split('_') 66 | user_info = base64.b64decode(info[0]).split('_') 67 | 68 | print "computer name: %s" % user_info[0] 69 | print "username: %s" % user_info[1] 70 | print "last modified (headers): %s" % req.headers['last-modified'] 71 | print "-"*32 72 | lines = data.split('\n') 73 | for l in lines: 74 | tag = "ABCDEFGHIJKLMNOP" 75 | tag = l[:len(tag)] 76 | counter = l[len(tag):20] 77 | data = l[len(tag)+20:] 78 | out = decode_b64(data) 79 | print out 80 | 81 | if __name__ == "__main__": 82 | parser = argparse.ArgumentParser(description='Chinese decoder.') 83 | 84 | #parser.add_argument('filename', type=argparse.FileType(), 85 | #help='file to extract resource') 86 | parser.add_argument('filename', type=str, 87 | help='file to extract resource') 88 | 89 | parser.add_argument('-e', action='store_const', const='exe', 90 | dest='action', help='extract all resource of the dll (default)') 91 | parser.add_argument('-d', action='store_const', const='file', 92 | dest='action', help='decode encrypted file like .ini') 93 | parser.add_argument('-c', action='store_const', const='config', 94 | dest='action', help='extract config of the dll') 95 | parser.add_argument('-b', action='store_const', const='b64', 96 | dest='action', help='decode network b64') 97 | parser.add_argument('-n', action='store_const', const='network', 98 | dest='action', help='decode network') 99 | 100 | args = parser.parse_args() 101 | 102 | 103 | if args.action == 'network': 104 | decode_network(args.filename) 105 | sys.exit(1) 106 | 107 | 108 | fp = open(args.filename) 109 | #fp = args.filename 110 | data = fp.read() 111 | 112 | 113 | if args.action == 'file': 114 | out = decode_file(data) 115 | filename = "%s.dec" % fp.name 116 | print "write decoded file in %s (%s)" % \ 117 | (filename, get_magic(out)) 118 | open(filename, 'w').write(out) 119 | elif args.action == 'config': 120 | out = decode_config(data) 121 | print out 122 | filename = "%s.dec" % fp.name 123 | #print "write decoded file in %s (%s)" % \ 124 | #(filename, get_magic(out)) 125 | #open(filename, 'w').write(out) 126 | elif args.action == 'b64': 127 | out = decode_b64(data) 128 | print out 129 | filename = "%s.dec" % fp.name 130 | #print "write decoded file in %s (%s)" % \ 131 | #(filename, get_magic(out)) 132 | #open(filename, 'w').write(out) 133 | else: 134 | magictag = "\x7e\x21\x40\x23\x24\x25\x5e\x26" 135 | i = 0 136 | while True: 137 | try: 138 | out = extract_res(magictag, data, i) 139 | filename = "%s.%d.dec" % (fp.name, i) 140 | print "write decoded file in %s (%s)" % \ 141 | (filename, get_magic(out)) 142 | open(filename, 'w').write(out) 143 | i += 1 144 | except Exception, e: 145 | #print e 146 | break 147 | 148 | -------------------------------------------------------------------------------- /xtremerat_config.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # xtremerat_config.py 3 | # _ _ 4 | # _ __ ___ __ _| |_ ____ _ _ __ ___ | |_ _ 5 | # | '_ ` _ \ / _` | \ \ /\ / / _` | '__/ _ \ | | | | | 6 | # | | | | | | (_| | |\ V V / (_| | | | __/_| | |_| | 7 | # |_| |_| |_|\__,_|_| \_/\_/ \__,_|_| \___(_)_|\__,_| 8 | 9 | import pefile, os, sys, argparse 10 | from struct import pack, unpack 11 | 12 | version = "0.1" 13 | def_rat_version = "v3.5" 14 | 15 | # need to be finish 16 | st = { 17 | 'v3.5' : { 18 | 'port' : {'pos':0, 'len':4, 'format': 'unpack("