Skip to content
Binary Analysis Platform
Branch: master
Clone or download
gitoleg and ivg preserves random values in Primus (#958)
Primus generates a new random value (of course, if some generator policy
was assigned) every time `Env.get` is called with an unbound variable.

This PR changes this behaviour and makes Primus remember the generated
value, i.e. bind such variable first time it's value was requested.
Latest commit 52d625c Jun 27, 2019
Type Name Latest commit message Commit time
Failed to load latest commit information.
benchmarks Jane Street 0.11.x library compatibility + minor fixes (#820) Jan 31, 2019
doc updates documentation, copyrights, readme, and changes (#785) Mar 1, 2018
docker adds an apline based dockerfile (#952) May 28, 2019
lib preserves random values in Primus (#958) Jun 27, 2019
lib_test Fixing common typos (#946) Apr 11, 2019
man BAP Platform Feb 29, 2016
oasis Fixing common typos (#946) Apr 11, 2019
opam Jane Street 0.11.x library compatibility + minor fixes (#820) Jan 31, 2019
plugins adds x86 stack pointer handling for external calls (#955) Jun 16, 2019
src Fixing common typos (#946) Apr 11, 2019
testsuite @ c4a0d73 includes plugin name into the configuration path (#935) Mar 29, 2019
tools Jane Street 0.11.x library compatibility + minor fixes (#820) Jan 31, 2019
vagrant updates vagrant/docker files (#928) Mar 22, 2019
.gitignore primus updates and many more (#734) Feb 15, 2018
.gitmodules Integrate testsuite (#520) Jul 14, 2016
.merlin Jane Street 0.11.x library compatibility + minor fixes (#820) Jan 31, 2019 includes plugin name into the configuration path (#935) Mar 29, 2019 Jane Street 0.11.x library compatibility + minor fixes (#820) Jan 31, 2019 updates travis env (#851) Aug 3, 2018
.travis.yml Jane Street 0.11.x library compatibility + minor fixes (#820) Jan 31, 2019 includes plugin name into the configuration path (#935) Mar 29, 2019 Fixing common typos (#946) Apr 11, 2019
LICENSE updates documentation, copyrights, readme, and changes (#785) Mar 1, 2018
Makefile Bil test integration (#737) Mar 16, 2018 adds a link to odoc documentation (#949) Apr 29, 2019 extended configuration options for plugins (#420) May 5, 2016 Jane Street 0.11.x library compatibility + minor fixes (#820) Jan 31, 2019
configure primus updates and many more (#734) Feb 15, 2018 Jane Street 0.11.x library compatibility + minor fixes (#820) Jan 31, 2019 Dehackify cxx and llvm building (#557) Sep 21, 2016 BAP Platform Feb 29, 2016


License Join the chat at docs docs docs Build Status pip

The Carnegie Mellon University Binary Analysis Platform (CMU BAP) is a reverse engineering and program analysis platform that works with binary code and doesn't require the source code. BAP supports multiple architectures: ARM, x86, x86-64, PowerPC, and MIPS. BAP disassembles and lifts binary code into the RISC-like BAP Instruction Language (BIL). Program analysis is performed using the BIL representation and is architecture independent in a sense that it will work equally well for all supported architectures. The platform comes with a set of tools, libraries, and plugins. The documentation and tutorial are also available. The main purpose of BAP is to provide a toolkit for implementing automated program analysis. BAP is written in OCaml and it is the preferred language to write analysis, we have bindings to C, Python and Rust. The Primus Framework also provide a Lisp-like DSL for writing program analysis tools.

BAP is developed in CMU, Cylab and is sponsored by various grants from the United States Department of Defense, Siemens AG, and the Korea government, see sponsors for more information.

Table of contents



We provide binary packages packed for Debian and Red Hat derivatives. For other distributions we provide tgz archives. To install bap on a Debian derivative:

sudo dpkg -i {bap,libbap,libbap-dev}_1.6.0.deb

From sources

The binary release doesn't contain OCaml runtime, and is suitable only if you are not going to extend BAP using OCaml programming language. If you want to write your own analysis in OCaml, we recommend to use the OPAM package manager to install BAP and the development environment. After you've successfully installed OPAM, run the following commands:

opam init --comp=4.05.0              # install the compiler
eval `opam config env`               # activate opam environment
opam depext --install bap            # install bap

Got any problems? Then visit our troubleshooting page or contact us directly via our Gitter chat.



The BAP main frontend is a command line utility called bap. You can use it to explore the binary, run existing analysis, plugin your own behavior, load traces, and much more.

To dump a program in various formats use the --dump option (or its short equivalent, -d), For example, let's run bap on the x86_64-linux-gnu-echo file.

$ bap testsuite/bin/x86_64-linux-gnu-echo -d | grep 'sub print_endline' -A44
00000334: sub print_endline()
00000302: v483 := RBP
00000303: RSP := RSP - 8
00000304: mem := mem with [RSP, el]:u64 <- v483
00000305: RBP := RSP
00000307: RSP := RSP - 0x20
0000030e: mem := mem with [RBP + 0xFFFFFFFFFFFFFFE8, el]:u64 <- RDI
0000030f: RAX := mem[RBP + 0xFFFFFFFFFFFFFFE8, el]:u64
00000310: mem := mem with [RBP + 0xFFFFFFFFFFFFFFF8, el]:u64 <- RAX
00000311: goto %00000312

00000313: RAX := mem[RBP + 0xFFFFFFFFFFFFFFF8, el]:u64
00000314: RAX := pad:64[pad:32[mem[RAX]]]
00000315: v545 := low:8[low:32[RAX]]
0000031b: ZF := 0 = v545
0000031c: when ~ZF goto %0000032a
0000031d: goto %0000031e

0000031f: RDI := pad:64[0xA]
00000320: RSP := RSP - 8
00000321: mem := mem with [RSP, el]:u64 <- 0x400731
00000322: call @putchar with return %00000323

00000324: RSP := RBP
00000325: RBP := mem[RSP, el]:u64
00000326: RSP := RSP + 8
00000327: v693 := mem[RSP, el]:u64
00000328: RSP := RSP + 8
00000329: return v693

0000032b: RAX := mem[RBP + 0xFFFFFFFFFFFFFFF8, el]:u64
0000032c: RDX := RAX + 1
0000032d: mem := mem with [RBP + 0xFFFFFFFFFFFFFFF8, el]:u64 <- RDX
0000032e: RAX := pad:64[pad:32[mem[RAX]]]
0000032f: RAX := pad:64[extend:32[low:8[low:32[RAX]]]]
00000330: RDI := pad:64[low:32[RAX]]
00000331: RSP := RSP - 8
00000332: mem := mem with [RSP, el]:u64 <- 0x40071C
00000333: call @putchar with return %00000312

By default, the --dump options used the IR format, but you can choose from various other formats. Use the --list-formats option to get the list. However, formats are provided by plugins, so just because you don't see your preferred format listed doesn't mean you can't generate it. Check OPAM for plugins which may provide the format you want to read (the bap-piqi plugin provides protobuf, xml, and json, which cover many use cases).

To discover what plugins are currently available, use the --list-plugins option. A short description will be printed for each plugin. The --list-plugins option also accepts a list of tags, that will limit the output to plugins that match with the selected tags. For the list of tags use the --list-tags option. You can also use the opam search bap command, to get the information about bap packages, available from OPAM.

To get information about a specific plugin named <PLUGIN> use the --<PLUGIN>-help option, e.g., bap --llvm-help.

The bap utility works with whole binaries; if you have just few bytes with which you would like to tackle, then bap-mc is what you are looking for.


An idiomatic way of using BAP is to extend it with a plugin. Suppose, you want to write some analysis. For example, let's estimate the ratio of jump instructions to the total amount of instructions (a value that probably correlates with a complexity of a program).

So, let's do it. Create an empty folder, then open your favorite text editor and write the following program in a file:

open Core_kernel.Std
open Bap.Std

let counter = object
  inherit [int * int] Term.visitor
  method! enter_term _ _ (jmps,total) = jmps,total+1
  method! enter_jmp _ (jmps,total) = jmps+1,total

let main proj =
  let jmps,total = counter#run (Project.program proj) (0,0) in
  printf "ratio = %d/%d = %g\n" jmps total (float jmps /. float total)

let () = Project.register_pass' main

Before we run it, let's go through the code. The counter object is a visitor that has a state consisting of a pair of counters. The first counter keeps track of the number of jmp terms, and the second counter is incremented every time we enter any term. The main function just runs the counter. Finally, we register it with the Project.register_pass' function. Later the function can be invoked from a command line, and it will get a project data structure, that contains all the information that was recovered from a binary.

To compile the plugin simply run the following command:

bapbuild jmp.plugin

It is easier to run the pass, if it is installed, so let's do it:

bapbundle install jmp.plugin

Now we can test it:

$ bap /bin/true --pass=jmp
ratio = 974/7514 = 0.129625
$ bap /bin/ls --pass=jmp
ratio = 8917/64557 = 0.138126


OK, If the previous example doesn't make any sense to you, then you can try our Python bindings. Install them with pip install bap (you still need to install bap beforehand). Here is the same example, but in Python:

import bap
from bap.adt import Visitor

class Counter(Visitor) :
    def __init__(self):
        self.jmps = 0 = 0

    def enter_Jmp(self,jmp):
        self.jmps += 1

    def enter_Term(self,t): += 1

proj ='/bin/true')
count = Counter()
print("ratio = {0}/{1} = {2}".format(count.jmps,,


The same program in C will take too much space, and will not fit into the README format, but this is an example, of a simple diassembler in C:

#include <stdio.h>
#include <bap.h>

char data[] = "\x48\x8d\x00";

int main(int argc, const char **argv) {
    bap_init(argc, argv);

    if (bap_load_plugins() < 0) {
        fprintf(stderr, "Failed to load BAP plugins\n");
        return 1;

    bap_disasm_basic_t *dis = bap_disasm_basic_create(BAP_ARCH_X86_64);

    if (!dis) {
        fprintf(stderr, "can't create a disassembler: %s\n", bap_error_get());

    const int len = sizeof(data) - 1;
    bap_code_t *code = bap_disasm_basic_next(dis, data, sizeof(data) - 1, 0x80000);
    if (!code) {
        fprintf(stderr, "can't disassemble instruction: %s\n", bap_error_get());
        return 1;
    return 0;

The example can be compiled with the following command (assuming that the code is in the example.c file):

make LDLIBS=-lbap example


BAP also ships an interactive toplevel, aka REPL. This is a shell-like program that will interactively evaluate OCaml instructions and print the results. Just run:

$ baptop

Now, you can play with BAP. The following example will open a file, build callgraph of a program, and a control flow graph with a dominance tree of a function.

open Core_kernel.Std;;
open Bap.Std;;
open Graphlib.Std;;
let rooter = Rooter.Factory.find "byteweight" |> Option.value_exn;;
let proj = Project.create ~rooter (Project.Input.file "/bin/true") |> ok_exn;;
let prog = Project.program proj;;
let cg = Program.to_graph prog;;
let sub = Term.first sub_t prog |> Option.value_exn;;
let cfg = Sub.to_cfg sub;;
module G = Graphs.Ir;;
let entry = Option.value_exn (Term.first blk_t sub);;
let dom_tree = Graphlib.dominators (module G) cfg (G.Node.create entry);;

Note: if you do not want to use baptop or utop, then you can execute the following in any OCaml top-level:

#use "topfind";;
#require "";;


Other than API documentation, we have blog and wiki, where you can find some useful information. Also, we have a permanently manned chat in case of emergency. Look at the badge on top of the README file, and feel free to join.


BAP is a framework, so you don't need to change its code to extend it.We use the dependency injection principle with many injection points to allow the user to alter BAP behavior. However, bugs happen, so if you have any problems, questions or suggestions, please, don't hesitate to use our issue tracker. Submitting a pull request with a problem fix will make us really happy. However, we will only accepted pull requests that have MIT license.

If you wrote analysis with BAP, then don't hesitate to release it to OPAM, for the benefit of the community.


  • DARPA VET Project
  • Siemens AG
  • Institute for Information & communications Technology Promotion(IITP) grant funded by the Korea government(MSIT) (No.2015-0-00565,Development of Vulnerability Discovery Technologies for IoT Software Security)

Please, contact us if you would like to become a sponsor.

You can’t perform that action at this time.