|
#!/usr/bin/env python3 |
|
|
|
""" |
|
Script was made by @alula on GitHub |
|
|
|
I made some improvements and modified it to be more user-friendly. |
|
""" |
|
|
|
import json |
|
import hashlib |
|
from datetime import datetime |
|
|
|
|
|
TIMESTAMP_FORMAT = '%Y-%m-%d %H:%M:%S' |
|
|
|
|
|
def license_structure(name: str, email: str, license_key: str) -> dict: |
|
now = datetime.now() |
|
ten_years_later = now.replace(year=now.year + 10) |
|
|
|
ts_start = now.strftime(TIMESTAMP_FORMAT) |
|
ts_end = ten_years_later.strftime(TIMESTAMP_FORMAT) |
|
|
|
base = { |
|
"header": {"version": 1}, |
|
"payload": { |
|
"name": name, |
|
"email": email, |
|
"licenses": [ |
|
{ |
|
"id": license_key, |
|
"license_type": "named", |
|
"product": "IDA", |
|
"seats": 1, |
|
"start_date": ts_start, |
|
"end_date": ts_end, # This can't be more than 10 years! |
|
"issued_on": ts_start, |
|
"owner": name, |
|
"add_ons": [], |
|
"features": [], |
|
} |
|
], |
|
}, |
|
} |
|
|
|
addons = [ |
|
"HEXX86", |
|
"HEXX64", |
|
"HEXARM", |
|
"HEXARM64", |
|
"HEXMIPS", |
|
"HEXMIPS64", |
|
"HEXPPC", |
|
"HEXPPC64", |
|
"HEXRV64", |
|
"HEXARC", |
|
"HEXARC64", |
|
# Probably cloud? |
|
# "HEXCX86", |
|
# "HEXCX64", |
|
# "HEXCARM", |
|
# "HEXCARM64", |
|
# "HEXCMIPS", |
|
# "HEXCMIPS64", |
|
# "HEXCPPC", |
|
# "HEXCPPC64", |
|
# "HEXCRV", |
|
# "HEXCRV64", |
|
# "HEXCARC", |
|
# "HEXCARC64", |
|
] |
|
|
|
for i, addon in enumerate(addons): |
|
base["payload"]["licenses"][0]["add_ons"].append( |
|
{ |
|
"id": f"48-1337-DEAD-{i:02}", |
|
"code": addon, |
|
"owner": base["payload"]["licenses"][0]["id"], |
|
"start_date": ts_start, |
|
"end_date": ts_end, |
|
} |
|
) |
|
|
|
return base |
|
|
|
|
|
def json_stringify_alphabetical(obj: dict) -> str: |
|
return json.dumps(obj, sort_keys=True, separators=(",", ":")) |
|
|
|
|
|
def buf_to_bigint(buf: bytes) -> int: |
|
return int.from_bytes(buf, byteorder="little") |
|
|
|
|
|
def bigint_to_buf(i: int) -> bytes: |
|
return i.to_bytes((i.bit_length() + 7) // 8, byteorder="little") |
|
|
|
|
|
# Yup, you only have to patch 5c -> cb in libida64.so |
|
pub_modulus_hexrays: int = buf_to_bigint( |
|
bytes.fromhex( |
|
"edfd425cf978546e8911225884436c57140525650bcf6ebfe80edbc5fb1de68f4c66c29cb22eb668788afcb0abbb718044584b810f8970cddf227385f75d5dddd91d4f18937a08aa83b28c49d12dc92e7505bb38809e91bd0fbd2f2e6ab1d2e33c0c55d5bddd478ee8bf845fcef3c82b9d2929ecb71f4d1b3db96e3a8e7aaf93" |
|
) |
|
) |
|
pub_modulus_patched: int = buf_to_bigint( |
|
bytes.fromhex( |
|
"edfd42cbf978546e8911225884436c57140525650bcf6ebfe80edbc5fb1de68f4c66c29cb22eb668788afcb0abbb718044584b810f8970cddf227385f75d5dddd91d4f18937a08aa83b28c49d12dc92e7505bb38809e91bd0fbd2f2e6ab1d2e33c0c55d5bddd478ee8bf845fcef3c82b9d2929ecb71f4d1b3db96e3a8e7aaf93" |
|
) |
|
) |
|
|
|
private_key: int = buf_to_bigint( |
|
bytes.fromhex( |
|
"77c86abbb7f3bb134436797b68ff47beb1a5457816608dbfb72641814dd464dd640d711d5732d3017a1c4e63d835822f00a4eab619a2c4791cf33f9f57f9c2ae4d9eed9981e79ac9b8f8a411f68f25b9f0c05d04d11e22a3a0d8d4672b56a61f1532282ff4e4e74759e832b70e98b9d102d07e9fb9ba8d15810b144970029874" |
|
) |
|
) |
|
|
|
example_real_sig_bytes: bytes = bytes.fromhex("8C601843D20AF0997C175723F49D6C6CE77A039F3FFCEC95B89FD99611C0EDDE0B9762A977C408D25662C06B2424B83EDDFBE30177C1A99A881ED1B695F2AD38E4119058463B0CA1BEA651CFCAFBD60E68A407FD76D519063CFB6EF35FFE7C1A375388BC5EB5565C29AFAB06BF0031A7A2AA7433CBD929FD8D12E160981D0812") |
|
example_real_sig_bigint: int = buf_to_bigint(example_real_sig_bytes) |
|
|
|
|
|
def decrypt(message: bytes, use_patched: bool = True) -> bytes: |
|
mod: int = pub_modulus_patched if use_patched else pub_modulus_hexrays |
|
decrypted_bigint: int = pow(buf_to_bigint(message), exponent, mod) |
|
decrypted_bytes: bytes = bigint_to_buf(decrypted_bigint) |
|
rev_decrypted_bytes = decrypted_bytes[::-1] |
|
print(f"decrypt: msg: {message.hex().upper()} decryped_bytes: {decrypted_bytes.hex().upper()} rev_decrypted_bytes: {rev_decrypted_bytes.hex().upper()}") |
|
return rev_decrypted_bytes |
|
|
|
|
|
def encrypt(message: bytes, use_patched: bool = True) -> bytes: |
|
mod: int = pub_modulus_patched if use_patched else pub_modulus_hexrays |
|
encrypted_bigint: int = pow(buf_to_bigint(message[::-1]), private_key, mod) |
|
encrypted: bytes = bigint_to_buf(encrypted_bigint) |
|
print(f"encrypt: msg: {message.hex().upper()} encrypted: {encrypted.hex().upper()}") |
|
return encrypted |
|
|
|
|
|
exponent = 0x13 |
|
|
|
|
|
def sign_hexlic(payload: dict) -> str: |
|
data = {"payload": payload} |
|
data_str = json_stringify_alphabetical(data) |
|
|
|
buffer = bytearray(128) |
|
# first 33 bytes are random |
|
for i in range(33): |
|
buffer[i] = 0x42 |
|
|
|
# compute sha256 of the data |
|
sha256 = hashlib.sha256() |
|
sha256.update(data_str.encode()) |
|
digest = sha256.digest() |
|
print(f"sha-256 digest: {digest.hex().upper()}") |
|
|
|
# copy the sha256 digest to the buffer |
|
for i in range(len(digest)): |
|
buffer[33 + i] = digest[i] |
|
|
|
print(f"pre-encrypted buffer: {buffer.hex().upper()}") |
|
# encrypt the buffer |
|
encrypted = encrypt(buffer) |
|
print(f"post-encrypted buffer: {encrypted.hex().upper()}") |
|
decrypted_sanity = decrypt(encrypted) |
|
print(f"decrypted encrypted buffer: {decrypted_sanity.hex().upper()}") |
|
|
|
return encrypted.hex().upper() |
|
|
|
|
|
def main(): |
|
print("IDA Pro 9.0 BETA Keygen") |
|
print("(!) DISCLAIMER: This is for educational purposes only. (!)") |
|
print("(!) Please note that you must patch the public modulus inside of the ida and ida64 dynamic libraries. (!)") |
|
print(" ↳ For more information about this process: https://gist.github.com/AngeloD2022/e949c1c7c2a51513c620ac5dd5212b94\n\n") |
|
|
|
lic_name = input("Enter desired license name (can be fake): ") |
|
lic_email = input("Enter license email address (can be fake): ") |
|
|
|
print("Generating license base...") |
|
lic_base = license_structure(lic_name, lic_email, "48-2437-ACBD-29") |
|
|
|
print("Signing...") |
|
lic_base["signature"] = sign_hexlic(lic_base["payload"]) |
|
|
|
print("Generating ida.hexlic...") |
|
serialized = json_stringify_alphabetical(lic_base) |
|
|
|
with open("ida.hexlic", "w") as file: |
|
file.write(serialized) |
|
|
|
print("Finished.") |
|
|
|
|
|
if __name__ == '__main__': |
|
main() |