karta-ng — Karta next-gen, for IDA Pro 9.1+
"Karta" (Russian for "Map") identifies and matches open-source libraries inside a binary. It uses a location-driven technique that scales to very large binaries (>200,000 functions) with almost no impact on performance, because the matching cost depends on K — the number of functions in the open source — rather than N, the size of the binary, and usually N >> K.
karta-ng is a maintained continuation of that work: IDA 9.x and Python 3.13 support, an analysis layer on the raw ida_* API, a headless entry point that runs the same matcher core without opening a form, relocation-independent structural signatures, and a much larger library-seeker catalogue.
Table of contents
- Why you would use this
- Installation
- Requirements
- Usage
- How it works
- What is new over upstream Karta
- Configuration schema
- Development
- Acknowledgements
- Contact
Why you would use this
- Identifying which open sources (and which versions) a binary uses, when hunting for a useful 1-day.
- Matching the symbols of supported open sources to speed up malware reverse engineering.
- Matching those symbols in a binary or firmware image when searching for 0-days in the proprietary code around them.
Installation
Quick install
pip install -e . # from a clone
The disassembler backend reads the raw ida_* modules directly (ida-domain was dropped in 2.5.0: its per-call wrappers were half of the analysis phase). idapro (idalib) opens databases for the headless surfaces.
Then deploy the plugin into IDA:
python -m karta_ng.installers.ida_installer
The installer detects your IDA installation and copies the plugin entry point into its plugins/ directory. Restart IDA afterwards; the plugin registers Karta NG: Match libraries under Edit > Plugins.
Install with hcli
hcli is Hex-Rays' command-line tool. Install it once:
curl -LsSf https://hcli.docs.hex-rays.com/install | sh # macOS/Linux
iwr -useb https://hcli.docs.hex-rays.com/install.ps1 | iex # Windows (PowerShell)
This repository ships an ida-plugin.json descriptor that is validated against the IDA Plugin Repository schema on every CI run, so it installs through hcli once published. Requires IDA 9.1+.
Need to find your plugin directory?
From IDA's Python console:
import idaapi, os; print(os.path.join(idaapi.get_user_idadir(), "plugins"))
Where is my default user directory?
- Windows:
%APPDATA%\Hex-Rays\IDA Pro - macOS:
~/.idapro - Linux:
~/.idapro
Requirements
| IDA Pro | 9.1, 9.2, 9.3, 9.4 |
| Python | 3.10+ (IDA 9.x bundles 3.13; CI exercises that interpreter) |
| Required | elementals, click, scikit-learn |
| Optional | Cython for native speedups |
sark is not required. The disassembler layer runs on the raw ida_* modules; the sark-shaped shim that replaced it (thumbs_up/ida_compat.py) now lives inside thumbs_up/, its only consumer.
Usage
Identifier
The identifier fingerprints which supported open sources are present and which versions they are, so you do not reverse the same library twice. It writes <input>_libraries.txt beside the database — the same place and naming convention the matcher uses for <input>.analysis.
karta-ng currently registers 152 seekers, spanning the upstream set (OpenSSL, libpng, libjpeg, NetSNMP, zlib, libtiff, libxml2, gSOAP, OpenSSH, and more) plus categories the upstream project never covered: crypto, compression, network, multimedia, database, math, runtime, game engines, GUI toolkits, IoT, ML, containers, parsing, cloud SDKs, logging, web, graphics, security, and codecs.
Matcher
Once a library and version are identified, point Karta at a matching .json configuration and it resolves the open source's functions — and the external functions it calls, such as memcpy, fread, or zlib_inflate — onto the functions in your binary.
In the GUI: Edit > Plugins > Karta NG: Match libraries.
Six ready-made configurations ship in configs/: OpenSSL 1.0.1j, libpng 1.2.29, libtiff 4.0.8 (Linux and Windows), and zlib 1.2.3 / 1.2.11.
Headless
The same matcher core runs without opening a single form, through idapro:
# match, write <input>.analysis (JSON) beside the database, touch nothing else
python -m karta_ng.karta_headless --config configs/ sample.bin
# opt in to renaming the matched functions and saving the IDB
python -m karta_ng.karta_headless --config configs/ --apply-names sample.bin
The report carries approxLibs, versions.{original,testedAgainst}, per-library match statistics, and a per-function ledger: function_matches, unmatched_used_functions, structural_signature_candidates, and applied_names.
Name import is opt-in by design — the default path never mutates your database.
Generating a configuration
To match a library version nobody has published a config for, compile that version and point the analyzer at its objects:
karta-analyze-src <lib-name> <lib-version> -C 8 <source-dir> <archive>
-C sets how many idapro worker processes run in parallel. The run is resumable: existing per-file state files are reused. Output is <lib>_<version>[_windows].json.
How it works
Identification and matching are separate phases joined only by JSON configuration files on disk.
The matching itself is location-driven. Rather than fingerprinting each function independently, Karta locates the compiled files and matches functions by their original order within each file. Unique constants and strings act as anchors that pin a small number of certain matches; confidence then propagates outward through the call graph and across file boundaries. A speculative branch that turns out contradictory is unwound rather than accepted.
karta-ng adds two relocation-independent signals on top:
- Instruction mnemonics — the normalized opcode sequence of a function. Static linking rewrites branch and call operands but not the mnemonic flow, so a unique instruction shape works as a final post-anchor confirmation pass.
- CFG block topology — per-basic-block predecessor and successor counts plus a terminal category (
exit,linear,branch,fanout). Deliberately low-weight supporting evidence, so Karta's conservative scoring behaviour is preserved.
What is new over upstream Karta
- Far more seekers, across 30+ categories rather than the original handful.
- IDA 9.x and Python 3.13 — the UI layer follows the 9.x move to
ida_kernwinand falls back toidaapiwhere it is unavailable. - Headless surfaces —
karta_headlessfor matching,karta-analyze-srcfor config generation with concurrentidaproworkers, neither needing anidatsubprocess. - Forced matching (
get_nearby_version) — when the exact version config is missing, match against the numerically closest available version, weighted toward earlier components. - Structural signatures and CFG topology, described above.
- Opt-in name import —
--apply-namesrenames only the matched functions. sarkremoved.
Configuration schema
karta-analyze-src emits one record per source function with a stable tag set, guarded by tests/unit/test_schema_roundtrip.py:
Function Name, Instruction Count, Stack Frame Size, Hash, Is Static, Numeric Consts, Strings, Calls, Unknown Functions, Unknown Globals, Code Block Sizes, Instruction Mnemonics, CFG Block Topology, Call Order
The schema is additive only. Configurations generated before Instruction Mnemonics and CFG Block Topology existed remain valid and simply contribute no topology score.
Note for the DontStarveLuaJIT2 consumer:
KartaConfig.cppparsesisStatic/Unknown Consts, but every Karta lineage emitsIs Static/Unknown Globals. That mismatch lives in the consumer; karta-ng emits the upstream-compatible schema.
Development
Tests
Unit tests are pure Python and need no IDA:
PYTHONPATH=src python -m pytest tests/unit/ -q
System tests need IDA (or idapro) and skip cleanly without it. The docker runner handles the whole environment:
tools/scripts/run_system_tests_docker.sh system
tools/scripts/run_system_tests_docker.sh system -- -k headless -v # args after -- go to pytest
A green run is 31 passed: 23 unit and 8 system. CI runs the suite against IDA 9.4 on arm64 and IDA 9.1 on amd64.
Architectural gates
Two boundaries are machine-enforced rather than merely documented — the portable layers (config, core, libs) hold the fingerprinting and matching logic and must stay IDA-free, receiving the disassembler by dependency injection:
sg scan --config sgconfig.yml # ast-grep: no print(), no mocks in system tests, no live IDA in portable core
lint-imports # import-linter contracts
Both run in .githooks/pre-commit. Enable once per clone:
git config core.hooksPath .githooks
Versioning
__version__ in src/karta_ng/__init__.py is the single source of truth. tools/sync_plugin_version.py copies it into ida-plugin.json — both the manifest version and its exact karta-ng==VERSION dependency — and the pre-commit hook stages the result.
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Test thoroughly
- Submit a pull request
New library seekers are the easiest contribution: subclass Seeker in src/karta_ng/libs/, implement search_lib and identify_versions, and call MySeeker.register(MySeeker.NAME, MySeeker) at the bottom of the module. libs/__init__.py walks the package, so being on disk is what makes it active — len(lib_factory.get_lib_factory()) is the ground truth.
Read the Seeker docstring first. A seeker produces the (library, version) pair that names <lib>_<version>.json, the configuration the matcher resolves onto the binary — it is a lookup key, not a detector. It is worth writing only if identifying the library could reduce the reversing workload, which needs the code to be statically linked into the binary and the source to be obtainable and compilable. Packers, system DLLs and bare algorithms fail that test; 204 seekers were deleted in 2026-08 for failing it, and the docstring says why so it does not happen again.
Configuration files for library versions not yet covered are just as welcome.
Acknowledgements
Karta was created by Eyal Itkin (@EyalItkin) with the support of Check Point Research, and originally lived at CheckPointSW/Karta. The original background reading is still the best explanation of the technique:
- Karta — Matching Open Sources in Binaries
- Thumbs Up: Using Machine Learning to Improve IDA's Analysis
- Upstream documentation
Eyal stepped away from maintaining the project on leaving Check Point Research. It was later forked to mitre/Karta by MalwareFrank in May 2025 and updated for IDA Pro 9, with additional IDA 9.1 and Python 3.13 work by seifreed. karta-ng continues from that lineage.
Contact
ping me on x @mahmoudimus or you may contact me from any one of the addresses on mahmoudimus.com.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file karta_ng-2.6.0.tar.gz.
File metadata
- Download URL: karta_ng-2.6.0.tar.gz
- Upload date:
- Size: 209.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9c298d6ae1d820b071d5dd1ce9ea5722e2c2f1195408f66a97fbacdbcee01960
|
|
| MD5 |
241e53a22cbb4d6cd2da1f9ed4df5605
|
|
| BLAKE2b-256 |
2b0a2f010bd3f7723328a58f1ce3ae3ef75edc09c0453ebcde04d384aa1b8167
|
Provenance
The following attestation bundles were made for karta_ng-2.6.0.tar.gz:
Publisher:
deploy.yml on mahmoudimus/karta-ng
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
karta_ng-2.6.0.tar.gz -
Subject digest:
9c298d6ae1d820b071d5dd1ce9ea5722e2c2f1195408f66a97fbacdbcee01960 - Sigstore transparency entry: 2646698315
- Sigstore integration time:
-
Permalink:
mahmoudimus/karta-ng@b48887b5dffe09cfd621644bde48e22d742aea63 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/mahmoudimus
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
deploy.yml@b48887b5dffe09cfd621644bde48e22d742aea63 -
Trigger Event:
workflow_run
-
Statement type:
File details
Details for the file karta_ng-2.6.0-py3-none-any.whl.
File metadata
- Download URL: karta_ng-2.6.0-py3-none-any.whl
- Upload date:
- Size: 260.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
be5773f8dd97190c9339aa1389166b08d86ea21f2d49416ddf83d187413a0f5d
|
|
| MD5 |
1b1d44c88271521e9dbdc474276a14f6
|
|
| BLAKE2b-256 |
eb8f0ace2fb401fc1f36c2b0ccd21052fd1537d40ab0b57207d82318d8cb722d
|
Provenance
The following attestation bundles were made for karta_ng-2.6.0-py3-none-any.whl:
Publisher:
deploy.yml on mahmoudimus/karta-ng
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
karta_ng-2.6.0-py3-none-any.whl -
Subject digest:
be5773f8dd97190c9339aa1389166b08d86ea21f2d49416ddf83d187413a0f5d - Sigstore transparency entry: 2646698384
- Sigstore integration time:
-
Permalink:
mahmoudimus/karta-ng@b48887b5dffe09cfd621644bde48e22d742aea63 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/mahmoudimus
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
deploy.yml@b48887b5dffe09cfd621644bde48e22d742aea63 -
Trigger Event:
workflow_run
-
Statement type: