-
-
Save hugsy/9b141827b66843ebbabc183731649f53 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
from ctypes import * | |
__all__ = [ 'depack', ] | |
_aplib = CDLL("/home/hugsy/ctf/flareon_2017/12/level12/libaplib.so") | |
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) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import zlib | |
import struct | |
import copy | |
import os | |
import sys | |
import subprocess | |
from ctypes import * | |
from hexdump import hexdump | |
from Crypto.Cipher import Blowfish | |
from Crypto.Cipher import DES3 | |
import camellia | |
import aplib | |
import lzo | |
def from_utf16(msg): | |
return msg#.decode('utf16') | |
def p32(x, endianness="little"): | |
if endianness=="big": | |
return struct.pack("!I",x) | |
return struct.pack("<I",x) | |
def u32(x, endianness="little"): | |
if endianness=="big": | |
return struct.unpack("!I",x)[0] | |
return struct.unpack("<I",x)[0] | |
# secondstage | |
magic_exe_value = "155BBF4A1EFE1517734604B9D42B80E8".decode('hex') | |
magic_exe_cmd = "F37126AD88A5617EAF06000D424C5A21".decode('hex') | |
magic_exe = "51298F741667D7ED2941950106F50545".decode('hex') | |
string_delim_utf = "F47C51070FA8698064B65B3B6E7D30C6".decode('hex') | |
string_delim_ascii = "F46D09704B40275FB33790A362762E56".decode('hex') | |
plugin_types = [ | |
"CMD", # send and receive commands | |
"COMP", # compression | |
"CRPT", # crypto | |
] | |
current_magic = None | |
# | |
# secondstage-lm-1.exe (r.dll) | |
# rc4 | |
magic_r_dll = "C30B1A2DCB489CA8A724376469CF6782".decode('hex') | |
def swap_byte(buf1, i1, buf2, i2): | |
temp1 = buf1[i1] | |
temp2 = buf2[i2] | |
buf1[i1] = temp2 | |
buf2[i2] = temp1 | |
return | |
def swap_bytes_1(msg): | |
buf = bytearray() | |
for _ in range(256): buf.append(_) | |
buf.append(0) | |
buf.append(0) | |
v6 = 0 | |
msg = bytearray(msg) | |
for j in range(256): | |
v6 = (v6 + msg[j % len(msg)] + buf[j]) & 0xff | |
swap_byte(buf, j, buf, v6) | |
return str(buf) | |
def swap_bytes_2(a1, a2): | |
a1 = bytearray(a1) | |
a2 = bytearray(a2) | |
a3 = bytearray() | |
for _ in range( len(a2) ): | |
a3.append(0) | |
for i in range( len(a2) ): | |
a1[256] = (a1[256] + 1) & 0xffL | |
a1[257] = (a1[257] + a1[ a1[256] ]) & 0xffL | |
swap_byte(a1, a1[256], a1, a1[257]) | |
c = (a1[a1[257]] + a1[a1[256]]) & 0xff | |
a3[i] = a1[c] ^ a2[i] | |
return str(a3) | |
# | |
# secondstage-lm-2.exe (t.dll) | |
# shuffle | |
magic_t_dll = "38BE0F624CE274FC61F75C90CB3F5915".decode('hex') | |
def unshuffle(msg): | |
shuffled_bytes = [ | |
0x0C7, 0x19, 0x30, 0x0C, 0x0A8, 0x10, 0x0AD, 0x0D5, 0x0D4, 0x16, | |
0x52, 0x0FC, 0x1B, 0x82, 0x7D, 0x32, 0x34, 0x1, 0x0E6, 0x4C, 0x12, | |
0x8, 0x2B, 0x0F7, 0x0AC, 0x8B, 0x3F, 0x67, 0x48, 0x72, 0x21, 0x0DC, | |
0x0ED, 0x0F6, 0x85, 0x0B8, 0x4F, 0x5F, 0x53, 0x0A, 0x4, 0x28, 0x0DF, | |
0x0D8, 0x7E, 0x6, 0x3D, 0x3, 0x40, 0x36, 0x68, 0x73, 0x25, 0x0B7, | |
0x5D, 0x1E, 0x0D2, 0x0D, 0x0C6, 0x0C3, 0x22, 0x0F2, 0x20, 0x0E, | |
0x17, 0x0CC, 0x60, 0x5C, 0x51, 0x0C2, 0x1D, 0x4A, 0x0CB, 0x33, | |
0x1C, 0x0F8, 0x66, 0x83, 0x6B, 0x3E, 0x27, 0x0E3, 0x9F, 0x0F5, | |
0x3A, 0x0AA, 0x8A, 0x26, 0x7F, 0x5A, 0x42, 0x0CF, 0x7C, 0x7, 0x58, | |
0x71, 0x0EB, 0x5, 0x0BA, 0x29, 0x4B, 0x7A, 0x0E0, 0x0EC, 0x9A, | |
0x7B, 0x2E, 0x37, 0x0FE, 0x0A4, 0x0BE, 0x49, 0x0DE, 0x0, 0x0C5, | |
0x0BB, 0x96, 0x0E9, 0x0C4, 0x79, 0x99, 0x87, 0x0F4, 0x13, 0x1A, | |
0x15, 0x63, 0x0F9, 0x0A0, 0x0D1, 0x2, 0x0D6, 0x9, 0x1F, 0x0E5, 0x92, | |
0x6A, 0x0E7, 0x18, 0x43, 0x91, 0x6E, 0x41, 0x0C8, 0x0A3, 0x0B2, | |
0x2C, 0x0EE, 0x8D, 0x0A6, 0x5B, 0x0EF, 0x24, 0x0B9, 0x75, 0x57, | |
0x0F, 0x6F, 0x11, 0x47, 0x9B, 0x3B, 0x76, 0x0E1, 0x9D, 0x64, 0x54, | |
0x0A7, 0x0C1, 0x55, 0x0B3, 0x89, 0x31, 0x0FD, 0x0AB, 0x0B1, 0x94, | |
0x0B6, 0x14, 0x2F, 0x0F3, 0x0BC, 0x69, 0x0BF, 0x0A1, 0x80, 0x59, | |
0x0B, 0x0BD, 0x0C9, 0x2A, 0x0D7, 0x81, 0x3C, 0x23, 0x0D3, 0x0F1, | |
0x0FA, 0x0EA, 0x39, 0x38, 0x9E, 0x5E, 0x0B5, 0x45, 0x61, 0x0FF, | |
0x4E, 0x77, 0x4D, 0x65, 0x9C, 0x0E8, 0x0D9, 0x93, 0x0AF, 0x50, | |
0x0A2, 0x84, 0x88, 0x78, 0x98, 0x0E2, 0x86, 0x0CE, 0x0DD, 0x8C, | |
0x8E, 0x0A9, 0x95, 0x70, 0x0AE, 0x0E4, 0x0CA, 0x62, 0x0CD, 0x90, | |
0x0C0, 0x0FB, 0x0B0, 0x0DB, 0x0B4, 0x0D0, 0x97, 0x0F0, 0x2D, | |
0x46, 0x0DA, 0x6C, 0x6D, 0x44, 0x74, 0x0A5, 0x8F, 0x56, 0x35, | |
] | |
res = bytearray() | |
for c in bytearray(msg): | |
res.append(shuffled_bytes[c]) | |
return str(res) | |
assert unshuffle("Jqqq") == p32(0x1c) | |
# | |
# secondstage-lm-3.exe (6.dll) | |
# base64 | |
magic_6_dll = "BA0504FCC08F9121D16FD3FED1710E60".decode('hex') | |
def tobase64(s, padd = False): | |
b64s = "B7wAOjbXLsD+S24/tcgHYqFRdVKTp0ixlGIMCf8zvE5eoN1uyU93Wm6rZPQaJhkn" | |
b64p = "=" | |
ret = "" | |
left = 0 | |
for i in range(0, len(s)): | |
if left == 0: | |
ret += b64s[ord(s[i]) >> 2] | |
left = 2 | |
else: | |
if left == 6: | |
ret += b64s[ord(s[i - 1]) & 63] | |
ret += b64s[ord(s[i]) >> 2] | |
left = 2 | |
else: | |
index1 = ord(s[i - 1]) & (2 ** left - 1) | |
index2 = ord(s[i]) >> (left + 2) | |
index = (index1 << (6 - left)) | index2 | |
ret += b64s[index] | |
left += 2 | |
if left != 0: | |
ret += b64s[(ord(s[len(s) - 1]) & (2 ** left - 1)) << (6 - left)] | |
if(padd): | |
for i in range(0, (4 - len(ret) % 4) % 4): | |
ret += b64p | |
return ret | |
def frombase64(s): | |
b64s = "B7wAOjbXLsD+S24/tcgHYqFRdVKTp0ixlGIMCf8zvE5eoN1uyU93Wm6rZPQaJhkn" | |
b64p = "=" | |
ret = "" | |
s2 = s.replace(b64p, "") | |
left = 0 | |
for i in range(0, len(s2)): | |
if left == 0: | |
left = 6 | |
else: | |
value1 = b64s.index(s2[i - 1]) & (2 ** left - 1) | |
value2 = b64s.index(s2[i]) >> (left - 2) | |
value = (value1 << (8 - left)) | value2 | |
ret += chr(value) | |
left -= 2 | |
return ret | |
assert frombase64("XBBBBB") == p32(0x1c) | |
# | |
# secondstage-lm-4.exe (x.dll) | |
# xtea | |
magic_x_dll = "B2E5490D2654059BBBAB7F2A67FE5FF4".decode('hex') | |
def _xtea_decrypt(block, key): | |
v11 = u32(block[0:4], endianness="big") | |
v10 = u32(block[4:8], endianness="big") | |
k = [ u32(key[i:i+4]) for i in range(0, len(key), 4) ] | |
iv = 0x9E3779B9L | |
m = 0xffffffffL | |
delta = (iv << 5) & m | |
for _ in range(32): | |
edx = (v11 << 4) & m | |
eax = (v11 >> 5) & m | |
edx = edx ^ eax | |
edx = (edx + v11) & m | |
ecx = ((delta >> 11) & m) & 3 | |
esi = delta + k[ecx] | |
edx = edx ^ esi | |
ecx = (v10 - edx) & m | |
v10 = ecx | |
delta = (delta - iv) & m | |
eax = (v10 << 4) & m | |
ecx = (v10 >> 5) & m | |
eax = eax ^ ecx | |
eax = (eax + v10) & m | |
edx = delta & 3 | |
esi = (delta + k[edx]) & m | |
eax = eax ^ esi | |
edx = (v11 - eax) & m | |
v11 = edx | |
return p32(v11, endianness="big") + p32(v10, endianness="big") | |
key = "0e7af86bd6235b5d10ac6a883d33a407".decode('hex') | |
text = "91471302dd5a7fd5".decode('hex') | |
result = "c821cbd2444ce75c".decode('hex') | |
assert _xtea_decrypt(text, key) == result, _xtea_decrypt(text, key).encode('hex') + " != " + result.encode('hex') | |
def xtea_decrypt(buf, key, iv): | |
assert len(buf) % 8 == 0 | |
dec = bytearray() | |
for i in range(0, len(buf), 8): | |
block = buf[i:i+8] | |
temp = copy.deepcopy(block) | |
res = _xtea_decrypt(block, key) | |
for j in range(8): | |
dec.append( ord(res[j]) ^ ord(iv[j]) ) | |
iv = temp | |
return str(dec) | |
# | |
# secondstage-lm-5.exe (z.dll) | |
# zlib | |
magic_z_dll = "5FD8EA0E9D0A92CBE425109690CE7DA2".decode('hex') | |
def inflate(x): | |
return zlib.decompressobj().decompress(x) | |
# secondstage-lm-6.exe (f.dll) | |
# sha1 | |
magic_f_dll = "F47C51070FA8698064B65B3B6E7D30C6".decode('hex') | |
# secondstage-lm-7.exe (s.dll) | |
# send/receive commands to cmd.exe | |
magic_s_dll = "F46D09704B40275FB33790A362762E56".decode('hex') | |
# secondstage-lm-8.exe (m.dll) | |
# screen capture | |
magic_m_dll = "A3AECCA1CB4FAA7A9A594D138A1BFBD5".decode('hex') | |
# p.dll | |
# proxy | |
magic_p_dll = "77D6CE92347337AEB14510807EE9D7BE".decode('hex') | |
# srv2-1.dll | |
# blowfish | |
magic_b_dll = "2965E4A19B6E9D9473F5F54DFEF93533".decode('hex') | |
def blowfish_decrypt(key, ciphertext, iv): | |
bs = Blowfish.block_size | |
if len(ciphertext) % 8 != 0: | |
ciphertext += '\x00' * (8- (len(ciphertext) % 8)) | |
cipher = Blowfish.new(key, Blowfish.MODE_CBC, iv) | |
plaintext = cipher.decrypt(ciphertext) | |
return plaintext | |
# srv2-2.dll | |
magic_e_dll = "8746E7B7B0C1B9CF3F11ECAE78A3A4BC".decode('hex') | |
def e_decrypt(iv, ciphertext): | |
plaintext = bytearray() | |
iv = u32(iv) | |
bs = 4 | |
if len(ciphertext) % bs != 0: | |
ciphertext += '\x00' * (bs - (len(ciphertext) % bs)) | |
for i in range(0, len(ciphertext), bs): | |
b = ciphertext[i:i+4] | |
c = iv ^ u32(b) | |
for b in p32(c): | |
plaintext.append(b) | |
return str(plaintext) | |
# srv2-3.dll | |
# des | |
magic_d_dll = "46C5525904F473ACE7BB8CB58B29968A".decode('hex') | |
def des_decrypt(key, ciphertext, iv): | |
bs = 8 | |
if len(ciphertext) % bs != 0: | |
ciphertext += '\x00' * (bs - (len(ciphertext) % bs)) | |
cipher = DES3.new(key, DES3.MODE_CBC, iv) | |
plaintext = cipher.decrypt(ciphertext) | |
return plaintext | |
# srv2-4.dll | |
# camellia | |
magic_c_dll = "9B1F6EC7D9B42BF7758A094A2186986B".decode('hex') | |
def camellia_decrypt(key, ciphertext): | |
bs = 16 | |
plaintext = "" | |
print("[*] c_dll -> key=%s , len(enc)=%d" % (key.encode('hex'), len(ciphertext))) | |
cipher = camellia.CamelliaCipher(key=key, mode=camellia.MODE_ECB) | |
for i in range(0, len(ciphertext), bs): | |
block = ciphertext[i:i+bs] | |
plaintext+= cipher.decrypt(block) | |
print("[*] c_dll -> len(dec)=%d" % (len(plaintext))) | |
return plaintext | |
# srv2-5.dll | |
# aplib (compression) | |
magic_a_dll = "503B6412C75A7C7558D1C92683225449".decode('hex') | |
def aplib_deflate(hdr, msg, inlen, outlen): | |
assert hdr.startswith("AP32") | |
_,_, len_compressed_data, _, len_decompressed_data, _ = struct.unpack("<IIIIII", hdr) | |
print("[*] a_dll -> len_compressed_data=%d , len(msg)=%d" % (len_compressed_data, len(msg))) | |
msg = msg[:len_compressed_data] | |
res = aplib.depack(msg, outlen+0x2048) | |
print ("[*] a_dll -> outlen=%d , len(msg)=%d" % (inlen, len(res))) | |
return str(res) | |
# srv2-6.dll | |
# | |
magic_l_dll = "0A7874D2478A7713705E13DD9B31A6B1".decode('hex') | |
def l_inflate(msg, inlen, outlen): | |
print ("[*] l_dll -> inlen=%d , len(msg)=%d , outlen=%d" % (inlen, len(msg), outlen)) | |
msg = msg[:inlen] | |
d = lzo.decompress(msg, False, outlen+0x2048) | |
print("[*] l_dll -> outlen=%d , len(res)=%d" % (outlen, len(d))) | |
return str(d) | |
# srv2-7.dll | |
# m.dll -> screenshot stuff | |
magic_cryp = "FFFFFFFFF47C51070FA8698064B65B3B".decode('hex') | |
# | |
# main | |
# | |
magics_lm = [ | |
magic_exe , | |
magic_r_dll , | |
magic_t_dll , | |
magic_6_dll , | |
magic_x_dll , | |
magic_z_dll , | |
magic_f_dll , | |
magic_s_dll , | |
magic_m_dll , | |
magic_p_dll , | |
magic_b_dll , | |
magic_e_dll , | |
magic_d_dll , | |
magic_c_dll , | |
magic_a_dll , | |
magic_l_dll , | |
] | |
magics_lm_str = [ | |
"secondstage" , | |
"rc4_dll" , | |
"magic_t_dll" , | |
"base64_dll" , | |
"xtea_dll" , | |
"zlib_dll" , | |
"magic_f_dll" , | |
"magic_s_dll" , | |
"bitmap_dll" , | |
"proxy_dll" , | |
"blowfish_dll" , | |
"magic_e_dll" , | |
"des_dll" , | |
"camellia_dll" , | |
"aplib_dll" , | |
"l_dll" , | |
] | |
magics_action = [ | |
string_delim_ascii , | |
string_delim_utf , | |
] | |
magics_action_str = [ | |
"string_delim_ascii" , | |
"string_delim_utf" , | |
] | |
buffered = "" | |
proxy_buffered_len = 0 | |
class Packet: | |
def __init__(self, buf): | |
assert len(buf) >= 0x14 | |
assert buf.startswith("2017") | |
q = struct.unpack("<IIIII", buf[:0x14]) | |
self.prefix, self.checksum, self.header_size, self.data_size, self.real_data_size = q | |
self.magic = buf[0x14:0x24] | |
self.header = buf[:self.header_size] | |
self.data = buf[self.header_size: self.header_size + self.data_size] | |
self.buf = buf[:] | |
return | |
def parse(self): | |
return self.parse_with_magic(self.magic, self.data, self.header[8:]) | |
def parse_with_magic(self, magic, data, header): | |
global buffered, proxy_buffered_len, current_magic | |
if data.startswith(p32(0x20170417)): | |
return self.parse_body(data, header) | |
if magic == magic_p_dll: | |
# PROXY | |
print("[*] 'magic_dll' -> writing %d B to proxy" % len(data)) | |
open("/tmp/proxy", "a+b").write(data) | |
return data | |
header_size, before_data_size, after_data_size = struct.unpack("<III", header[:0xc]) | |
print("[*] magic='%s' header_size=0x%x before_data_size=0x%x after_data_size=0x%x" % (magics_lm_str[magics_lm.index(magic)], header_size, before_data_size, after_data_size)) | |
if magic == magic_exe: | |
# EXE | |
hdr_sz, data_sz1, data_sz2 = struct.unpack("<III", data[:0xc]) | |
print("[*] magic_exe -> header_sz=0x%x data_size1=0x%x data_size2=0x%x" % (hdr_sz, data_sz1, data_sz2)) | |
action_magic = data[0xc:0x1c] | |
if action_magic == magic_exe_cmd: # secondstage @ 0404D60 | |
return self.parse_body(data[0x1c:], data[:0x1c]) | |
if action_magic in magics_lm: | |
return self.parse_with_magic(action_magic, data[0x1c:], data[:0x1c]) | |
return data | |
elif magic == magic_t_dll: | |
# CRPT | |
next_data = unshuffle(data) | |
next_header_len = u32(next_data[:4]) | |
next_header = next_data[:next_header_len] | |
next_data = next_data[next_header_len:] | |
next_magic = next_header[0xc:0x1c] | |
return self.parse_with_magic(next_magic, next_data, next_header) | |
elif magic == magic_6_dll: | |
# COMP | |
next_data = frombase64(data[:-1])[:after_data_size] | |
next_header_len = u32(next_data[:4]) | |
next_header = next_data[:next_header_len] | |
next_data = next_data[next_header_len:] | |
next_magic = next_header[0xc:0x1c] | |
return self.parse_with_magic(next_magic, next_data, next_header) | |
elif magic == magic_z_dll: | |
# COMP | |
next_data = inflate(data)[:after_data_size] | |
if next_data.startswith(p32(0x20170417)): | |
return self.parse_body(next_data) | |
next_header_len = u32(next_data[:4]) | |
next_header = next_data[:next_header_len] | |
next_data = next_data[next_header_len:] | |
next_magic = next_header[0xc:0x1c] | |
return self.parse_with_magic(next_magic, next_data, next_header) | |
elif magic == magic_x_dll: # hdrlen = 0x3c | |
# CRPT | |
iv = header[0x2c:0x34] | |
key = header[0x1c:0x2c] | |
key = [ u32(key[i:i+4], endianness="big") for i in range(0, len(key), 4) ] | |
key = ''.join([p32(x) for x in key]) | |
next_data= xtea_decrypt(data, key, iv)[:after_data_size] | |
next_header_len = u32(next_data[:4]) | |
next_header = next_data[:next_header_len] | |
next_data = next_data[next_header_len:] | |
next_magic = next_header[0xc:0x1c] | |
return self.parse_with_magic(next_magic, next_data, next_header) | |
elif magic == magic_r_dll: # hdrlen = 0x34 | |
# CRPT | |
iv = header[0x1c:0x2c] | |
next_data = swap_bytes_2(swap_bytes_1(iv), data) | |
next_header_len = u32(next_data[:4]) | |
next_header = next_data[:next_header_len] | |
next_data = next_data[next_header_len:] | |
next_magic = next_header[0xc:0x1c] | |
return self.parse_with_magic(next_magic, next_data, next_header) | |
elif magic == magic_m_dll: # hdrlen = 0x34 | |
# CMD | |
offset, full_size, chunk_size = struct.unpack("<III", data[:0xc]) | |
return data[0xc:] | |
elif magic == magic_b_dll: # hdrlen = 0x3c | |
# CRPT | |
key=header[0x1c:0x2c] | |
iv =header[0x2c:0x34] | |
next_data = blowfish_decrypt(key, data, iv) | |
if next_data.startswith(p32(0x20170417)): | |
return self.parse_body(next_data) | |
next_header_len = u32(next_data[:4]) | |
next_header = next_data[:next_header_len] | |
next_data = next_data[next_header_len:] | |
next_magic = next_header[0xc:0x1c] | |
return self.parse_with_magic(next_magic, next_data, next_header) | |
elif magic == magic_e_dll: # hdrlen = 0x28 | |
# CRPT | |
iv = header[0x1c:0x20] | |
next_data = e_decrypt(iv, data)[:after_data_size] | |
if next_data.startswith(p32(0x20170417)): | |
return self.parse_body(next_data) | |
next_header_len = u32(next_data[:4]) | |
next_header = next_data[:next_header_len] | |
next_data = next_data[next_header_len:] | |
next_magic = next_header[0xc:0x1c] | |
return self.parse_with_magic(next_magic, next_data, next_header) | |
elif magic == magic_d_dll: # hdrlen = 0x44 | |
# CRPT | |
key=header[0x1c:0x34] | |
iv=header[0x34:0x3c] | |
next_data = des_decrypt(key, data, iv)[:after_data_size] | |
hexdump(next_data[:0x50]) | |
if next_data.startswith(p32(0x20170417)): | |
return self.parse_body(next_data) | |
next_header_len = u32(next_data[:4]) | |
next_header = next_data[:next_header_len] | |
next_data = next_data[next_header_len:] | |
next_magic = next_header[0xc:0x1c] | |
return self.parse_with_magic(next_magic, next_data, next_header) | |
elif magic == magic_c_dll: | |
# CRPT | |
key = header[0x1c:0x2c] | |
next_data=camellia_decrypt(key, data)[:after_data_size] | |
if next_data.startswith(p32(0x20170417)): | |
return self.parse_body(next_data) | |
next_header_len = u32(next_data[:4]) | |
next_header = next_data[:next_header_len] | |
next_data = next_data[next_header_len:] | |
next_magic = next_header[0xc:0x1c] | |
return self.parse_with_magic(next_magic, next_data, next_header) | |
elif magic == magic_a_dll: | |
# CRPT | |
next_data = aplib_deflate(data[:0x18], data[0x18:], before_data_size, after_data_size) | |
if next_data.startswith(p32(0x20170417)): | |
return self.parse_body(next_data) | |
next_header_len = u32(next_data[:4]) | |
next_header = next_data[:next_header_len] | |
next_data = next_data[next_header_len:] | |
next_magic = next_header[0xc:0x1c] | |
return self.parse_with_magic(next_magic, next_data, next_header) | |
elif magic == magic_l_dll: | |
# COMP | |
next_data = l_inflate(data, before_data_size, after_data_size) | |
if next_data.startswith(p32(0x20170417)): | |
return self.parse_body(next_data) | |
next_header_len = u32(next_data[:4]) | |
next_header = next_data[:next_header_len] | |
next_data = next_data[next_header_len:] | |
next_magic = next_header[0xc:0x1c] | |
return self.parse_with_magic(next_magic, next_data, next_header) | |
return data | |
def parse_body(self, data, header=""): | |
arg0, arg1, arg2, arg2 = struct.unpack("<IIII", data[:0x10]) | |
assert arg0 == 0x20170417 | |
print("[*] body -> a1=0x{:x} a2=0x{:x} a3=0x{:x} a4=0x{:x}".format(arg0, arg1, arg2, arg2)) | |
if arg1 == 0xe: | |
print("\t -> auth") | |
i = data[0x10:].find(magic_exe_value) + 0x10 + 0x10 | |
print("[*] Value '%s'" % from_utf16(data[i:])) | |
elif arg1 == 0x2: | |
i = data[0x10:].find(string_delim_utf) | |
if i > -1: | |
print("[*] utf_string -> Value '%s'" % from_utf16(data[i+0x10+0x10:])) | |
elif arg1 == 0x3: | |
m = data[0x14:0x24] | |
if m in magics_lm: | |
return self.parse_with_magic(m, data[0x24:], data[:0x24]) | |
i = data[0x10:].find(string_delim_ascii) | |
if i > -1: | |
print("[*] ascii_string -> Value '%s'" % from_utf16(data[i+0x10+0x10:])) | |
elif arg1 == 0x4: | |
m = data[0x10:0x20] | |
if m == magic_cryp: | |
body = data[0x34:] | |
offset, _, filesize, _, blocksize, _ = struct.unpack("<IIIIII", body[:24]) | |
if len(data[0x18:]) < blocksize: | |
print("[*] writing %d to proxy" % (len(data[0x18:],))) | |
open("/tmp/proxy", "a+b").write(self.buf) | |
else: | |
fname = "g/crypfile-%.8x-%.8x" % (offset, blocksize) | |
print("[!] writing `%s` (len=%d off=%d filesize=%d len(msg)=%d)" % (fname, blocksize, offset, filesize, len(body[0x18:]))) | |
open(fname, "wb").write(body[0x18:]) | |
elif arg1 == 0x5: | |
print("[*] register_plugin") | |
elif arg1 == 0x6: | |
print("[*] recv_plugin") | |
elif arg1 == 0x7: | |
print("[*] run_plugin_function") | |
return data | |
def populate_directory_with_packets(fname, to_dir): | |
with open(fname) as fd: | |
i = 0 | |
while True: | |
hdr = fd.read(0x14) | |
if not hdr: | |
break | |
pkt = Packet(hdr) | |
hdr += fd.read(pkt.header_size - 0x14) | |
data = fd.read(pkt.data_size) | |
open("%s/pkt-%d" % (to_dir, i, ), "wb").write(hdr + data) | |
print("[*] pkt-%d written" % i) | |
i += 1 | |
return i | |
if __name__ == "__main__": | |
## step 0 | |
# populate_directory_with_packets("./all-packets-client.raw", to_dir="packets-to-server/") | |
## step1 | |
try: os.unlink("/tmp/proxy") | |
except: pass | |
for i in range(0, 743): | |
fname = "packets-to-server/pkt-%d" % i | |
if not os.path.isfile(fname): continue | |
print("-------- %s" % fname) | |
raw_data = open(fname).read() | |
Packet(raw_data).parse() | |
## step2 | |
nb = populate_directory_with_packets("/tmp/proxy", "proxied-packets/") | |
for i in range(1,nb): | |
fname = "proxied-packets/pkt-%d" % i | |
print("-------- %s" % fname) | |
Packet( open(fname).read() ).parse() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import base64, sys, hashlib, struct | |
from Crypto import Random | |
from Crypto.Cipher import AES | |
from hexdump import hexdump | |
BLOCK_SIZE = 32 | |
def p32(x): | |
return struct.pack("<I",x) | |
def u32(x): | |
return struct.unpack("<I",x)[0] | |
def decrypt(encrypted, passphrase, iv): | |
aes = AES.new(passphrase, AES.MODE_CBC, iv) | |
return aes.decrypt(encrypted) | |
if __name__ == "__main__": | |
data = open(sys.argv[1]).read() | |
# assert len(data) == 0x0089334, "file is 0x%x (expected 0x0089334)" % len(data) | |
print("[+] data_size = 0x%x" % len(data)) | |
key = base64.b64decode("tCqlc2+fFiLcuq1ee1eAPOMjxcdijh8z0jrakMA/jxg=") | |
i = data.find("cryp") | |
i += 4 | |
iv = data[i:i+0x10] | |
print("[+] iv: %s" % iv.encode('hex')) | |
i += 0x10 | |
sha = data[i:i+0x20] | |
print("[+] sha: %s" % sha.encode('hex')) | |
i += 0x20 | |
enc = data[i:] | |
if len(enc) % 16: | |
enc += '\x00' * (16-(len(enc) % 16)) | |
dec = decrypt(enc, key, iv) | |
sz = u32(dec[:4]) | |
filename = dec[4:4+sz] | |
filesize = u32(dec[4+sz:4+sz+4]) | |
print("[+] filepath '%s'" % filename) | |
print("[+] filesize 0x%x" % filesize) | |
i = 4+sz+8 | |
decrypted_file_content = dec[i:i+filesize] | |
print("[+] len(decrypted) 0x%x" % len(decrypted_file_content)) | |
h = hashlib.sha256(decrypted_file_content).digest() | |
if h == sha: | |
print("[!!!] win ! dumping lab10.zip...") | |
open("lab10.zip", "wb").write(decrypted_file_content) | |
else: | |
print("[-] invalid sha256") | |
print("[-] decrypted_sha: %s" % h1) | |
print("[-] decrypted_sha: %s" % h2) | |
# password: infectedinfectedinfectedinfectedinfected919 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment