Skip to content

Instantly share code, notes, and snippets.

@BorjaMerino
Created September 18, 2023 10:24
Show Gist options
  • Save BorjaMerino/d1534a3b563df9f1d5188c435b98f212 to your computer and use it in GitHub Desktop.
Save BorjaMerino/d1534a3b563df9f1d5188c435b98f212 to your computer and use it in GitHub Desktop.
Silly script to extract the compressed-encrypted payload of PNG images dropped by HijackLoader
# @BorjaMerino (Alpine Security)
import lznt1, argparse, os, struct
TAG = b'\xC6\xA5\x79\xEA'
CHUNK_ID = b'\x49\x44\x41\x54'
DWORD = 4
def get_header(png):
with open(png, "rb") as file:
filebuf = file.read()
offset_TAG = filebuf.find(TAG)
if offset_TAG != -1:
offset_KEY = offset_TAG + DWORD
offset_CSIZE = offset_KEY + DWORD
offset_USIZE = offset_CSIZE + DWORD
KEY = filebuf[offset_KEY:offset_CSIZE]
CSIZE = filebuf[offset_CSIZE:offset_USIZE]
USIZE = filebuf[offset_USIZE:offset_USIZE + DWORD]
print(f"[+] HEADER: 0x{offset_TAG:02X} 0x{KEY.hex().upper()} 0x{CSIZE.hex().upper()} 0x{USIZE.hex().upper()}")
print(f"\t TAG: 0x{TAG.hex().upper()}")
print(f"\t KEY: 0x{KEY.hex().upper()}")
print(f"\t CSIZE: 0x{CSIZE.hex().upper()} ({(int.from_bytes(CSIZE, byteorder='little'))} bytes) ")
print(f"\t USIZE: 0x{USIZE.hex().upper()} ({(int.from_bytes(USIZE, byteorder='little'))} bytes)")
return offset_TAG, KEY, CSIZE
else:
print("[-] Header not found :/")
return None, None, None
def get_encrypted_payload(png, offset_TAG):
with open(png, "rb") as file:
filebuf = file.read()
offset_TAG += DWORD * 4 # ID + XOR + CSIZE + USIZE
content_buf = filebuf[offset_TAG:]
ID_offset = content_buf.find(CHUNK_ID)
if ID_offset != -1:
xored_buffer = bytearray()
while ID_offset != -1:
ID_offset_8 = ID_offset - 8 # Ignoring offset/size for each chunk (changeme)
data_to_extract = content_buf[:ID_offset_8]
xored_buffer.extend(data_to_extract)
content_buf = content_buf[ID_offset + DWORD:]
ID_offset = content_buf.find(CHUNK_ID)
xored_buffer.extend(content_buf)
return xored_buffer
else:
print("[-] ID chunk not found:/")
return None
def decrypt_xor(enc_payload, KEY):
xor_buff = bytearray()
for i, byte in enumerate(enc_payload):
xor_byte = byte ^ KEY[i % 4]
xor_buff.append(xor_byte)
return xor_buff
def uncompress_lznt(compressed_payload):
output = "payload.bin"
try:
uncompressed_payload = lznt1.decompress(compressed_payload)
except Exception as e:
print(f"[-] ERROR occurred while decompressing: {str(e)} :/")
uncompressed_payload = None
return
with open(output, 'wb') as dump_buffer:
dump_buffer.write(uncompressed_payload)
print(f"[+] Payload saved to {output}")
def main():
parser = argparse.ArgumentParser(description="payload extractor")
parser.add_argument("File", help="PNG file name")
png_file = parser.parse_args().File
offset_TAG, KEY, CSIZE = get_header(png_file)
if offset_TAG is not None:
enc_payload = get_encrypted_payload(png_file, offset_TAG)
if enc_payload is not None:
dec_payload = decrypt_xor(enc_payload, KEY)
uncompress_lznt(dec_payload[:(int.from_bytes(CSIZE, byteorder='little'))])
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment