Flare-On 4 Challenge #12 plugins implemented in python
################################################################################ | |
# quick hack for using aplib (http://www.ibsensoftware.com/products_aPLib.html) | |
# put aplib.dll in %PATH% or same dir as this script | |
# on *nix it might require LD_LIBRARY_PATH set depending on where libaplib.so is | |
import os | |
from ctypes import * | |
################################################################################ | |
__all__ = [ 'pack', 'pack_safe', 'depack', 'depack_safe', 'CB_COMPRESS'] | |
################################################################################ | |
if os.name == 'nt': | |
CB_COMPRESS = WINFUNCTYPE(c_uint, c_uint, c_uint, c_uint, c_void_p) | |
_aplib = windll.aplib | |
else: | |
CB_COMPRESS = CFUNCTYPE(c_uint, c_uint, c_uint, c_uint, c_void_p) | |
# might require LD_LIBRARY_PATH set | |
_aplib = CDLL("libaplib.so") | |
def _ratio(inpos, insize): | |
return (inpos * 100) / insize | |
def _cbCompress(insize, inpos, outpos, cbparam): | |
print "compressed %u -> %u bytes (%u%% done)" % \ | |
( inpos, outpos, _ratio(inpos, insize)) | |
return 1 | |
_cbCompressFunc = CB_COMPRESS(_cbCompress) | |
################################################################################ | |
def pack(src, cb=None): | |
srclen = len(src) | |
if srclen <= 0: | |
raise ValueError('Invalid input.') | |
dstlen = _aplib.aP_max_packed_size(srclen) | |
dst = create_string_buffer(dstlen) | |
wrkmem = create_string_buffer(_aplib.aP_workmem_size(srclen)) | |
dstlen = _aplib.aP_pack(src, dst, srclen, wrkmem, cb, 0) | |
if dstlen == -1: | |
raise ValueError('Compression error.') | |
return buffer(dst, 0, dstlen) | |
def pack_safe(src, cb=None): | |
srclen = len(src) | |
if srclen <= 0: | |
raise ValueError('Invalid input.') | |
dstlen = _aplib.aP_max_packed_size(srclen) | |
dst = create_string_buffer(dstlen) | |
wrkmem = create_string_buffer(_aplib.aP_workmem_size(srclen)) | |
dstlen = _aplib.aPsafe_pack(src, dst, srclen, wrkmem, cb, 0) | |
if dstlen == -1: | |
raise ValueError('Compression error.') | |
return buffer(dst, 0, dstlen) | |
################################################################################ | |
def depack(src, dstlen): | |
srclen = len(src) | |
if srclen <= 0 or dstlen <= 0: | |
raise ValueError('Invalid input.') | |
dst = create_string_buffer(dstlen) | |
dstlen = _aplib.aP_depack_asm_safe(src, srclen, dst, dstlen) | |
if dstlen == -1: | |
raise ValueError('Decompression error.') | |
return buffer(dst, 0, dstlen) | |
def depack_safe(src): | |
srclen = len(src) | |
if srclen <= 0: | |
raise ValueError('Invalid input.') | |
dstlen = _aplib.aPsafe_get_orig_size(src) | |
dst = create_string_buffer(dstlen) | |
dstlen = _aplib.aPsafe_depack(src, srclen, dst, dstlen) | |
if dstlen == -1: | |
raise ValueError('Decompression error.') | |
return buffer(dst, 0, dstlen) | |
################################################################################ | |
if __name__ == "__main__": | |
import optparse | |
parser = optparse.OptionParser( | |
usage='%prog [-h] [-v] -m c|d infile outfile' | |
) | |
parser.add_option( | |
'-m', '--mode', | |
action="store", | |
type="string", | |
dest='mode', | |
help='c for compress, d for decompress') | |
parser.add_option( | |
'-v', '--verbose', | |
action="store_true", | |
dest='verbose') | |
options, args = parser.parse_args() | |
if not options.mode in ['c', 'd']: | |
parser.error('You must give a valid --mode') | |
if not len(args) == 2: | |
parser.error('You must give in- and outfile') | |
infile = args[0] | |
outfile = args[1] | |
src = open(infile, 'rb').read() | |
if options.mode == 'c': | |
print "Compressing '%s' to '%s'" % (infile, outfile) | |
if options.verbose: | |
dst = pack_safe(src, _cbCompressFunc) | |
else: | |
dst = pack_safe(src) | |
open(outfile, 'wb').write(dst) | |
print "Compressed '%s' from %u to %u bytes (%u%%)" \ | |
% (infile, len(src), len(dst), _ratio(len(dst), len(src))) | |
elif options.mode == 'd': | |
print "Decompressing '%s' to '%s'" % (infile, outfile) | |
dst = depack_safe(src) | |
open(outfile, 'wb').write(dst) | |
print "Decompressed '%s' from %u to %u bytes (%u%%)" \ | |
% (infile, len(src), len(dst), _ratio(len(dst), len(src))) | |
################################################################################ |
import sys | |
import struct | |
import cStringIO | |
import traceback | |
import plugin_rc4 | |
import plugin_transp | |
import plugin_base64 | |
import plugin_xtea | |
import plugin_zlib | |
import plugin_bfish | |
import plugin_xor | |
import plugin_des | |
import plugin_camelia | |
import plugin_aplib | |
PLUGIN_RC4_SIGN = '\xC3\x0B\x1A\x2D\xCB\x48\x9C\xA8\xA7\x24\x37\x64\x69\xCF\x67\x82' | |
PLUGIN_TRANSP_SIGN = '\x38\xBE\x0F\x62\x4C\xE2\x74\xFC\x61\xF7\x5C\x90\xCB\x3F\x59\x15' | |
PLUGIN_BASE64_SIGN = '\xBA\x05\x04\xFC\xC0\x8F\x91\x21\xD1\x6F\xD3\xFE\xD1\x71\x0E\x60' | |
PLUGIN_XTEA_SIGN = '\xB2\xE5\x49\x0D\x26\x54\x05\x9B\xBB\xAB\x7F\x2A\x67\xFE\x5F\xF4' | |
PLUGIN_ZLIB_SIGN = '\x5F\xD8\xEA\x0E\x9D\x0A\x92\xCB\xE4\x25\x10\x96\x90\xCE\x7D\xA2' | |
PLUGIN_CMD1_SIGN = '\xF4\x7C\x51\x07\x0F\xA8\x69\x80\x64\xB6\x5B\x3B\x6E\x7D\x30\xC6' | |
PLUGIN_CMD2_SIGN = '\xF4\x6D\x09\x70\x4B\x40\x27\x5F\xB3\x37\x90\xA3\x62\x76\x2E\x56' | |
PLUGIN_CMD3_SIGN = '\xA3\xAE\xCC\xA1\xCB\x4F\xAA\x7A\x9A\x59\x4D\x13\x8A\x1B\xFB\xD5' | |
PLUGIN_CMD4_SIGN = '\x77\xD6\xCE\x92\x34\x73\x37\xAE\xB1\x45\x10\x80\x7E\xE9\xD7\xBE' | |
PLUGIN_MAIN1_SIGN = '\xF3\x71\x26\xAD\x88\xA5\x61\x7E\xAF\x06\x00\x0D\x42\x4C\x5A\x21' | |
PLUGIN_MAIN2_SIGN = '\x15\x5B\xBF\x4A\x1E\xFE\x15\x17\x73\x46\x04\xB9\xD4\x2B\x80\xE8' | |
PLUGIN_MAIN3_SIGN = '\x51\x29\x8F\x74\x16\x67\xD7\xED\x29\x41\x95\x01\x06\xF5\x05\x45' | |
PLUGIN_BFISH_SIGN = '\x29\x65\xE4\xA1\x9B\x6E\x9D\x94\x73\xF5\xF5\x4D\xFE\xF9\x35\x33' | |
PLUGIN_XOR_SIGN = '\x87\x46\xE7\xB7\xB0\xC1\xB9\xCF\x3F\x11\xEC\xAE\x78\xA3\xA4\xBC' | |
PLUGIN_DES_SIGN = '\x46\xC5\x52\x59\x04\xF4\x73\xAC\xE7\xBB\x8C\xB5\x8B\x29\x96\x8A' | |
PLUGIN_CAMELIA_SIGN = '\x9B\x1F\x6E\xC7\xD9\xB4\x2B\xF7\x75\x8A\x09\x4A\x21\x86\x98\x6B' | |
PLUGIN_APLIB_SIGN = '\x50\x3B\x64\x12\xC7\x5A\x7C\x75\x58\xD1\xC9\x26\x83\x22\x54\x49' | |
PLUGIN_CMD5_SIGN = '\x0A\x78\x74\xD2\x47\x8A\x77\x13\x70\x5E\x13\xDD\x9B\x31\xA6\xB1' | |
PLUGIN_CMD6_SIGN = '\xA3\xAE\xCC\xA1\xCB\x4F\xAA\x7A\x9A\x59\x4D\x13\x8A\x1B\xFB\xD5' | |
PLUGIN_CMD7_SIGN = '\xF4\x7C\x51\x07\x0F\xA8\x69\x80\x64\xB6\x5B\x3B\x6E\x7D\x30\xC6' | |
PLUGIN_CMD8_SIGN = '\xF4\x6D\x09\x70\x4B\x40\x27\x5F\xB3\x37\x90\xA3\x62\x76\x2E\x56' | |
ALL_SIGNS = (PLUGIN_RC4_SIGN, PLUGIN_TRANSP_SIGN, PLUGIN_BASE64_SIGN, PLUGIN_XTEA_SIGN, | |
PLUGIN_ZLIB_SIGN, PLUGIN_CMD1_SIGN, PLUGIN_CMD2_SIGN, PLUGIN_CMD3_SIGN, PLUGIN_CMD4_SIGN, | |
PLUGIN_MAIN1_SIGN, PLUGIN_MAIN2_SIGN, PLUGIN_MAIN3_SIGN, PLUGIN_BFISH_SIGN, | |
PLUGIN_XOR_SIGN, PLUGIN_DES_SIGN, PLUGIN_CAMELIA_SIGN, PLUGIN_APLIB_SIGN, | |
PLUGIN_CMD5_SIGN, PLUGIN_CMD6_SIGN, PLUGIN_CMD7_SIGN, PLUGIN_CMD8_SIGN | |
) | |
def process_header(inf, outf): | |
assert inf.read(4) == '2017' | |
crc = struct.unpack('<I', inf.read(4))[0] | |
header_len = struct.unpack('<I', inf.read(4))[0] | |
msg_before_len = struct.unpack('<I', inf.read(4))[0] | |
msg_after_len = struct.unpack('<I', inf.read(4))[0] | |
plug_sign = inf.read(16) | |
assert plug_sign in ALL_SIGNS | |
if plug_sign == PLUGIN_RC4_SIGN: | |
key = inf.read(16) | |
outf.write(plugin_rc4.decrypt(key, inf.read(msg_before_len))) | |
elif plug_sign == PLUGIN_TRANSP_SIGN: | |
outf.write(plugin_transp.decrypt(inf.read(msg_before_len))) | |
elif plug_sign == PLUGIN_BASE64_SIGN: | |
outf.write(plugin_base64.decrypt(inf.read(msg_before_len))) | |
elif plug_sign == PLUGIN_XTEA_SIGN: | |
key = inf.read(16) | |
iv = inf.read(8) | |
outf.write(plugin_xtea.decrypt(key, iv, inf.read(msg_before_len))) | |
elif plug_sign == PLUGIN_ZLIB_SIGN: | |
outf.write(plugin_zlib.decrypt(inf.read(msg_before_len))) | |
elif plug_sign == PLUGIN_BFISH_SIGN: | |
key = inf.read(16) | |
iv = inf.read(8) | |
outf.write(plugin_bfish.decrypt(key, iv, inf.read(msg_before_len))) | |
elif plug_sign == PLUGIN_XOR_SIGN: | |
key = inf.read(4) | |
outf.write(plugin_xor.decrypt(key, inf.read(msg_before_len))) | |
elif plug_sign == PLUGIN_DES_SIGN: | |
key = inf.read(24) | |
iv = inf.read(8) | |
outf.write(plugin_des.decrypt(key, iv, inf.read(msg_before_len))) | |
elif plug_sign == PLUGIN_CAMELIA_SIGN: | |
key = inf.read(16) | |
outf.write(plugin_camelia.decrypt(key, inf.read(msg_before_len))) | |
elif plug_sign == PLUGIN_APLIB_SIGN: | |
outf.write(plugin_aplib.decrypt(inf.read(msg_before_len))) | |
else: | |
outf.write(inf.read(msg_before_len)) | |
def process_msg(inf, outf): | |
msg_header_len = struct.unpack('<I', inf.read(4))[0] | |
msg_before_len = struct.unpack('<I', inf.read(4))[0] | |
msg_after_len = struct.unpack('<I', inf.read(4))[0] | |
plug_sign = inf.read(16) | |
assert plug_sign in ALL_SIGNS | |
if plug_sign == PLUGIN_RC4_SIGN: | |
key = inf.read(16) | |
outf.write(plugin_rc4.decrypt(key, inf.read(msg_before_len))) | |
elif plug_sign == PLUGIN_TRANSP_SIGN: | |
outf.write(plugin_transp.decrypt(inf.read(msg_before_len))) | |
elif plug_sign == PLUGIN_BASE64_SIGN: | |
outf.write(plugin_base64.decrypt(inf.read(msg_before_len))) | |
elif plug_sign == PLUGIN_XTEA_SIGN: | |
key = inf.read(16) | |
iv = inf.read(8) | |
outf.write(plugin_xtea.decrypt(key, iv, inf.read(msg_before_len))) | |
elif plug_sign == PLUGIN_ZLIB_SIGN: | |
outf.write(plugin_zlib.decrypt(inf.read(msg_before_len))) | |
elif plug_sign == PLUGIN_BFISH_SIGN: | |
key = inf.read(16) | |
iv = inf.read(8) | |
outf.write(plugin_bfish.decrypt(key, iv, inf.read(msg_before_len))) | |
elif plug_sign == PLUGIN_XOR_SIGN: | |
key = inf.read(4) | |
outf.write(plugin_xor.decrypt(key, inf.read(msg_before_len))) | |
elif plug_sign == PLUGIN_DES_SIGN: | |
key = inf.read(24) | |
iv = inf.read(8) | |
outf.write(plugin_des.decrypt(key, iv, inf.read(msg_before_len))) | |
elif plug_sign == PLUGIN_CAMELIA_SIGN: | |
key = inf.read(16) | |
outf.write(plugin_camelia.decrypt(key, inf.read(msg_before_len))) | |
elif plug_sign == PLUGIN_APLIB_SIGN: | |
outf.write(plugin_aplib.decrypt(inf.read(msg_before_len))) | |
else: | |
outf.write(inf.read(msg_before_len)) | |
def process(inf, outf): | |
t = cStringIO.StringIO() | |
process_header(inf, t) | |
t.seek(0) | |
process_msg(t, outf) | |
def main(ipath, opath): | |
inf = cStringIO.StringIO(open(ipath, 'rb').read()) | |
t = cStringIO.StringIO() | |
process(inf, t) | |
v = t.getvalue() | |
if v[20:20+16] == PLUGIN_CMD4_SIGN: | |
print ipath | |
open(opath, 'wb').write(v) | |
if __name__ == '__main__': | |
filename = sys.argv[1] | |
main(filename, filename + '_d') |
import aplib | |
def decrypt(buf): | |
return aplib.depack_safe(buf) |
import base64 | |
import string | |
stan_base64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' | |
cust_base64 = 'B7wAOjbXLsD+S24/tcgHYqFRdVKTp0ixlGIMCf8zvE5eoN1uyU93Wm6rZPQaJhkn' | |
table = string.maketrans(cust_base64, stan_base64) | |
def decrypt(buf): | |
s = buf.translate(table) | |
return base64.b64decode(s) |
from Crypto.Cipher import Blowfish | |
def decrypt(key, iv, buf): | |
bf = Blowfish.new(key, Blowfish.MODE_CBC, iv = iv) | |
return bf.decrypt(buf) |
import camellia | |
def decrypt(key, buf): | |
c = camellia.CamelliaCipher(key, mode=camellia.MODE_ECB) | |
return c.decrypt(buf) | |
from Crypto.Cipher import DES3 | |
def decrypt(key, iv, buf): | |
bf = DES3.new(key, DES3.MODE_CBC, iv = iv) | |
return bf.decrypt(buf) |
from Crypto.Cipher import ARC4 | |
def decrypt(key, buf): | |
arc4 = ARC4.new(key) | |
return arc4.decrypt(buf) |
table = [199, 25, 48, 12, 168, 16, 173, 213, 212, 22, | |
82, 252, 27, 130, 125, 50, 52, 1, 230, 76, 18, 8, 43, | |
247, 172, 139, 63, 103, 72, 114, 33, 220, 237, 246, | |
133, 184, 79, 95, 83, 10, 4, 40, 223, 216, 126, 6, 61, | |
3, 64, 54, 104, 115, 37, 183, 93, 30, 210, 13, 198, 195, | |
34, 242, 32, 14, 23, 204, 96, 92, 81, 194, 29, 74, 203, | |
51, 28, 248, 102, 131, 107, 62, 39, 227, 159, 245, 58, | |
170, 138, 38, 127, 90, 66, 207, 124, 7, 88, 113, 235, | |
5, 186, 41, 75, 122, 224, 236, 154, 123, 46, 55, 254, | |
164, 190, 73, 222, 0, 197, 187, 150, 233, 196, 121, | |
153, 135, 244, 19, 26, 21, 99, 249, 160, 209, 2, 214, | |
9, 31, 229, 146, 106, 231, 24, 67, 145, 110, 65, 200, | |
163, 178, 44, 238, 141, 166, 91, 239, 36, 185, 117, 87, | |
15, 111, 17, 71, 155, 59, 118, 225, 157, 100, 84, 167, | |
193, 85, 179, 137, 49, 253, 171, 177, 148, 182, 20, 47, | |
243, 188, 105, 191, 161, 128, 89, 11, 189, 201, 42, 215, | |
129, 60, 35, 211, 241, 250, 234, 57, 56, 158, 94, 181, | |
69, 97, 255, 78, 119, 77, 101, 156, 232, 217, 147, 175, | |
80, 162, 132, 136, 120, 152, 226, 134, 206, 221, 140, | |
142, 169, 149, 112, 174, 228, 202, 98, 205, 144, 192, | |
251, 176, 219, 180, 208, 151, 240, 45, 70, 218, 108, | |
109, 68, 116, 165, 143, 86, 53] | |
def decrypt(buf): | |
b = map(ord, buf) | |
return ''.join([chr(table[c]) for c in b]) | |
import struct | |
import cStringIO | |
def decrypt(key, buf): | |
k = struct.unpack('<I', key)[0] | |
pt = cStringIO.StringIO() | |
assert len(buf) % 4 == 0 | |
for i in xrange(len(buf) / 4): | |
ct = struct.unpack('<I', buf[i*4:(i*4)+4])[0] | |
pt.write(struct.pack('<I', ct ^ k)) | |
v = pt.getvalue() | |
pt.close() | |
return v | |
import xtea | |
def decrypt(key, iv, buf): | |
x = xtea.new(key, mode = xtea.MODE_CBC, IV = iv) | |
return x.decrypt(buf) |
import zlib | |
def decrypt(buf): | |
return zlib.decompress(buf) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment