Skip to content

Instantly share code, notes, and snippets.

@ivg
Last active March 16, 2019 08:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ivg/35a37397ab838aae3ae06df556f2d6bd to your computer and use it in GitHub Desktop.
Save ivg/35a37397ab838aae3ae06df556f2d6bd to your computer and use it in GitHub Desktop.
Double Dereferences under Tainted Branch Detector
(extend ddtbd)
;; debugging stuff
(option primus-propagate-taint-to-attributes)
(option print-bir-attr tainted-reg)
(option print-bir-attr tainted-ptr)
(option print-bir-attr tainted-regs)
(option print-bir-attr tainted-ptrs)
(option dump bir:out.bir)
(option primus-print-obs enter-term read)
(option primus-print-output trace)
open Core_kernel
open Bap.Std
open Bap_primus.Std
open Bap_taint.Std
open Bap_future.Std
open Format
include Self()
let max_length = Config.(param int "length" ~default:4)
(* a kind of program point *)
type point =
| Cond (* a tainted condition *)
| L1 (* the first load *)
| L2 (* the second access *)
type path = {
length : int; (* length of the tainted path *)
points : (point * addr) list; (* points of interest, for the report *)
step : point; (* on which state we are *)
}
let initial_state = {
length = 0;
points = [];
step = Cond;
}
let state = Primus.Machine.State.declare
~uuid:"10d552e4-9c4d-40ce-8bfe-50faed839dcf"
~name:"ddtbd"
(fun _ -> initial_state)
let get par =
Future.peek_exn (Config.determined par)
let string_of_point = function
| Cond -> "branch"
| L1 -> "first load"
| L2 -> "second load"
module Tracker(Machine : Primus.Machine.S) = struct
open Machine.Syntax
module Tracker = Taint.Tracker.Make(Machine)
module Eval = Primus.Interpreter.Make(Machine)
let init_track v =
Tracker.lookup v Taint.Rel.direct >>= fun td ->
if Set.is_empty td
then Machine.return ()
else Eval.pc >>= fun pc ->
info "path is tainted by the condition at %a" Addr.pp pc;
Machine.Local.update state ~f:(fun s -> {
s with length = get max_length;
points = (Cond,pc) :: s.points;
})
let on_jmp (_,dst) = init_track dst
let on_cnd cnd = init_track cnd
let push k p s = {s with step = k; points = (k,p)::s.points}
let next_step is_load s p = match s.step with
| Cond -> if is_load then push L1 p s else s
| L1 | L2 -> push L2 p s
(* ideally, we should make an observation... but let's print it just *)
let report s =
info "DDTBD Violation. Backtrace:@\n";
List.iter s.points ~f:(fun (p,pc) ->
info "%a: %s@\n" Addr.pp pc (string_of_point p));
Machine.return ()
let access ~is_load addr =
Machine.Local.get state >>= function
| {length=0} -> Machine.return () (* no tracking yet *)
| s -> (* we're close to a tainted branch *)
Tracker.lookup addr Taint.Rel.indirect >>= fun taints ->
if Set.is_empty taints
then Machine.return () (* but a load is not tained *)
else Eval.pc >>= fun pc -> (* we got a load, let's get the PC *)
info "%s on a tainted path at %a"
(if is_load then "load" else "store")
Addr.pp pc ;
let s = next_step is_load s pc in
Machine.Local.put state s >>= fun () ->
match s.step with
| L2 -> report s (* we reached the last state *)
| _ -> Machine.return ()
let decay _ =
Machine.Local.update state ~f:(fun s ->
let length = max 0 (s.length - 1) in
if length = 0 && s.length <> 0 then info "path has decayed";
if length = 0 then initial_state
else {s with length})
let init () = Machine.sequence Primus.Interpreter.[
eval_cond >>> on_cnd;
jumping >>> on_jmp;
loading >>> access ~is_load:true;
storing >>> access ~is_load:false;
leave_term >>> decay;
]
end
let () = Config.when_ready (fun _ ->
Primus.Machine.add_component (module Tracker))
(parameter taint-source malloc_result "a source of the taint")
(parameter decay 100 "the number of terms while the trail is hot")
(parameter depth 10000 "a depth of analysis")
(parameter entry-points all-subroutines "where to search")
(option taint-reg ${taint-source})
(option run)
(option primus-promiscuous-mode)
(option primus-greedy-scheduler)
(option primus-limit-max-length 10000)
(option primus-propagate-taint-from-attributes)
(option report-progress)
@ivg
Copy link
Author

ivg commented Apr 17, 2018

download the provided recipes and run with

bap ./exe --recipe ddtbd

or

bap ./exe --recipe ddtbd-debug

the latter will also propagate taint to the IR terms and dump them. And create a trace file.

@fubuki8087
Copy link

Hi,

BAP has updated. Now the version is 1.6.0-dev. Syntax is changed.

And could I compile this ddtbd to plugin?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment