Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save AutoScrape123TX/40106f915919875e9704f154b0b8784f to your computer and use it in GitHub Desktop.
Save AutoScrape123TX/40106f915919875e9704f154b0b8784f to your computer and use it in GitHub Desktop.
Guide: Patching IDA Pro 9.0 BETA

Patching the IDA Pro 9.0 BETA

Note

Obligatory disclaimer: this is for educational purposes only. I am not responsible for any damages caused by following this guide, or using any of the script(s) herein.

This guide prioritizes arm64 macOS, but may also work for other platforms.


Step 1 - Patching dylibs

Note

Repeat this step for both, libida64.dylib and libida.dylib, as both contain this signature check.

Warning

Make sure to create a backup of the libraries just in case something doesn't go correctly.

Start by opening the dylib in your favorite binary analysis software (or hex editor if you're doing a simple search for the public modulus sequence).

Search for usage of the string: Signature decryption failed with code: %d.

image

Dylib Public Modulus Location
libida64.dylib 0x40bf44
libida.dylib 0x3f4b24

At the location, replace the fourth byte 0x5C to 0xCB (pictured below).

image

Finally, save the patched dylibs to their original location.

Step 2

Use the attached script to generate an ida.hexlic for your copy.

Troubleshooting

Internal Error 30016

If encountering this error, navigate to /Applications/IDA Professional 9.0.app/Contents/MacOS/plugins and rename arm_mac_user64.dylib to arm_mac_user64.dylib.bak.

If you so choose, you can also remove this file, as it does not seem to benefit the software in any way.

"This application cannot be opened"

Try re-signing both dylibs:

codesign -f -s - --timestamp=none --all-architectures --deep "/Applications/IDA Professional 9.0.app/Contents/MacOS/libida.dylib"

codesign -f -s - --timestamp=none --all-architectures --deep "/Applications/IDA Professional 9.0.app/Contents/MacOS/libida64.dylib"

If that didn't work, try unquarantining IDA Pro using this command:

xattr -r -d com.apple.quarantine /Applications/IDA Professional 9.0.app

Alternatively, try disabling System Integrity Protection.

References

#!/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()
@AutoScrape123TX
Copy link
Author

https://zerobin.org/?d5c5cf44154895e9#C9fXArBX3K7XWXWr1hSDAACtW74v5grtj12exhWUuPNP

This one make the cake and coffee 👯‍♀️

import json
import hashlib
import os
 
license = {
    "header": {"version": 1},
    "payload": {
        "name": "meow :3",
        "email": "[email protected]",
        "licenses": [
            {
                "id": "48-2137-ACAB-99",
                "license_type": "named",
                "product": "IDA",
                "seats": 1,
                "start_date": "2024-08-10 00:00:00",
                "end_date": "2033-12-31 23:59:59",  # This can't be more than 10 years!
                "issued_on": "2024-08-10 00:00:00",
                "owner": "cracked by alula :3",
                "add_ons": [
                    # {
                    #     "id": "48-1337-DEAD-01",
                    #     "code": "HEXX86L",
                    #     "owner": "48-0000-0000-00",
                    #     "start_date": "2024-08-10 00:00:00",
                    #     "end_date": "2033-12-31 23:59:59",
                    # },
                    # {
                    #     "id": "48-1337-DEAD-02",
                    #     "code": "HEXX64L",
                    #     "owner": "48-0000-0000-00",
                    #     "start_date": "2024-08-10 00:00:00",
                    #     "end_date": "2033-12-31 23:59:59",
                    # },
                ],
                "features": [],
            }
        ],
    },
}
 
 
def add_every_addon(license):
    platforms = [
        "W",  # Windows
        "L",  # Linux
        "M",  # macOS
    ]
    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",
    ]
 
    i = 0
    for addon in addons:
        i += 1
        license["payload"]["licenses"][0]["add_ons"].append(
            {
                "id": f"48-1337-DEAD-{i:02}",
                "code": addon,
                "owner": license["payload"]["licenses"][0]["id"],
                "start_date": "2024-08-10 00:00:00",
                "end_date": "2033-12-31 23:59:59",
            }
        )
    # for addon in addons:
    #     for platform in platforms:
    #         i += 1
    #         license["payload"]["licenses"][0]["add_ons"].append(
    #             {
    #                 "id": f"48-1337-DEAD-{i:02}",
    #                 "code": addon + platform,
    #                 "owner": license["payload"]["licenses"][0]["id"],
    #                 "start_date": "2024-08-10 00:00:00",
    #                 "end_date": "2033-12-31 23:59:59",
    #             }
    #         )
 
 
add_every_addon(license)
 
 
def json_stringify_alphabetical(obj):
    return json.dumps(obj, sort_keys=True, separators=(",", ":"))
 
 
def buf_to_bigint(buf):
    return int.from_bytes(buf, byteorder="little")
 
 
def bigint_to_buf(i):
    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 = buf_to_bigint(
    bytes.fromhex(
        "edfd425cf978546e8911225884436c57140525650bcf6ebfe80edbc5fb1de68f4c66c29cb22eb668788afcb0abbb718044584b810f8970cddf227385f75d5dddd91d4f18937a08aa83b28c49d12dc92e7505bb38809e91bd0fbd2f2e6ab1d2e33c0c55d5bddd478ee8bf845fcef3c82b9d2929ecb71f4d1b3db96e3a8e7aaf93"
    )
)
pub_modulus_patched = buf_to_bigint(
    bytes.fromhex(
        "edfd42cbf978546e8911225884436c57140525650bcf6ebfe80edbc5fb1de68f4c66c29cb22eb668788afcb0abbb718044584b810f8970cddf227385f75d5dddd91d4f18937a08aa83b28c49d12dc92e7505bb38809e91bd0fbd2f2e6ab1d2e33c0c55d5bddd478ee8bf845fcef3c82b9d2929ecb71f4d1b3db96e3a8e7aaf93"
    )
)
 
private_key = buf_to_bigint(
    bytes.fromhex(
        "77c86abbb7f3bb134436797b68ff47beb1a5457816608dbfb72641814dd464dd640d711d5732d3017a1c4e63d835822f00a4eab619a2c4791cf33f9f57f9c2ae4d9eed9981e79ac9b8f8a411f68f25b9f0c05d04d11e22a3a0d8d4672b56a61f1532282ff4e4e74759e832b70e98b9d102d07e9fb9ba8d15810b144970029874"
    )
)
 
 
def decrypt(message):
    decrypted = pow(buf_to_bigint(message), exponent, pub_modulus_patched)
    decrypted = bigint_to_buf(decrypted)
    return decrypted[::-1]
 
 
def encrypt(message):
    encrypted = pow(buf_to_bigint(message[::-1]), private_key, pub_modulus_patched)
    encrypted = bigint_to_buf(encrypted)
    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()
 
    # copy the sha256 digest to the buffer
    for i in range(32):
        buffer[33 + i] = digest[i]
 
    # encrypt the buffer
    encrypted = encrypt(buffer)
 
    return encrypted.hex().upper()
 
 
def generate_patched_dll(filename):
    if not os.path.exists(filename):
        print(f"Didn't find {filename}, skipping patch generation")
        return
 
    with open(filename, "rb") as f:
        data = f.read()
 
        if data.find(bytes.fromhex("EDFD42CBF978")) != -1:
            print(f"{filename} looks to be already patched :)")
            return
        
        if data.find(bytes.fromhex("EDFD425CF978")) == -1:
            print(f"{filename} doesn't contain the original modulus.")
            return
 
        data = data.replace(
            bytes.fromhex("EDFD425CF978"), bytes.fromhex("EDFD42CBF978")
        )
 
        patched_filename = f"{filename}.patched"
        with open(patched_filename, "wb") as f:
            f.write(data)
 
        print(f"Generated modulus patch to {patched_filename}! To apply the patch, replace the original file with the patched file")
 
 
# message = bytes.fromhex(license["signature"])
# print(decrypt(message).hex())
# print(encrypt(decrypt(message)).hex())
 
license["signature"] = sign_hexlic(license["payload"])
 
serialized = json_stringify_alphabetical(license)
 
# write to ida.hexlic
filename = "ida.hexlic"
 
with open(filename, "w") as f:
    f.write(serialized)
 
print(f"Saved new license to {filename}!")
 
generate_patched_dll("ida.dll")
generate_patched_dll("ida64.dll")
generate_patched_dll("libida.so")
generate_patched_dll("libida64.so")
generate_patched_dll("libida.dylib")
generate_patched_dll("libida64.dylib")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment