Commit eaf51726 by Enkelmann Committed by Thomas Barabosch

Corrected dune linter warnings, linter warnings are now handled like errors. (#20)

parent 09f6dbb0
.PHONY: all clean test uninstall .PHONY: all clean test uninstall
all: all:
dune build --profile release dune build
dune install dune install
cd plugins/cwe_checker; make all; cd ../.. cd plugins/cwe_checker; make all; cd ../..
cd plugins/cwe_checker_emulation; make all; cd ../.. cd plugins/cwe_checker_emulation; make all; cd ../..
...@@ -8,7 +8,7 @@ all: ...@@ -8,7 +8,7 @@ all:
cd plugins/cwe_checker_type_inference_print; make all; cd ../.. cd plugins/cwe_checker_type_inference_print; make all; cd ../..
test: test:
dune runtest --profile release # TODO: correct all dune linter warnings so that we can remove --profile release dune runtest
cd test/artificial_samples; scons; cd ../.. cd test/artificial_samples; scons; cd ../..
pytest -v pytest -v
......
...@@ -52,7 +52,7 @@ If you plan to develop cwe_checker, it is recommended to build it using the prov ...@@ -52,7 +52,7 @@ If you plan to develop cwe_checker, it is recommended to build it using the prov
- Opam 2.0.2 - Opam 2.0.2
- dune >= 1.6 - dune >= 1.6
- BAP 1.6 (and its dependencies) - BAP 1.6 (and its dependencies)
- yojson >= 1.4.1 - yojson >= 1.6.0
- alcotest >= 0.8.3 - alcotest >= 0.8.3
- Sark (latest) for IDA Pro annotations - Sark (latest) for IDA Pro annotations
- pytest >= 3.5.1 - pytest >= 3.5.1
......
...@@ -14,7 +14,7 @@ dev-repo: "git+https://github.com/fkie-cad/cwe_checker" ...@@ -14,7 +14,7 @@ dev-repo: "git+https://github.com/fkie-cad/cwe_checker"
depends: [ depends: [
"ocaml" {>= "4.05"} "ocaml" {>= "4.05"}
"dune" {>= "1.6"} "dune" {>= "1.6"}
"yojson" {>= "1.4.1"} "yojson" {>= "1.6.0"}
"bap" {>= "1.6"} "bap" {>= "1.6"}
"alcotest" {>= "0.8.3"} "alcotest" {>= "0.8.3"}
"core_kernel" {>= "v0.11" & < "v0.12"} "core_kernel" {>= "v0.11" & < "v0.12"}
......
...@@ -57,13 +57,13 @@ let partial_run project config modules = ...@@ -57,13 +57,13 @@ let partial_run project config modules =
let tid_address_map = Address_translation.generate_tid_map program in let tid_address_map = Address_translation.generate_tid_map program in
let json = Yojson.Basic.from_file config in let json = Yojson.Basic.from_file config in
Log_utils.info "[cwe_checker] Just running the following analyses: %s." modules; Log_utils.info "[cwe_checker] Just running the following analyses: %s." modules;
List.iter (String.split modules ~on: ',') ~f:(fun cwe -> try List.iter (String.split modules ~on: ',') ~f:(fun cwe ->
begin let cwe_mod = match List.find known_modules ~f:(fun x -> x.name = cwe) with
let cwe_mod = List.find_exn known_modules ~f:(fun x -> x.name = cwe) in | Some(module_) -> module_
let program = Project.program project in | None -> failwith "[CWE_CHECKER] Unknown CWE module" in
execute_cwe_module cwe_mod json program project tid_address_map let program = Project.program project in
end execute_cwe_module cwe_mod json program project tid_address_map
with Not_found -> failwith "[CWE_CHECKER] Unknown CWE module") )
let full_run project config = let full_run project config =
let program = Project.program project in let program = Project.program project in
......
...@@ -6,7 +6,7 @@ let (+), (-) = Bitvector.(+), Bitvector.(-) ...@@ -6,7 +6,7 @@ let (+), (-) = Bitvector.(+), Bitvector.(-)
let (>) x y = Bitvector.(>) (Bitvector.signed x) (Bitvector.signed y) let (>) x y = Bitvector.(>) (Bitvector.signed x) (Bitvector.signed y)
let (<) x y = Bitvector.(<) (Bitvector.signed x) (Bitvector.signed y) let (<) x y = Bitvector.(<) (Bitvector.signed x) (Bitvector.signed y)
let (>=) x y = Bitvector.(>=) (Bitvector.signed x) (Bitvector.signed y) (* let (>=) x y = Bitvector.(>=) (Bitvector.signed x) (Bitvector.signed y) *)
let (<=) x y = Bitvector.(<=) (Bitvector.signed x) (Bitvector.signed y) let (<=) x y = Bitvector.(<=) (Bitvector.signed x) (Bitvector.signed y)
let (=) x y = Bitvector.(=) x y let (=) x y = Bitvector.(=) x y
...@@ -74,16 +74,6 @@ let rec get mem_region pos = ...@@ -74,16 +74,6 @@ let rec get mem_region pos =
else else
Some(Error(())) (* pos intersects some data, but does not equal its starting address*) Some(Error(())) (* pos intersects some data, but does not equal its starting address*)
(* Helper function. Removes all elements with position <= pos. *)
let rec remove_until mem_region pos =
match mem_region with
| [] -> []
| hd :: tl ->
if hd.pos <= pos then
remove_until tl pos
else
mem_region
let rec remove mem_region ~pos ~size = let rec remove mem_region ~pos ~size =
let () = if pos + size < pos then failwith "[CWE-checker] element out of bounds for mem_region" in let () = if pos + size < pos then failwith "[CWE-checker] element out of bounds for mem_region" in
...@@ -91,11 +81,11 @@ let rec remove mem_region ~pos ~size = ...@@ -91,11 +81,11 @@ let rec remove mem_region ~pos ~size =
| [] -> [] | [] -> []
| hd :: tl -> | hd :: tl ->
if hd.pos + hd.size <= pos then if hd.pos + hd.size <= pos then
hd :: remove tl pos size hd :: remove tl ~pos ~size
else if pos + size <= hd.pos then else if pos + size <= hd.pos then
mem_region mem_region
else else
let mem_region = remove tl pos size in let mem_region = remove tl ~pos ~size in
let mem_region = let mem_region =
if hd.pos + hd.size > pos + size then if hd.pos + hd.size > pos + size then
error_elem ~pos:(pos + size) ~size:(hd.pos + hd.size - (pos + size)) :: mem_region error_elem ~pos:(pos + size) ~size:(hd.pos + hd.size - (pos + size)) :: mem_region
...@@ -111,12 +101,12 @@ let rec remove mem_region ~pos ~size = ...@@ -111,12 +101,12 @@ let rec remove mem_region ~pos ~size =
let rec mark_error mem_region ~pos ~size = let rec mark_error mem_region ~pos ~size =
let () = if pos + size < pos then failwith "[CWE-checker] element out of bounds for mem_region" in let () = if pos + size < pos then failwith "[CWE-checker] element out of bounds for mem_region" in
match mem_region with match mem_region with
| [] -> (error_elem pos size) :: [] | [] -> (error_elem ~pos ~size) :: []
| hd :: tl -> | hd :: tl ->
if hd.pos + hd.size <= pos then if hd.pos + hd.size <= pos then
hd :: (mark_error tl pos size) hd :: (mark_error tl ~pos ~size)
else if pos + size <= hd.pos then else if pos + size <= hd.pos then
(error_elem pos size) :: mem_region (error_elem ~pos ~size) :: mem_region
else else
let start_pos = min pos hd.pos in let start_pos = min pos hd.pos in
let end_pos_plus_one = max (pos + size) (hd.pos + hd.size) in let end_pos_plus_one = max (pos + size) (hd.pos + hd.size) in
...@@ -130,22 +120,22 @@ let rec merge mem_region1 mem_region2 ~data_merge = ...@@ -130,22 +120,22 @@ let rec merge mem_region1 mem_region2 ~data_merge =
| ([], value) -> value | ([], value) -> value
| (hd1 :: tl1, hd2 :: tl2) -> | (hd1 :: tl1, hd2 :: tl2) ->
if hd1.pos + hd1.size <= hd2.pos then if hd1.pos + hd1.size <= hd2.pos then
hd1 :: merge tl1 mem_region2 data_merge hd1 :: merge tl1 mem_region2 ~data_merge
else if hd2.pos + hd2.size <= hd1.pos then else if hd2.pos + hd2.size <= hd1.pos then
hd2 :: merge mem_region1 tl2 data_merge hd2 :: merge mem_region1 tl2 ~data_merge
else if hd1.pos = hd2.pos && hd1.size = hd2.size then else if hd1.pos = hd2.pos && hd1.size = hd2.size then
match (hd1.data, hd2.data) with match (hd1.data, hd2.data) with
| (Ok(data1), Ok(data2)) -> begin | (Ok(data1), Ok(data2)) -> begin
match data_merge data1 data2 with match data_merge data1 data2 with
| Some(Ok(value)) -> { hd1 with data = Ok(value) } :: merge tl1 tl2 ~data_merge | Some(Ok(value)) -> { hd1 with data = Ok(value) } :: merge tl1 tl2 ~data_merge
| Some(Error(_)) -> {hd1 with data = Error(())} :: merge tl1 tl2 ~data_merge | Some(Error(_)) -> {hd1 with data = Error(())} :: merge tl1 tl2 ~data_merge
| None -> merge tl1 tl2 data_merge | None -> merge tl1 tl2 ~data_merge
end end
| _ -> { hd1 with data = Error(()) } :: merge tl1 tl2 ~data_merge | _ -> { hd1 with data = Error(()) } :: merge tl1 tl2 ~data_merge
else else
let start_pos = min hd1.pos hd2.pos in let start_pos = min hd1.pos hd2.pos in
let end_pos_plus_one = max (hd1.pos + hd1.size) (hd2.pos + hd2.size) in let end_pos_plus_one = max (hd1.pos + hd1.size) (hd2.pos + hd2.size) in
let mem_region = merge tl1 tl2 data_merge in let mem_region = merge tl1 tl2 ~data_merge in
mark_error mem_region ~pos:start_pos ~size:(end_pos_plus_one - start_pos) mark_error mem_region ~pos:start_pos ~size:(end_pos_plus_one - start_pos)
...@@ -156,8 +146,8 @@ let rec equal (mem_region1:'a t) (mem_region2:'a t) ~data_equal : bool = ...@@ -156,8 +146,8 @@ let rec equal (mem_region1:'a t) (mem_region2:'a t) ~data_equal : bool =
if hd1.pos = hd2.pos && hd1.size = hd2.size then if hd1.pos = hd2.pos && hd1.size = hd2.size then
match (hd1.data, hd2.data) with match (hd1.data, hd2.data) with
| (Ok(data1), Ok(data2)) when data_equal data1 data2 -> | (Ok(data1), Ok(data2)) when data_equal data1 data2 ->
equal tl1 tl2 data_equal equal tl1 tl2 ~data_equal
| (Error(()), Error(())) -> equal tl1 tl2 data_equal | (Error(()), Error(())) -> equal tl1 tl2 ~data_equal
| _ -> false | _ -> false
else else
false false
......
...@@ -7,7 +7,7 @@ let version = "0.1" ...@@ -7,7 +7,7 @@ let version = "0.1"
let collect_muliplications = Exp.fold ~init:0 (object let collect_muliplications = Exp.fold ~init:0 (object
inherit [Int.t] Exp.visitor inherit [Int.t] Exp.visitor
method! enter_binop op o1 o2 binops = match op with method! enter_binop op _o1 _o2 binops = match op with
| Bil.TIMES | Bil.LSHIFT -> binops + 1 | Bil.TIMES | Bil.LSHIFT -> binops + 1
| _ -> binops | _ -> binops
end) end)
...@@ -17,7 +17,7 @@ let contains_multiplication d = ...@@ -17,7 +17,7 @@ let contains_multiplication d =
let binops = collect_muliplications rhs in let binops = collect_muliplications rhs in
binops > 0 binops > 0
let check_multiplication_before_symbol proj prog sub blk jmp tid_map symbols = let check_multiplication_before_symbol _proj _prog _sub blk jmp tid_map symbols =
Seq.iter (Term.enum def_t blk) Seq.iter (Term.enum def_t blk)
~f:(fun d -> if contains_multiplication d then ~f:(fun d -> if contains_multiplication d then
Log_utils.warn Log_utils.warn
......
open Core_kernel open Core_kernel
open Bap.Std open Bap.Std
open Unix
(* TODO: IVG via gitter: (* TODO: IVG via gitter:
I see, so you need the CU information, and yes BAP doesn't provide this. I see, so you need the CU information, and yes BAP doesn't provide this.
...@@ -19,16 +19,6 @@ but in general case it is better to use the approach described above. *) ...@@ -19,16 +19,6 @@ but in general case it is better to use the approach described above. *)
let name = "CWE215" let name = "CWE215"
let version = "0.1" let version = "0.1"
let read_lines in_chan =
let lines = ref [] in
try
while true; do
lines := input_line in_chan :: !lines
done; !lines
with End_of_file ->
In_channel.close in_chan;
List.rev !lines
(* TODO: check if program contains strings like "DEBUG"*) (* TODO: check if program contains strings like "DEBUG"*)
let check_cwe _ project _ _ _ = let check_cwe _ project _ _ _ =
match Project.get project filename with match Project.get project filename with
...@@ -36,7 +26,7 @@ let check_cwe _ project _ _ _ = ...@@ -36,7 +26,7 @@ let check_cwe _ project _ _ _ =
let cmd = Format.sprintf "readelf --debug-dump=decodedline %s | grep CU" fname in let cmd = Format.sprintf "readelf --debug-dump=decodedline %s | grep CU" fname in
try try
let in_chan = Unix.open_process_in cmd in let in_chan = Unix.open_process_in cmd in
read_lines in_chan |> List.iter ~f:(fun l -> Log_utils.warn "[%s] {%s} (Information Exposure Through Debug Information) %s" name version l) In_channel.input_lines in_chan |> List.iter ~f:(fun l -> Log_utils.warn "[%s] {%s} (Information Exposure Through Debug Information) %s" name version l)
with with
Unix.Unix_error (e,fm,argm) -> Unix.Unix_error (e,fm,argm) ->
Log_utils.error "[%s] {%s} %s %s %s" name version (Unix.error_message e) fm argm Log_utils.error "[%s] {%s} %s %s %s" name version (Unix.error_message e) fm argm
......
...@@ -50,7 +50,7 @@ let check_route sub symbols = ...@@ -50,7 +50,7 @@ let check_route sub symbols =
if res then res else res if res then res else res
(** Checks one possible valid path (combination of APIs) of chroot. *) (** Checks one possible valid path (combination of APIs) of chroot. *)
let check_path prog tid_map sub path = let check_path prog _tid_map sub path =
let symbols = build_symbols path prog in let symbols = build_symbols path prog in
if List.length symbols = List.length path then if List.length symbols = List.length path then
begin begin
...@@ -81,7 +81,7 @@ let check_subfunction prog tid_map sub pathes = ...@@ -81,7 +81,7 @@ let check_subfunction prog tid_map sub pathes =
(Term.name sub) (Term.name sub)
end end
let check_cwe prog proj tid_map pathes _ = let check_cwe prog _proj tid_map pathes _ =
let chroot_symbol = find_symbol prog "chroot" in let chroot_symbol = find_symbol prog "chroot" in
match chroot_symbol with match chroot_symbol with
| Some _ -> | Some _ ->
......
...@@ -27,7 +27,7 @@ let contains_symbol block symbol_name = ...@@ -27,7 +27,7 @@ let contains_symbol block symbol_name =
(* Checks whether a subfunction contains a catch block. *) (* Checks whether a subfunction contains a catch block. *)
let contains_catch subfunction = let contains_catch subfunction =
let blocks = Term.enum blk_t subfunction in let blocks = Term.enum blk_t subfunction in
Seq.exists blocks (fun block -> contains_symbol block "@__cxa_begin_catch") Seq.exists blocks ~f:(fun block -> contains_symbol block "@__cxa_begin_catch")
(* Find all calls to subfunctions that are reachable from this subfunction. The calls are returned (* Find all calls to subfunctions that are reachable from this subfunction. The calls are returned
as a list, except for calls to "@__cxa_throw", which are logged as possibly uncaught exceptions. *) as a list, except for calls to "@__cxa_throw", which are logged as possibly uncaught exceptions. *)
...@@ -59,7 +59,7 @@ let rec find_uncaught_exceptions subfunction already_checked_functions program ~ ...@@ -59,7 +59,7 @@ let rec find_uncaught_exceptions subfunction already_checked_functions program ~
(* Search for uncatched exceptions for each entry point into the binary. (* Search for uncatched exceptions for each entry point into the binary.
TODO: Exceptions, that are catched when starting from one entry point, but not from another, are masked this TODO: Exceptions, that are catched when starting from one entry point, but not from another, are masked this
way. We should check whether this produces a lot of false negatives. *) way. We should check whether this produces a lot of false negatives. *)
let check_cwe program project tid_map symbol_pairs _ = let check_cwe program _project tid_map _symbol_pairs _ =
let entry_points = Symbol_utils.get_program_entry_points program in let entry_points = Symbol_utils.get_program_entry_points program in
let _ = Seq.fold entry_points ~init:[] ~f:(fun already_checked_functions sub -> find_uncaught_exceptions ~tid_map:tid_map sub already_checked_functions program) in let _ = Seq.fold entry_points ~init:[] ~f:(fun already_checked_functions sub -> find_uncaught_exceptions ~tid_map:tid_map sub already_checked_functions program) in
() ()
open Core_kernel open Core_kernel
open Bap.Std
open Graph_utils
open Symbol_utils open Symbol_utils
let name = "CWE332" let name = "CWE332"
let version = "0.1" let version = "0.1"
let check_cwe program proj tid_map symbol_pairs _ = let check_cwe program _proj _tid_map _symbol_pairs _ =
match Option.both (find_symbol program "srand") (find_symbol program "rand") with match Option.both (find_symbol program "srand") (find_symbol program "rand") with
| None -> begin | None -> begin
match (find_symbol program "rand") with match (find_symbol program "rand") with
| None -> () | None -> ()
| Some _ -> Log_utils.warn "[%s] {%s} (Insufficient Entropy in PRNG) program uses rand without calling srand before" name version | Some _ -> Log_utils.warn "[%s] {%s} (Insufficient Entropy in PRNG) program uses rand without calling srand before" name version
end end
| Some (srand_tid, rand_tid) -> () | Some (_srand_tid, _rand_tid) -> ()
...@@ -34,7 +34,7 @@ let is_reachable sub source sink = ...@@ -34,7 +34,7 @@ let is_reachable sub source sink =
let sink_blk = get_blk_tid_of_tid sub sink_tid in let sink_blk = get_blk_tid_of_tid sub sink_tid in
Graphlib.Std.Graphlib.is_reachable (module Graphs.Tid) cfg source_blk sink_blk Graphlib.Std.Graphlib.is_reachable (module Graphs.Tid) cfg source_blk sink_blk
let handle_sub sub program tid_map symbols source sink = let handle_sub sub program tid_map _symbols source sink =
if (Symbol_utils.sub_calls_symbol program sub source) && (Symbol_utils.sub_calls_symbol program sub sink) then if (Symbol_utils.sub_calls_symbol program sub source) && (Symbol_utils.sub_calls_symbol program sub sink) then
begin begin
let calls = Symbol_utils.get_direct_callsites_of_sub sub in let calls = Symbol_utils.get_direct_callsites_of_sub sub in
...@@ -57,6 +57,6 @@ let handle_sub sub program tid_map symbols source sink = ...@@ -57,6 +57,6 @@ let handle_sub sub program tid_map symbols source sink =
else else
() ()
let check_cwe program proj tid_map symbol_pairs _ = let check_cwe program _proj tid_map _symbol_pairs _ =
let symbols = Symbol_utils.build_symbols ["access"; "open";] in let symbols = Symbol_utils.build_symbols ["access"; "open";] in
Seq.iter (Term.enum sub_t program) ~f:(fun s -> handle_sub s program tid_map symbols "access" "open") Seq.iter (Term.enum sub_t program) ~f:(fun s -> handle_sub s program tid_map symbols "access" "open")
...@@ -21,7 +21,7 @@ let handle_sub sub program tid_map symbols = ...@@ -21,7 +21,7 @@ let handle_sub sub program tid_map symbols =
end end
else () else ()
let check_cwe program proj tid_map symbols _ = let check_cwe program _proj tid_map symbols _ =
match symbols with match symbols with
| hd::[] -> | hd::[] ->
Seq.iter (Term.enum sub_t program) ~f:(fun s -> handle_sub s program tid_map hd) Seq.iter (Term.enum sub_t program) ~f:(fun s -> handle_sub s program tid_map hd)
......
...@@ -10,7 +10,7 @@ let get_defs sub_ssa = ...@@ -10,7 +10,7 @@ let get_defs sub_ssa =
let collect_stores_of_exp = Exp.fold ~init:0 (object let collect_stores_of_exp = Exp.fold ~init:0 (object
inherit [int] Exp.visitor inherit [int] Exp.visitor
method! enter_store ~mem:_ ~addr:addr ~exp:exp _ _ stores = method! enter_store ~mem:_ ~addr:_ ~exp:_ _ _ stores =
stores + 1 stores + 1
end) end)
...@@ -62,7 +62,7 @@ let is_interesting_load_store def fp_pointer = ...@@ -62,7 +62,7 @@ let is_interesting_load_store def fp_pointer =
(*TODO: implement real filtering*) (*TODO: implement real filtering*)
let filter_mem_address i min_fp_offset = Set.filter i ~f:(fun elem -> (Word.of_int ~width:32 min_fp_offset) < elem) let filter_mem_address i min_fp_offset = Set.filter i ~f:(fun elem -> (Word.of_int ~width:32 min_fp_offset) < elem)
let check_subfunction prog proj tid_map sub = let check_subfunction _prog proj tid_map sub =
let fp_pointer = get_fp_of_arch (Project.arch proj) in let fp_pointer = get_fp_of_arch (Project.arch proj) in
let min_fp_offset = get_min_fp_offset (Project.arch proj) in let min_fp_offset = get_min_fp_offset (Project.arch proj) in
let stores = ref [||] in let stores = ref [||] in
...@@ -92,5 +92,5 @@ let check_subfunction prog proj tid_map sub = ...@@ -92,5 +92,5 @@ let check_subfunction prog proj tid_map sub =
end end
end) end)
let check_cwe prog proj tid_map symbol_names _ = let check_cwe prog proj tid_map _symbol_names _ =
Seq.iter (Term.enum sub_t prog) ~f:(fun sub -> check_subfunction prog proj tid_map sub) Seq.iter (Term.enum sub_t prog) ~f:(fun sub -> check_subfunction prog proj tid_map sub)
...@@ -8,7 +8,7 @@ let version = "0.1" ...@@ -8,7 +8,7 @@ let version = "0.1"
let get_pointer_size arch = let get_pointer_size arch =
Size.in_bytes @@ Arch.addr_size arch Size.in_bytes @@ Arch.addr_size arch
let check_input_is_pointer_size proj prog sub blk jmp tid_map symbols = let check_input_is_pointer_size proj _prog _sub blk jmp tid_map symbols =
Seq.iter (Term.enum def_t blk) ~f:(fun d -> match Exp.eval @@ Def.rhs d with Seq.iter (Term.enum def_t blk) ~f:(fun d -> match Exp.eval @@ Def.rhs d with
| Imm w -> | Imm w ->
begin begin
......
...@@ -53,7 +53,7 @@ module State = struct ...@@ -53,7 +53,7 @@ module State = struct
(** two states are equal if they contain the same set of tainted registers*) (** two states are equal if they contain the same set of tainted registers*)
let equal state1 state2 = let equal state1 state2 =
(List.length state1) = (List.length state2) && (List.length state1) = (List.length state2) &&
not (List.exists state1 ~f:(fun (var, tid) -> Option.is_none (find state2 var) )) not (List.exists state1 ~f:(fun (var, _tid) -> Option.is_none (find state2 var) ))
(** The union of two states is the union of the tainted registers*) (** The union of two states is the union of the tainted registers*)
let union state1 state2 = let union state1 state2 =
...@@ -66,14 +66,14 @@ module State = struct ...@@ -66,14 +66,14 @@ module State = struct
(** remove virtual registers from the state (useful at the end of a block) *) (** remove virtual registers from the state (useful at the end of a block) *)
let remove_virtual_registers state = let remove_virtual_registers state =
List.filter state ~f:(fun (var, tid) -> Var.is_physical var) List.filter state ~f:(fun (var, _tid) -> Var.is_physical var)
end end
(* check whether an expression contains an unchecked value. *) (* check whether an expression contains an unchecked value. *)
let rec contains_unchecked exp state : access_type = let rec contains_unchecked exp state : access_type =
match exp with match exp with
| Bil.Load(mem, addr, _, _)-> | Bil.Load(_mem, addr, _, _)->
begin begin
let acc = contains_unchecked addr state in let acc = contains_unchecked addr state in
match acc with match acc with
...@@ -81,7 +81,7 @@ let rec contains_unchecked exp state : access_type = ...@@ -81,7 +81,7 @@ let rec contains_unchecked exp state : access_type =
| Access(var) -> MemAccess(var) | Access(var) -> MemAccess(var)
| NoAccess -> NoAccess | NoAccess -> NoAccess
end end
| Bil.Store(mem, addr, val_expression, _,_) -> | Bil.Store(_mem, addr, val_expression, _,_) ->
begin begin
let acc = union_access (contains_unchecked addr state) (contains_unchecked val_expression state) in let acc = union_access (contains_unchecked addr state) (contains_unchecked val_expression state) in
match acc with match acc with
...@@ -111,7 +111,7 @@ let rec contains_unchecked exp state : access_type = ...@@ -111,7 +111,7 @@ let rec contains_unchecked exp state : access_type =
to the source of this return value from state. *) to the source of this return value from state. *)
let checks_value exp state : State.t = let checks_value exp state : State.t =
match exp with match exp with
| Bil.Ite(if_, then_, else_) -> begin | Bil.Ite(if_, _then_, _else_) -> begin
match contains_unchecked if_ state with match contains_unchecked if_ state with
| Access(var) -> | Access(var) ->
(* We filter out all registers with the same generating tid, since we have checked (* We filter out all registers with the same generating tid, since we have checked
...@@ -138,7 +138,7 @@ let flag_any_access exp state ~cwe_hits = ...@@ -138,7 +138,7 @@ let flag_any_access exp state ~cwe_hits =
(** flag all unchecked registers as cwe_hits, return empty state *) (** flag all unchecked registers as cwe_hits, return empty state *)
let flag_all_unchecked_registers state ~cwe_hits = let flag_all_unchecked_registers state ~cwe_hits =
let () = List.iter state ~f:(fun (var, tid) -> let () = List.iter state ~f:(fun (_var, tid) ->
append_to_hits cwe_hits tid) in append_to_hits cwe_hits tid) in
[] []
...@@ -190,30 +190,30 @@ let update_state_jmp jmp state ~cwe_hits ~function_names ~program ~block ~strict ...@@ -190,30 +190,30 @@ let update_state_jmp jmp state ~cwe_hits ~function_names ~program ~block ~strict
| NoAccess -> state | NoAccess -> state
end in end in
match Jmp.kind jmp with match Jmp.kind jmp with
| Goto(Indirect(exp)) -> flag_any_access exp state cwe_hits | Goto(Indirect(exp)) -> flag_any_access exp state ~cwe_hits
| Goto(Direct(_)) -> state | Goto(Direct(_)) -> state
| Ret(_) -> if strict_call_policy then | Ret(_) -> if strict_call_policy then
flag_all_unchecked_registers state cwe_hits flag_all_unchecked_registers state ~cwe_hits
else else
state state
| Int(_, _) -> flag_all_unchecked_registers state cwe_hits | Int(_, _) -> flag_all_unchecked_registers state ~cwe_hits
| Call(call) -> | Call(call) ->
let state = match Call.return call with let state = match Call.return call with
| Some(Indirect(exp)) -> flag_any_access exp state cwe_hits | Some(Indirect(exp)) -> flag_any_access exp state ~cwe_hits
| _ -> state in | _ -> state in
let state = match Call.target call with let state = match Call.target call with
| Indirect(exp) -> flag_any_access exp state cwe_hits | Indirect(exp) -> flag_any_access exp state ~cwe_hits
| _ -> state in | _ -> state in
let state = match strict_call_policy with let state = match strict_call_policy with
| true -> (* all unchecked registers get flagged as hits *) | true -> (* all unchecked registers get flagged as hits *)
flag_all_unchecked_registers state cwe_hits flag_all_unchecked_registers state ~cwe_hits
| false -> (* we assume that the callee will check all remaining unchecked values *) | false -> (* we assume that the callee will check all remaining unchecked values *)
[] in [] in
match Call.target call with match Call.target call with
| Indirect(_) -> state (* already handled above *) | Indirect(_) -> state (* already handled above *)
| Direct(tid) -> | Direct(tid) ->
if List.exists function_names ~f:(fun elem -> String.(=) elem (Tid.name tid)) then if List.exists function_names ~f:(fun elem -> String.(=) elem (Tid.name tid)) then
taint_return_registers tid state program block taint_return_registers tid state ~program ~block
else else
state state
...@@ -227,7 +227,7 @@ let update_block_analysis block register_state ~cwe_hits ~function_names ~progra ...@@ -227,7 +227,7 @@ let update_block_analysis block register_state ~cwe_hits ~function_names ~progra
let register_state = Seq.fold elements ~init:register_state ~f:(fun state element -> let register_state = Seq.fold elements ~init:register_state ~f:(fun state element ->
match element with match element with
| `Def def -> update_state_def def state ~cwe_hits | `Def def -> update_state_def def state ~cwe_hits
| `Phi phi -> state (* We ignore phi terms for this analysis. *) | `Phi _phi -> state (* We ignore phi terms for this analysis. *)
| `Jmp jmp -> update_state_jmp jmp state ~cwe_hits ~function_names ~program ~block ~strict_call_policy | `Jmp jmp -> update_state_jmp jmp state ~cwe_hits ~function_names ~program ~block ~strict_call_policy
) in ) in
State.remove_virtual_registers register_state (* virtual registers should not be accessed outside of the block where they are defined. *) State.remove_virtual_registers register_state (* virtual registers should not be accessed outside of the block where they are defined. *)
...@@ -255,7 +255,7 @@ let print_hit tid ~sub ~function_names ~tid_map = ...@@ -255,7 +255,7 @@ let print_hit tid ~sub ~function_names ~tid_map =
| _ -> false | _ -> false
) in () ) in ()
let check_cwe prog proj tid_map symbol_names parameters = let check_cwe prog _proj tid_map symbol_names parameters =
let symbols = match symbol_names with let symbols = match symbol_names with
| hd :: _ -> hd | hd :: _ -> hd
| _ -> failwith "[CWE476] symbol_names not as expected" in | _ -> failwith "[CWE476] symbol_names not as expected" in
......
...@@ -4,7 +4,7 @@ open Bap.Std ...@@ -4,7 +4,7 @@ open Bap.Std
let name = "CWE676" let name = "CWE676"
let version = "0.1" let version = "0.1"
let get_call_to_target cg callee target = let get_call_to_target _cg callee target =
Term.enum blk_t callee |> Term.enum blk_t callee |>
Seq.concat_map ~f:(fun blk -> Seq.concat_map ~f:(fun blk ->
Term.enum jmp_t blk |> Seq.filter_map ~f:(fun j -> Term.enum jmp_t blk |> Seq.filter_map ~f:(fun j ->
...@@ -35,7 +35,7 @@ let resolve_symbols prog symbols = ...@@ -35,7 +35,7 @@ let resolve_symbols prog symbols =
Seq.filter ~f:(fun s -> List.exists ~f:(fun x -> x = Sub.name s) symbols) Seq.filter ~f:(fun s -> List.exists ~f:(fun x -> x = Sub.name s) symbols)
let check_cwe prog proj tid_map symbol_names _ = let check_cwe prog _proj tid_map symbol_names _ =
match symbol_names with match symbol_names with
| hd::[] -> | hd::[] ->
let subfunctions = Term.enum sub_t prog in let subfunctions = Term.enum sub_t prog in
......
open Core_kernel
open Bap.Std open Bap.Std
let name = "CWE782" let name = "CWE782"
let version = "0.1" let version = "0.1"
(*TODO: check if binary is setuid*) (*TODO: check if binary is setuid*)
let handle_sub sub program tid_map symbols = let handle_sub sub program tid_map _symbols =
if Symbol_utils.sub_calls_symbol program sub "ioctl" then if Symbol_utils.sub_calls_symbol program sub "ioctl" then
Log_utils.warn "[%s] {%s} (Exposed IOCTL with Insufficient Access Control) Program uses ioctl at %s (%s). Be sure to double check the program and the corresponding driver." Log_utils.warn "[%s] {%s} (Exposed IOCTL with Insufficient Access Control) Program uses ioctl at %s (%s). Be sure to double check the program and the corresponding driver."
name name
...@@ -15,5 +14,5 @@ let handle_sub sub program tid_map symbols = ...@@ -15,5 +14,5 @@ let handle_sub sub program tid_map symbols =
else else
() ()
let check_cwe program proj tid_map symbols _ = let check_cwe program _proj tid_map symbols _ =
Seq.iter (Term.enum sub_t program) ~f:(fun s -> handle_sub s program tid_map symbols) Seq.iter (Term.enum sub_t program) ~f:(fun s -> handle_sub s program tid_map symbols)
...@@ -14,7 +14,7 @@ dev-repo: "git+https://github.com/fkie-cad/cwe_checker" ...@@ -14,7 +14,7 @@ dev-repo: "git+https://github.com/fkie-cad/cwe_checker"
depends: [ depends: [
"ocaml" {>= "4.05"} "ocaml" {>= "4.05"}
"dune" {>= "1.6"} "dune" {>= "1.6"}
"yojson" {>= "1.4.1"} "yojson" {>= "1.6.0"}
"bap" {>= "1.6"} "bap" {>= "1.6"}
"core_kernel" {>= "v0.11" & < "v0.12"} "core_kernel" {>= "v0.11" & < "v0.12"}
"ppx_jane" {>= "v0.11" & < "v0.12"} "ppx_jane" {>= "v0.11" & < "v0.12"}
......
...@@ -9,7 +9,7 @@ let translate_tid_to_assembler_address_string tid tid_map = ...@@ -9,7 +9,7 @@ let translate_tid_to_assembler_address_string tid tid_map =
let generate_tid_map prog = let generate_tid_map prog =
(object (object
inherit [addr Tid.Map.t] Term.visitor inherit [addr Tid.Map.t] Term.visitor
method enter_term _ t addrs = match Term.get_attr t address with method! enter_term _ t addrs = match Term.get_attr t address with
| None -> addrs | None -> addrs
| Some addr -> Map.add_exn addrs ~key:(Term.tid t) ~data:addr | Some addr -> Map.add_exn addrs ~key:(Term.tid t) ~data:addr
end)#run prog Tid.Map.empty end)#run prog Tid.Map.empty
...@@ -12,9 +12,11 @@ let callee_saved_register_list project = ...@@ -12,9 +12,11 @@ let callee_saved_register_list project =
let arch = Project.arch project in let arch = Project.arch project in
match arch with match arch with
| `x86_64 -> (* System V ABI *) | `x86_64 -> (* System V ABI *)
"RBX" :: "RSP" :: "RBP" :: "R12" :: "R13" :: "R14" :: "R15" :: [] "RBX" :: "RSP" :: "RBP" :: "R12" :: "R13" :: "R14" :: "R15" :: []
| `x86_64 -> (* Microsoft x64 calling convention *) (* TODO: How to distinguish from System V? For the time being, only use the System V ABI, since it saves less registers. *) (* Microsoft x64 calling convention. Unused at the moment, since Windows binaries are not yet supported.
"RBX" :: "RBP" :: "RDI" :: "RSI" :: "RSP" :: "R12" :: "R13" :: "R14" :: "R15" :: [] | `x86_64 -> (* Microsoft x64 calling convention *)
"RBX" :: "RBP" :: "RDI" :: "RSI" :: "RSP" :: "R12" :: "R13" :: "R14" :: "R15" :: []
*)
| `x86 -> (* Both Windows and Linux save the same registers *) | `x86 -> (* Both Windows and Linux save the same registers *)
"EBX" :: "ESI" :: "EDI" :: "EBP" :: [] "EBX" :: "ESI" :: "EDI" :: "EBP" :: []
| `armv4 | `armv5 | `armv6 | `armv7 | `armv4 | `armv5 | `armv6 | `armv7
......
open Core_kernel
open Bap.Std
open Graphlib.Std
type path = {
start_node: Bap.Std.tid;
nodes: Bap.Std.tid array;
end_node: Bap.Std.tid;
}
let get_entry_blk_of_sub sub =
match Term.first blk_t sub with
| Some blk -> blk
| _ -> failwith "Could not determine first block of sub."
let print_path p =
Format.printf "%s\n" (Array.fold p.nodes ~init:"" ~f:(fun acc n -> acc ^ " -> " ^ (Tid.to_string n)))
let print_path_length p =
Format.printf "%d\n" (Array.length p.nodes)
(* ToDo: remove *)
let print_current_edge a b =
Format.printf "\t%s -> %s\n" (Tid.to_string a) (Tid.to_string b)
let fork_path current_path current_node =
let new_path = Array.append (Array.copy current_path.nodes) [|current_node|] in
{start_node = current_path.start_node; nodes = new_path; end_node = current_path.end_node;}
let node_already_visited_on_path node path =
node = path.start_node || Array.exists path.nodes ~f:(fun n -> n = node)
let rec get_all_paths_from_node node g current_path =
match Seq.to_list (Graphs.Tid.Node.succs node g) with
| [] -> [current_path]
| succs -> List.concat_map succs
~f:(fun succ ->
if node_already_visited_on_path succ current_path then
[]
else
get_all_paths_from_node succ g (fork_path current_path node))
(* Please mind the path explosion !!! *)
let enumerate_paths_between_blks sub blk_start_tid blk_end_tid limit =
let g = Sub.to_graph sub in
let pathes = get_all_paths_from_node blk_start_tid g {start_node = blk_start_tid; nodes = [||]; end_node = blk_end_tid} in
Format.printf "\tFound %d pathes.\n" (List.length pathes); []
(** This module implements functionality that works on graphs like the CFG.
Most of its functionality is implemented by using BAP's Graphlib.Std. *)
(* This module implements functionality related to parsing the JSON configuration file. *) (* This module implements functionality related to parsing the JSON configuration file. *)
val get_symbol_lists_from_json : Yojson.Basic.json -> string -> string list list val get_symbol_lists_from_json : Yojson.Basic.t -> string -> string list list
val get_symbols_from_json : Yojson.Basic.json -> string -> string list val get_symbols_from_json : Yojson.Basic.t -> string -> string list
val get_parameter_list_from_json : Yojson.Basic.json -> string -> string list val get_parameter_list_from_json : Yojson.Basic.t -> string -> string list
...@@ -166,7 +166,7 @@ module Make (S: SECTION) = struct ...@@ -166,7 +166,7 @@ module Make (S: SECTION) = struct
!prefix !prefix
(* example for a shorter timestamp string *) (* example for a shorter timestamp string *)
let short_timestamp_str lvl = let _short_timestamp_str lvl =
sprintf "%.3f %s: " (Unix.gettimeofday()) (string_of_level lvl) sprintf "%.3f %s: " (Unix.gettimeofday()) (string_of_level lvl)
let log lvl fmt = let log lvl fmt =
......
...@@ -48,7 +48,7 @@ Term.enum blk_t sub |> ...@@ -48,7 +48,7 @@ Term.enum blk_t sub |>
match Jmp.kind j with match Jmp.kind j with
| Goto _ | Ret _ | Int (_,_) -> None | Goto _ | Ret _ | Int (_,_) -> None
| Call destination -> begin match Call.target destination with | Call destination -> begin match Call.target destination with
| Direct tid -> Some j | Direct _tid -> Some j
| _ -> None | _ -> None
end)) end))
......
open Bap.Std open Bap.Std
open Core_kernel (* open Core_kernel *)
open Cwe_checker_core open Cwe_checker_core
let check msg x = Alcotest.(check bool) msg true x let check msg x = Alcotest.(check bool) msg true x
......
open Bap.Std
open Core_kernel
val tests: unit Alcotest.test_case list val tests: unit Alcotest.test_case list
open Bap.Std open Bap.Std
open Core_kernel open Core_kernel
open Cwe_checker_core
let run_tests project = let run_tests project =
Type_inference_test.example_project := Some(project); Type_inference_test.example_project := Some(project);
......
...@@ -24,7 +24,7 @@ let test_parse_dyn_syms () = ...@@ -24,7 +24,7 @@ let test_parse_dyn_syms () =
let () = check "__libc_start_main_as_dyn_sym" (String.Set.mem (parse_dyn_syms project) "__libc_start_main") in let () = check "__libc_start_main_as_dyn_sym" (String.Set.mem (parse_dyn_syms project) "__libc_start_main") in
let () = check "malloc_as_dyn_sym" (String.Set.mem (parse_dyn_syms project) "malloc") in let () = check "malloc_as_dyn_sym" (String.Set.mem (parse_dyn_syms project) "malloc") in
let () = check "__cxa_finalize_as_dyn_sym" (String.Set.mem (parse_dyn_syms project) "__cxa_finalize") in let () = check "__cxa_finalize_as_dyn_sym" (String.Set.mem (parse_dyn_syms project) "__cxa_finalize") in
let () = check "dyn_sym_count" (String.Set.count (parse_dyn_syms project) ~f:(fun elem -> true) = 4) in let () = check "dyn_sym_count" (String.Set.count (parse_dyn_syms project) ~f:(fun _elem -> true) = 4) in
() ()
let tests = [ let tests = [
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment