#!/usr/bin/env python3 from Crypto.Cipher import AES from Crypto.Random import get_random_bytes import hashlib import os def rolling_xor_encode(data): result = bytearray(data) for i in range(1, len(result)): result[i] ^= result[i - 1] return bytes(result) def rolling_xor_decode(data): result = bytearray(data) for i in range(len(result) - 1, 0, -1): result[i] ^= result[i - 1] return bytes(result) def xor_with_key(data, key): return bytes(data[i] ^ key[i % len(key)] for i in range(len(data))) def encrypt_mode_1(plaintext, aes_key): nonce = get_random_bytes(12) cipher = AES.new(aes_key, AES.MODE_GCM, nonce=nonce) ciphertext, tag = cipher.encrypt_and_digest(plaintext) return nonce + ciphertext + tag def encrypt_mode_4(data, xor_key): xored = xor_with_key(data, xor_key) return rolling_xor_decode(xored) def encrypt_c2_url(url_bytes, aes_key, xor_key): aes_encrypted = encrypt_mode_1(url_bytes, aes_key) hex_str = aes_encrypted.hex() hex_bytes = hex_str.encode('latin-1') mode4_encrypted = encrypt_mode_4(hex_bytes, xor_key) final_hex = mode4_encrypted.hex() return final_hex def decrypt_mode_4(data, xor_key): rolled = rolling_xor_encode(data) return xor_with_key(rolled, xor_key) def decrypt_mode_1(data, aes_key): nonce = data[:12] tag = data[-16:] ciphertext = data[12:-16] cipher = AES.new(aes_key, AES.MODE_GCM, nonce=nonce) return cipher.decrypt_and_verify(ciphertext, tag) def decrypt_c2(enc_hex, aes_key, xor_key): encrypted = bytes.fromhex(enc_hex) after_mode4 = decrypt_mode_4(encrypted, xor_key) hex_str = after_mode4.decode('latin-1') intermediate = bytes.fromhex(hex_str) url = decrypt_mode_1(intermediate, aes_key) return url md5_biba = hashlib.md5(b"biba").digest() aes_key = rolling_xor_encode(md5_biba) xor_key = bytes.fromhex("d0af20d0bbd18ed0b1d0bbd18e20d181d0bed181d0b0d182d18c") print("=" * 70) print("patch") print("=" * 70) print(f"AES Key: {aes_key.hex()}") print(f"XOR Key: {xor_key.hex()}") print() #encrypted_hex_len = (url_len + 12 + 16) * 4 #url_len = encrypted_hex_len / 4 - 28 original_c2s = [ {"name": "C2[0]", "offset": 0x599252, "orig_len": 212, "orig_enc": "e72c8df43c680b056c60696d57a7f207043b690a5a603000070b5b7285a23e6c54046331393e5afeab0e0e356c0706383b56050c057188f26c3f07506461686202aba6050a606c5752373551060c5a7adda06c6b0e59316d6b3602a0f055023b6c0156673752070a0b23"}, {"name": "C2[1]", "offset": 0x598FF6, "orig_len": 200, "orig_enc": "b3288da43d6f5e0a64643e6b0ca8a505026a6a0703663702590001238fa16d685a0e313768325ea6a0095c3d6c005c3a3350050b0b28ddf33e6a5c526e6f316a5af9f457556f69565668615a510b0f2adaf53d3a580c34613b3b5ba7fe5507693b570232"}, {"name": "C2[2]", "offset": 0x599326, "orig_len": 212, "orig_enc": "e62f8cf43b6e5f536e616d6a59faa152526466050c616e5c0d0d5c7b8ef56e6b0f0962656a3c59faa704023a38075b616951570b5e2889a06a6f0e503b336b6b0cf5ad0007383e070161335b5b0e0c2f8cf26e3b5f0d3d6d6f3e5aabf450026a3b0150626751035d5a7e"}, {"name": "C2[3]", "offset": 0x5993FA, "orig_len": 220, "orig_enc": "e62cdba2386a0e0a6568313c08aca95a016e345802373305500c0c7d88f73d385d5d65633c385fabf504563e6d5405353353005d0a7fd8f039395f0f3a696e3a59f9f65a0d3364555e3d3205565804248ef5346a02086369606a0afdf5565f6f625450676506045e56778ef53b3a"}, {"name": "BC[0]", "offset": 0x599186, "orig_len": 204, "orig_enc": "b22c8da23c6d0d5b65303c3f5ba9f30300683a00546d6a025501502cd0f963360d593261396a5dabf000563a3e5605636156015d0b7cdfaf3736540e616738395df0ff5053386856503b3e53565b01258ba1386a0f59363c613d5af6ad51543d385057306705"}, ] print("=" * 70) print("CALCULATING EXACT URL LENGTHS") print("=" * 70) for c2 in original_c2s: # url_len = encrypted_hex_len / 4 - 28 (nonce 12 + tag 16) required_url_len = c2["orig_len"] // 4 - 28 print(f"{c2['name']}: encrypted_len={c2['orig_len']} -> url_len={required_url_len}") c2["required_url_len"] = required_url_len print() # C2[0]: 25, C2[1]: 22, C2[2]: 25, C2[3]: 27, BC[0]: 23 new_urls = { "C2[0]": "http://127.0.0.1/salat/", # 24 "C2[1]": "http://127.0.0.1/sa1/", # 21 "C2[2]": "http://127.0.0.1/salat/", # 24 "C2[3]": "http://127.0.0.1/salat/", # 24 "BC[0]": "http://127.0.0.1/sa1a/", # 22 } print("=" * 70) print("GENERATING ENCRYPTED URLs") print("=" * 70) for c2 in original_c2s: base = new_urls[c2["name"]] required = c2["required_url_len"] if len(base) < required: url = base + "x" * (required - len(base)) elif len(base) > required: url = base[:required] else: url = base url_bytes = url.encode('utf-8') print(f"\n{c2['name']}:") print(f" URL: {url} ({len(url)} chars)") encrypted = encrypt_c2_url(url_bytes, aes_key, xor_key) print(f" Encrypted len: {len(encrypted)} (required: {c2['orig_len']})") if len(encrypted) != c2["orig_len"]: print(f" [ERROR] Length mismatch!") exit(1) try: decrypted = decrypt_c2(encrypted, aes_key, xor_key) print(f" Verify: {decrypted.decode('utf-8')}") except Exception as e: print(f" [ERROR] Verification failed: {e}") exit(1) c2["new_url"] = url c2["new_encrypted"] = encrypted print() INPUT_FILE = "webrat.exe1" OUTPUT_FILE = "webrat_patched.exe" if os.path.exists(INPUT_FILE): print("=" * 70) print("PATCHING BINARY") print("=" * 70) with open(INPUT_FILE, "rb") as f: data = bytearray(f.read()) print(f"Read {len(data)} bytes from {INPUT_FILE}") for c2 in original_c2s: orig_enc_bytes = c2["orig_enc"].encode('ascii') new_enc_bytes = c2["new_encrypted"].encode('ascii') found_at = data.find(orig_enc_bytes) if found_at == -1: print(f" [-] {c2['name']}: NOT FOUND!") continue if len(new_enc_bytes) != len(orig_enc_bytes): print(f" [!] {c2['name']}: FATAL length mismatch!") continue data[found_at:found_at + len(orig_enc_bytes)] = new_enc_bytes print(f" [+] {c2['name']}: Patched at 0x{found_at:X}") print(f" {c2['new_url']}") with open(OUTPUT_FILE, "wb") as f: f.write(data) print() print(f"[+] Saved: {OUTPUT_FILE}") print() print("=" * 70) print("FINAL VERIFICATION") print("=" * 70) with open(OUTPUT_FILE, "rb") as f: patched = f.read() for c2 in original_c2s: enc_bytes = c2["new_encrypted"].encode('ascii') pos = patched.find(enc_bytes) if pos >= 0: try: dec = decrypt_c2(c2["new_encrypted"], aes_key, xor_key) print(f" {c2['name']}: {dec.decode('utf-8')}") except Exception as e: print(f" {c2['name']}: FAILED - {e}") print() print("=" * 70) print("DONE!") print("=" * 70) else: print(f"[-] File not found: {INPUT_FILE}")