Files
webrat_crack/patch.py
T

214 lines
6.9 KiB
Python
Raw Normal View History

2026-08-27 11:23:33 -06:00
#!/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}")