-
Notifications
You must be signed in to change notification settings - Fork 274
Public API [draft]
This documents describes Binary Analysis Platform (BAP) library public API. The current state of the document is draft. Everything can be changed without further notice.
- Introduction
- Conventions
- Transport Layer
- Session
- Requests
init
use-file
use-data
set-view
disassemble
- Responses
error
capabilities
image
symbols
sections
insns
This is a draft for a public API for BAP Server. The BAP server is an application that can provide BAP as a service to the third party applications, written in any language. We will refer to a BAP server as SERVER, and to third party application as a CLIENT. This document describes only the application protocol, the underlying transport protocol is out of the scope of the document.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 .
Transport Layer is used to deliver messages and data. Different transport layers may be used to deliver different data. For example, while requests and responses may be delivered using http, data maybe delivered using ZMQ, network sockets or file system. Data is referenced using Uniform Resource Identifiers uri.
Uri must fully identify the contents of the file, i.e., two objects with the same uri must have the same data.
Session consists of a series of interactions. Each interaction must consist of at one request and at least one response. Request and response are messages. Client must be an initiator of the session. Client must not send responses, and server must not send requests. Server must send messages only in response to the client's requests. Server may send more than one response to one request.
The request should be a JSON
object of the following schema:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Request",
"description": "A request from Client to Server",
"type": "object",
"properties": {
"id" : {
"description" : "unique for the client side identifier",
"type" : "integer",
},
"init" : {
"title" : "initialize",
"description" : "initialize a session",
"type" : {"$ref" : "#definitions/init"}
},
"use-file" : {
"title": "Command use-file",
"description": "Target BAP onto specified path",
"type" : {"$ref" : "#/definitions/use-file"},
},
"use-data" : {
"title": "Command use-data",
"description": "Target BAP onto specified data represented by a string",
"type" : {"$ref" : "#/definitions/use-data"},
},
"set-view" : {
"title": "Command set-view",
"description": "Target BAP onto specified position in the data",
"type" : {"$ref" : "#/definitions/seek"},
},
"disassemble" : {
"title" : "Disassemble command",
"description": "Disassemble the specified region",
"type" : {"$ref" : "#/definitions/disassemble"},
}
},
"required" : ["id"],
"minProperties" : 1,
"maxProperties" : 2,
"definitions" : {
"init" : {
"type" : "object",
"propeties" : {
"version" : "string"
}
},
"use-file" : {
"type" : "object",
"properties": {
"uri" : {
"description" : "file path",
"type" : "uri",
},
"loader" : {
"description" : "what backend to use",
"type" : "string",
}
},
"required" : ["path"]
},
"use-data" : {
"type": "object",
"properties": {
"uri" : {
"description" : "resource locator",
"type" : "uri",
},
"arch" : {
"description" : "target architecture",
"type" : "string",
},
"address" : {
"description" : "virtual address of the first byte",
"type" : "int",
"default" : 0,
}
},
"required" : ["uri", "arch"],
},
"view" : {
"type": "object",
"properties": {
"offset" : {
"description" : "offset in octets from the start of the data",
"type" : "integer",
"minimum" : 0,
},
"size" : {
"description" : "maximum offset",
"type" : "integer",
"minimum" : 1,
}
},
"required" : ["offset"]
},
"disassemble" : {
"type": "object",
"properties": {
"stop-conditions" : {
"description" : "A set of stop conditions",
"type" : "stringArray",
}
}
}
}
}
The init
request is sent to initiate a session. Client must not send
any requests before the init
request.
Server must respond to this request with error
or capabilities
message.
The use-file
request is sent to direct the server to use the
specified file as a target of analysis. Server must respond to this
request with either of this responses:
error
image
The server may react with additional responses, like symbols
or
sections
.
The file must be a properly encoded binary container in one of the
supported formats, see capabilities. For loading raw
binary chunks into bap see use-data
command. Despite the name use-file
can point to any resource location.
Client may send several use-file
or use-data
request
per session. Each time Server receives such request it will change
current data.
Example of the request:
{
"id" : 12,
"use-file" : {
"path" : "/bin/ls",
"loader" : "bap-elf",
}
}
The use-data
may be used if the calling side wants to provide an
arbitrary data for analyzing. The data shouldn't contain any meta
data, and it wouldn't be parsed as a binary container. Since no meta
data exists, a client side must define an instruction set, using
arch
property.
The server must respond to this request with the error
or empty
responses.
Example:
{
"id" : 15,
"use-data" : {
"arch" : "arm",
"uri" : "ipc:/tmp/bap/15"
}
}
The set-view
message is used to narrow the region of analysis. The
narrowing must be active until any of the following messages is issued
by Client:
Example:
{
"id" : 255,
"set-view" : {
"offset" : "0",
"size" : "1024"
}
}
The disassemble
command is used to start the disassembling of the
specified data. The data must be specified before this command by a
client side with either use-file
or
use-data
commands.
The server must respond with insns
or error
messages. The server
may still response with insns
message even when the error has
occurred.
Example:
{
"id" : 17,
"disassemble" : {
"stop-conditions" : ["isCall()"]
}
}
Response message must be a JSON
object with the following schema:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Response",
"description": "A reply from Server to Client",
"type": "object",
"properties": {
"id" : {
"description" : "identifier unique for the server side",
"type" : "integer",
},
"request" : {
"description": "An id of the request to which we're replying",
"type" : "interger",
},
"error" : {
"description" : "the request cannot be satisfied",
"type" : {"$ref" : "#/definitions/error"}
},
"capabilities" : {
"description" : "a set of capabilities support by Server",
"type" : {"$ref" : "#/definitions/capabilities"}
},
"image" : {
"description" : "binary container description",
"type" : {"$ref" : "#/definitions/image"}
},
"symbols" : {
"description" : "the array of symbols",
"type" : "array",
"minItems" : 1,
"uniqueItems" : true,
"items" : {"type" : {"$ref" : "#/definitions/symbol"}}
},
"sections" : {
"description" : "the array of sections",
"type" : "array",
"minItems" : 1,
"uniqueItems" : true,
"items" : {"type" : {"$ref" : "#/definitions/section"}}
},
"insns" : {
"description" : "the array of insns",
"type" : "array",
"minItems" : 1,
"items" : {"type" : {"$ref" : "#/definitions/insn"}}
},
},
"required" : ["id", "request"],
"minProperties" : 2,
"maxProperties" : 3,
"definitions" : {
"error" : {
"type" : "object",
"properties" : {
"description" : {"type" : "string"},
"severity" : {
"type" : "string",
"oneOf" : ["critical", "error", "warning"]
}
},
"required" : ["description", "severity"]
},
"capabilities" : {
"type" : "array",
"minItems" : 1,
"items" : {
"type" : "object",
"properties" : {
"version" : {
"description" : "protocol version",
"type" : "stringArray"
},
"loaders" : {
"description" : "a set of supported file loaders",
"type" : "array",
"minItems" : 1,
"uniqueItems" : true,
"items" : {"type" : {"$ref" : "#/definitions/loader"}}
},
"disassemblers" : {
"description" : "a set of supported disassemblers backend",
"type" : "array",
"minItems" : 1,
"uniqueItems" : true,
"items" : {"type" : {"$ref" : "#/definitions/disassembler"}}
},
"transports" : {
"description" : "Supported set of transport protocols",
"type" : "array",
"minItems" : 1,
"uniqueItems" : true,
"items" : {"type" : {"$ref" : "string"}}
}
},
"required" : ["version", "loaders", "disassemblers"]
},
},
"symbol" : {
"type" : "object",
"properties" : {
"name" : {"type" : "string"},
"addr" : {"type" : "integer"},
"size" : {"type" : "integer"},
"is_function" : {"type" : "boolean"},
},
"required" : ["addr"]
},
"section" : {
"type" : "object",
"properties" : {
"name" : {"type" : "string"},
"addr" : {"type" : "integer"},
"size" : {"type" : "integer"},
"off" : {"type" : "integer"},
"perm" : {
"type" : "array",
"minItems" : 1,
"maxItems" : 3,
"uniqueItems" : true,
"items" : {"type" : "string", "oneOf" : ["r", "w", "x"]}
},
},
"required" : ["addr", "off", "perm", "size"]
},
"image" : {
"type" : "object",
"properties" : {
"arch" : {"type" : "string"},
"entry-point" : {"type" : "integer"},
"addr-size" : {
"type" : "integer",
"oneOf" : [32, 64],
},
"endian" : {
"type" : "string",
"oneOf" : ["LittleEndian()", "BigEndian()"]
}
}
},
"insn" : {
"type" : "object",
"properties" : {
"name" : {
"title" : "Instruction name",
"description" : "Name accroding to the disassembler backend in use",
"type" : "string",
},
"size" : {
"description" : "Instruction size in bytes",
"type" : "integer"
},
"addr" : {
"description" : "Address of the first byte of the instruction",
"type" : "integer"
},
"asm" : {
"description" : "Instruction representation in a target assembler",
"type" : "string"
},
"ops" : {
"descrption" : "An array of operators, according to the disassembler",
"type" : "array",
"minItems" : 0,
"items" : {"type" : "string"}
},
"kinds" : {
"descrption" : "A set of kinds appropriate for the instruction",
"type" : "array",
"minItems" : 0,
"uniqueItems" : true,
"items" : {"type" : "string"}
},
"target" : {
"title" : "Target Instruction",
"description" : "Target specific machine instruction",
"type" : "string"
},
"bil" : {
"description" : "BIL Instructions",
"type" : "array",
"minItems" : 0,
"items" : {"type" : "string"}
}
},
"required" : ["size", "addr", "asm"]
},
"loader" : {
"description" : "Capabilities of binary container parser",
"type" : "object",
"properties" : {
"name" : { "type" : "string"},
"format" : {
"description" : "File format",
"type" : "string"
},
"architecture" : {
"description" : "Supported architecture",
"type" : "string",
},
"symbols" : {
"description" : "Capability to read symbol information",
"type" : "array",
"minItems" : 0,
"items" : {
"type" : "string",
"anyOf" : ["symtab", "debug"],
}
}
},
"required" : ["name", "format", "architecture", "symbols"]
},
"disassembler" : {
"description" : "capabilities of disassembler",
"type" : "object",
"properties" : {
"name" : { "type" : "string"},
"architecture" : {
"description" : "Disassembler instruction set",
"type" : "string",
},
"kinds" : {
"description" : "set of understandable kinds",
"type" : "array",
"items" : {"type" : "string"},
"minItems" : 1,
"uniqueItems" : true
},
"has-name" : {
"description" : "can provide instruction name",
"type" : "boolean",
},
"has-ops" : {
"description" : "can provide instruction operands",
"type" : "boolean",
},
"has-target" : {
"description" : "can provide lifted target instruction",
"type" : "boolean",
},
"has-bil" : {
"description" : "can provide BIL",
"type" : "boolean",
},
},
"required" : [
"name", "architecture", "kinds",
"has-name", "has-ops", "has-target", "has-bil"
]
}
}
}
Server may use this message as a respond to any request. The
description
field shall contain a printable and human readable
description of the occurred condition. The severity
field values
have the following meaning:
-
critical
an unrecoverable error has occurred. All further request may contain invalid data or may be ignored. Client should start new session. -
error
the corresponding request cannot be satisfied. All following responses to the specifiedrequest
should be discarded. -
warning
the corresponding request can not be satisfied to full extent. All other responses to therequest
may be considered valid.
This message should be sent in response to the init
request, if
Server supports the requested protocol version. Otherwise Server must
respond with an error
. Message contains a description of features,
that Server can provide to Client. Each set of features is tagged by a
protocol version. Example:
{
"id" : 0,
"request" : 0,
"capabilities" : [
{
"version" : "1.2.1-alpha",
"loaders" : [
{
"name" : "bap-elf",
"formats" : ["ELF"],
"architecture" : "386",
"symbols" : ["debug"]
},
{
"name" : "bap-elf",
"formats" : ["ELF"],
"architecture" : "ARM",
"symbols" : ["debug"]
}
],
"disassemblers" : [
{
"name" : "llvm",
"architecture" : "arm",
"kinds" : [
"Kind()", "Having_side_effects()",
"Affecting_control()", "Branch()",
"ConditionalBranch()", "UnconditionalBranch()",
"IndirectBranch()", "Return()", "Call()",
"Barrier()", "Terminator()", "May_affect_control_flow()",
"May_load()", "May_store()"
],
"has-name" : true,
"has-ops" : true,
"has-target" : true,
"has-bil" : true,
},
{
"name" : "llvm",
"architecture" : "x86",
"kinds" : [
"Kind()", "Having_side_effects()",
"Affecting_control()", "Branch()",
"ConditionalBranch()", "UnconditionalBranch()",
"IndirectBranch()", "Return()", "Call()",
"Barrier()", "Terminator()", "May_affect_control_flow()",
"May_load()", "May_store()"
],
"has-name" : true,
"has-ops" : true,
"has-target" : false,
"has-bil" : false,
}
],
"transports : ["ipc", "socket", "file"],
}
]
}
This message must be sent in response to use-file
command, if
there're no error conditions of error
or critical
severity. It
contains the most information about loaded file (aka, image).
{
"id" : 128,
"request" : 17,
"image" : {
"arch" : "ARM",
"entry-point" : 40000000,
"addr-size" : 32,
"endian" : "LittleEndian()"
}
}
This message must be sent in response to use-file
command, if no
error conditions have occurred. Server may still send this message, if
error conditions have occurred. This message contains information
about symbols found in the binary container. Example
{
"id" : 3423,
"request" : 12,
"symbols" : [
{
"name" : "get_args",
"addr" : 2147745792,
"size" : 256,
"is_function" : "true",
}
]
}
This message must be sent in response to use-file
command, if no error conditions have occurred. Server may still send
this message, if error conditions have occurred. This message contains
information about sections found in the binary container. Example
{
"id" : 34324,
"request" : 12,
"sections" : [
{
"name" : "data",
"perm" : ["r"],
"addr" : 2147483648,
"size" : 16384,
"off" : 64,
}
]
}
This message must be send in response to disassemble
command if no
error conditions have occurred. Server may still send this message, if
error condition have occurred. Server must send all instructions
disassembled by the request
in one message.
Example:
{
"id" : 4256,
"request" : 17,
"insns" : [
{
"name" : "MOVi",
"size" : 4,
"addr" : 262144,
"asm" : "mov r0, #5",
"ops" : [ "Reg(\"R0\")", "Imm(5)", "Imm(14)", "Reg(\"Nil\")", "Reg(\"Nil\")"],
"kinds" : ["Call()"],
"target": "MOVi(Reg(R0()), Imm(5), Imm(14), Reg(Nil()), Reg(Nil()))",
"bil" : ["Move(Var('R0', Imm(32)), Int(5))"]
}
]
}
ops
items, target
and bil
uses ADT format to represent data.