Skip to content

Instantly share code, notes, and snippets.

@sagittarius-a
Created August 12, 2024 20:50
Show Gist options
  • Save sagittarius-a/799048adae7c9ce07dba4970b48ef901 to your computer and use it in GitHub Desktop.
Save sagittarius-a/799048adae7c9ce07dba4970b48ef901 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()
@dyoniz
Copy link

dyoniz commented Oct 2, 2024

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

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