Skip to content

Commit

Permalink
adds an option to directly use ogre files as a loader (BinaryAnalysis…
Browse files Browse the repository at this point in the history
…Platform#1392)

The feature is implemented directly in the `Image.create` function so
that it can be used programmatically. The `backend` parameter can now
accept an explicit file path instead of the loader name. The
documentation of the `loader` command-line parameter is accordingly
updated.

To prevent clashes between existing loaders and filenames, only
existing filenames with explicit paths are treated as ogre
specifications, i.e., the path must start with `./`, `../`, or `/` in
Unix.

Example of usage,
```
$ bap testsuite/bin/arm-linux-gnueabi-echo -dogre:echo.ogre -dbir | grep print_endline
000007da: sub print_endline(print_endline_result)
00000804: print_endline_result :: out u32 = R0
0000031e: call @print_endline with return %00000320
$ sed 's/print_endline/printl/g' echo.ogre > echo.mangled.ogre
$ bap testsuite/bin/arm-linux-gnueabi-echo --loader=./echo.mangled.ogre -dbir | grep printl
00000339: call @printl with return %0000033b
000007df: sub printl(printl_result)
00000807: printl_result :: out u32 = R0
```

You can also use `bap specification ./exe` to obtain the initial OGRE
specification for a file (without disassembling it) and the edit it to
your taste. And, of course, you can write a specification from
scratch.
  • Loading branch information
ivg authored Jan 6, 2022
1 parent 5be8fef commit 6af0e78
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 12 deletions.
20 changes: 15 additions & 5 deletions lib/bap/bap.mli
Original file line number Diff line number Diff line change
Expand Up @@ -5506,10 +5506,20 @@ module Std : sig
type result = (t * Error.t list) Or_error.t

(** [create ?backend filename] creates an image of the file specified
specified by the [filename]. If [backend] is equal to "auto", then
all backends are tried in order. If only one backend can read this
file (i.e., there is no ambiguity), then image is returned. If
[backend] is not specified, then the LLVM backend is used. *)
by the [filename]. If [backend] is not specified, then
all availabe backends are used and their information is
merged. If the information provided by all backends agree (i.e.,
there's no conflicting information), then image is returned.
If [backend] is an explicit file path, then it is read as an
OGRE file and used for loading. Otherwise, [backend] should be
a name of one of the backends registered either with
[register_backend] or [register_loader]. See
[available_backends] for the list of available backends.
@since 2.5.0 accepts backend accepts an explicit file path,
note a file path is explicit if it exists and
[Fn.non Filename.is_implicit].
*)
val create : ?backend:string -> path -> result

(** [of_string ?backend ~data] creates an image from the specified
Expand Down Expand Up @@ -9084,7 +9094,7 @@ module Std : sig
is translated to,
{v
#11 := #9 + 13
#12 := 11 * #11
#12 := 11 * #11
#10 := #12 - 17
v}
@since 2.5.0 *)
Expand Down
17 changes: 13 additions & 4 deletions lib/bap_image/bap_image.ml
Original file line number Diff line number Diff line change
Expand Up @@ -664,15 +664,24 @@ let merge_loaders () : loader =

let get_loader = function
| None -> merge_loaders ()
| Some name when Sys.file_exists name &&
Fn.non Filename.is_implicit name ->
let local _ = match Ogre.Doc.from_file name with
| Error err -> Error err
| Ok doc -> Ok (Some doc) in
(module struct
let from_file = local
let from_data = local
end)
| Some name -> match Hashtbl.find backends name with
| Some loader -> loader
| None ->
let module Failure = struct
let fail _ = Result.failf "Unknown image loader %s" name ()
let fail _ = Result.failf "Unknown image loader %s" name () in
(module struct
let from_file = fail
let from_data = fail
end in
(module Failure)
end)


let invoke load data arg = match load arg with
| Ok (Some doc) -> from_spec (data arg) doc
Expand Down
18 changes: 15 additions & 3 deletions plugins/disassemble/disassemble_main.ml
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,18 @@ let input = Extension.Command.argument
let loader =
Extension.Command.parameter
~doc:"Use the specified loader.
Use the loader `raw' to load unstructured files"
The loader could be either an identifier or a filename. \
The filename has to be explicit, i.e., to start with an \
explicit reference to the root directory or to the current \
directory (e.g., $(b,./), or $(b,../), or $(b,/) in Unix). \
The contents of the file should be a well-formed OGRE \
document that contains the necessary meta-information \
about the binary. \
The default loader is named $(b,llvm) and uses LLVM loaders \
to parse the input binary and supports ELF, MachO, and COFF \
(including Windows PE), formats. \
To load unstructured files use the $(b,raw) loader and \
specify the loader parameters via the $(b,raw) plugin."
Extension.Type.(string =? "llvm")
"loader"

Expand Down Expand Up @@ -362,13 +373,14 @@ let save_knowledge ~had_knowledge ~update digest = function
| Some _ -> ()



let create_and_process input outputs passes loader target update kb ctxt =
let uses_file_loader = Sys.file_exists loader &&
Fn.non Filename.is_implicit loader in
let package = input in
let digest = make_digest [
Extension.Configuration.digest ctxt;
Caml.Digest.file input;
loader;
if uses_file_loader then Caml.Digest.file loader else loader;
] in
let had_knowledge = load_knowledge digest kb in
let input = Project.Input.load ~target ~loader input in
Expand Down

0 comments on commit 6af0e78

Please sign in to comment.