Triton (JonathanSalwan/Triton): a dynamic binary analysis library for symbolic execution and taint analysis
Triton is a dynamic binary analysis library. Build your own program analysis tools, automate your reverse engineering, perform software verification or just emulate code.
At a glance
- What is it?
- Triton is a C++ and Python library that lifts x86, ARM and RISC-V instructions into symbolic expressions and hands them to an SMT solver. It is aimed at people building their own analysis tools, not at people who want a finished decompiler.
- Who is it for?
- Adopt Triton when you need to write your own symbolic or taint analysis and want the instruction semantics handled for you; the pip package triton-library is the fastest way to find out whether the API fits. Skip it if you want a finished decompiler or a turnkey symbolic executor, since Triton is a library and the README describes it as a part-time project.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 12 days ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What Triton solves, and who ends up using it
Writing a symbolic executor from scratch means writing instruction semantics first. Every opcode needs a translation into an expression tree, every flag bit needs modelling, and every architecture needs its own version of that work. Triton exists to remove that layer. The README describes it as a dynamic binary analysis library whose internal components let you "build your own program analysis tools, automate reverse engineering, perform software verification or just emulate code".
The intended user is therefore someone who already has an analysis idea and does not want to write a lifter. Malware analysts who need to know which input bytes reach a comparison, researchers testing a deobfuscation pass, and developers checking whether a small routine can produce a given output all fit. Someone who wants to open a binary and read C code does not fit, and Triton does not pretend otherwise: it ships no user interface, only a C++ and a Python API.
The scope is bounded by architecture support. The README lists AST representation of x86, x86-64, ARM32, AArch64 and RISC-V 32/64 instruction semantics. Anything outside that set is not handled by the library, and there is no plugin mechanism described for adding an architecture yourself.
The mechanism: a context, a lifter, an AST and a solver
The working object in Triton is a context, created for one architecture. You feed it instruction bytes, and it lifts them into an AST, which is a tree of bitvector operations rather than a string of assembly. Concrete register values are optional; if you set them, the AST folds constants where it can. If you instead symbolize a register, that register becomes a free variable in every expression that depends on it.
The data flow is visible in the README's own example. A context is created for X86_64, rip is set to 0x40000, rax is symbolized under the name my_rax, two instructions are processed, and the symbolic expression for rcx is retrieved. Because the second instruction is a move from rax, the returned expression is a reference to the same variable. Constraints are then handed to an SMT solver through getModel, and the README shows the model coming back as my_rax:64 = 0xcc99, with the arithmetic check 0xcc99 ^ 0x1234 confirming 0xdead.
Three optional layers sit on top of that core. Lifting to LLVM and back, an SMT solver interface to Z3 and Bitwuzla, and expression synthesis. The README also lists SMT simplification passes, which matter because an unsimplified AST from a long basic block can be far larger than the constraint it encodes. Taint analysis is a separate mode: instead of asking what value a register holds, you mark data as tainted and ask where it flows.
Installing Triton with pip and running a first symbolic query
The README gives a pip route and a source route. The pip route is one command:
pip install triton-libraryThat installs the Python bindings and the underlying shared object. The source route is for people who need the optional interfaces, and it needs libcapstone 5.0.x at minimum, plus optional libboost, libpython, libz3, libbitwuzla and LLVM 12 or later. On Linux and macOS the README's sequence is a clone, a build directory, cmake, make and install:
$ git clone https://github.com/JonathanSalwan/Triton
$ cd Triton
$ mkdir build ; cd build
$ cmake ..
$ make -j3
$ sudo make installThe README states that LLVM and Bitwuzla are not compiled by default and gives the flags to enable them:
$ cmake -DLLVM_INTERFACE=ON -DCMAKE_PREFIX_PATH=$(llvm-config --prefix) -DBITWUZLA_INTERFACE=ON ..Once installed, the README's getting started example is the shortest real use. It symbolizes rax, executes an xor and a mov, and asks the solver for an input that makes rcx equal 0xdead:
from triton import *
ctx = TritonContext(ARCH.X86_64)
ctx.setConcreteRegisterValue(ctx.registers.rip, 0x40000)
ctx.symbolizeRegister(ctx.registers.rax, 'my_rax')
ctx.processing(Instruction(b"\x48\x35\x34\x12\x00\x00")) # xor rax, 0x1234
ctx.processing(Instruction(b"\x48\x89\xc1")) # mov rcx, rax
rcx_expr = ctx.getSymbolicRegister(ctx.registers.rcx)
print(ctx.getModel(rcx_expr.getAst() == 0xdead))The expected output is a model of the form {0: my_rax:64 = 0xcc99}. If you get an empty model, the constraint is unsatisfiable under the values you set, not a bug in the lift. The README also notes a separate script for Python autocompletion: run doc/autocomplete/generate_autocomplete.py and place the generated triton.pyi next to the Triton shared object.
Where Triton stops: path explosion, solver cost and thin documentation
The README is unusually direct about reliability: Triton is "a kind of a part-time project" and the authors ask not to be blamed "if it is not fully reliable". That sentence should be read as a maintenance statement, not modesty. The most recent release listed is v0.9 from 2022-02-09, while setup.py on the master branch carries VERSION_MAJOR 1, VERSION_MINOR 0, VERSION_PATCH 0 and RELEASE_CANDIDATE 4, so the 1.0 line exists in the tree and in a dev branch but has not been cut as a release.
The technical limits follow from the design. Symbolic execution of a loop produces one path per iteration, and Triton does not solve that for you; there is no path exploration engine in the README, only lifting, simplification and a solver interface. Solver cost is the second wall: getModel on a large unsimplified AST can be slow, which is why the simplification passes exist. If you cannot express your question as a bitvector constraint, Triton will not help, and a fuzzer or a dynamic tracer will be cheaper.
Documentation is uneven. The README points to Doxygen pages for the Python and C++ APIs and to a directory of Python examples, but it does not document rollback of context state, and it says nothing about how to add an architecture. The Windows instructions are the weakest part: they are written around Visual Studio 2015 and Python 3.6 paths, which is a strong hint that this path is less exercised than the Linux and macOS ones.
Triton against angr and Unicorn: library versus framework
The closest comparison is angr. angr is a binary analysis framework that includes a symbolic execution engine, a CFG recovery pass and a simulation manager that walks paths for you. Triton gives you the lifter and the solver bridge and leaves path selection to your code. If you want to ask "what input reaches this function" without writing a search loop, angr answers that out of the box; if you want to control exactly which instruction is lifted and how the AST is built, Triton's smaller surface is easier to reason about.
Unicorn is a different kind of neighbour. It is a CPU emulator: you run code and observe concrete registers and memory. Triton also emulates, and the README's example shows concrete values being set, but its purpose is the symbolic expression attached to that execution. A common pattern is to use an emulator to reach an interesting address and Triton to reason about what the code at that address computes. The two are not substitutes, and Triton's Dockerfile installs unicorn alongside z3-solver, lief and meson in the same Python environment, which suggests the maintainers expect that combination.
On solvers, Triton is a client rather than a competitor. The README lists interfaces to Z3 and Bitwuzla, and the Dockerfile builds Bitwuzla from source while pulling z3-solver from pip. Choosing between them is a solver question, not a Triton question.
Licence, upgrade cost and the 1.0 question
Triton is Apache-2.0, and the setup.py header repeats that the program is under the terms of the Apache License 2.0. For most users that is a permissive licence with a patent grant, and it does not force you to publish your analysis tool. The practical constraint is different: Triton links against Capstone, and optionally against Z3, Bitwuzla, Boost and LLVM, each with its own licence. If you redistribute a binary that bundles those, you are distributing their code too. That is a question for your own legal review, not something the README answers.
Upgrade cost is shaped by the release history. With the last tagged release at v0.9 in 2022 and a 1.0 release candidate present in setup.py, anyone tracking master is tracking an unreleased line. The repository's last push was on 2026-09-18, so development activity exists, but it is not reflected in a matching release tag. Pinning to v0.9 means missing whatever landed afterwards; tracking master means accepting that the API can move.
The build itself is the other recurring cost. Capstone 5.0.x is a hard dependency, and the README's macOS M1 note shows that Python library discovery can fail with "Could NOT find PythonLibs" unless PYTHON_EXECUTABLE, PYTHON_LIBRARIES and PYTHON_INCLUDE_DIRS are passed explicitly. On Windows the documented flags reference Visual Studio 2015 and Boost 1.61 paths. If you depend on the optional LLVM or Bitwuzla interfaces, budget time for a source build rather than a pip install.
Editorial conclusion
Adopt Triton when you need to write your own symbolic or taint analysis and want the instruction semantics handled for you; the pip package triton-library is the fastest way to find out whether the API fits. Skip it if you want a finished decompiler or a turnkey symbolic executor, since Triton is a library and the README describes it as a part-time project. Verify before committing: that the pip wheel matches your Python and platform, whether you need the LLVM or Bitwuzla interfaces built in, and which SMT solver your constraints will be sent to.
Frequently asked questions
What is Triton (JonathanSalwan/Triton)?
It is a dynamic binary analysis library that provides symbolic execution, taint analysis, an AST representation of instruction semantics, and an SMT solver interface, with C++ and Python APIs. The README describes it as a set of internal components for building your own program analysis tools.
How do I install Triton?
The README gives two routes: pip install triton-library, or a source build with a git clone, a build directory, cmake, make and make install. The source route needs libcapstone 5.0.x, with libboost, libpython, libz3, libbitwuzla and LLVM 12 or later as optional dependencies.
How do I install Triton on Windows?
The README documents using cmake to generate a .sln file for libTriton, passing paths for Boost, Python, Z3 and Capstone, and using setup.py to produce a debug triton.pyd. Those instructions are written around Visual Studio 2015 and Python 3.6 paths, so expect to adapt them.
How do I use Triton in Python?
Create a TritonContext for an architecture, optionally set concrete register values and symbolize registers, then pass Instruction objects to ctx.processing. Symbolic expressions come back from getSymbolicRegister, and ctx.getModel on an AST constraint returns a model.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/jonathansalwan-triton)