Skip to content

Instantly share code, notes, and snippets.

@extremecoders-re
Last active November 3, 2017 07:56
Show Gist options
  • Save extremecoders-re/b7caf1a5d2f884733a75dcdc80d8e384 to your computer and use it in GitHub Desktop.
Save extremecoders-re/b7caf1a5d2f884733a75dcdc80d8e384 to your computer and use it in GitHub Desktop.
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