Skip to content
ivg edited this page Dec 10, 2014 · 31 revisions

Introduction

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.

Conventions

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 .

Requirements for the Transport Layer

The transport layer should provide a reliable message delivery facilities. Messages must be sent and received in an atomic way. The order of messages must not shuffle. Also, transport layer should provide authentication and ensure the security of the channel, in assumptions that the transported information can be evaluated.

Session

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.

Requests

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-string" : {
            "title": "Command use-string",
            "description": "Target BAP onto specified data represented by a string",
            "type" : {"$ref" : "#/definitions/use-string"},
        },

        "set-position" : {
            "title": "Command set-position",
            "description": "Target BAP onto specified position in the data",
            "type" : {"$ref" : "#/definitions/set-position"},
        },

        "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": {
                "path" : {
                    "description" : "file path",
                    "type" : "string",
                },

                "loader" : {
                    "description" : "what backend to use",
                    "type" : "string",
                }
            },
            "required" : ["path"]
        },
        "use-string" : {
            "type": "object",
            "properties": {
                "data" : {
                    "description" : "actual data",
                    "type" : "string",
                },

                "format" : {
                    "description" : "how to interpret the string",
                    "type" : "string",
                    "oneOf" : ["escaped-ascii"]
                },

                "arch" : {
                    "description" : "target architecture",
                    "type" : "string",
                }
            },
            "required" : ["data", "format", "arch"],
        },

        "set-position" : {
            "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",
                }
            }
        }
    }
}

init

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.

use-file

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.

Example of the request

{
    "id" : 12,
    "use-file" : {
        "path"    : "/bin/ls",
        "loader"  : "bap-elf",
    }
}

use-string

The use-string may be used instead of use-file request if the calling side want 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-string" : {
        "format"  : "escaped-ascii",
        "arch"    : "arm",
        "data"    : "\\x10\\x12"
    }
}

set-position

The set-position message is used to target Server at the specific point in the data. It can be also used to limit the extent of data.

Example:

{
    "id" : 255,
    "set-position" : {
        "offset"  : "0",
        "size"    : "1024"
    }
}

disassemble

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-string command.

The server must respond with insns or error messages. The server may still response with insns message even when the error has occurred. In that case insns message should be sent before the error command.

Example:

{
    "id" : 17,
    "disassemble" : {
        "stop-conditions" : ["isCall()"]
    }
}

Responses

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"}}
                    }
                },
                "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"
            ]
        }
    }
}

error

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 specified request should be discarded.

  • warning the corresponding request can not be satisfied to full extent. All other responses to the request may be considered valid.

capabilities

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,
                }
            ]
        }
    ]
}

image

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()"
    }
}

symbols

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",
        }
    ]
}

sections

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,
        }
    ]
}

insns

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))"]
        }
    ]
}