mirror of
https://github.com/pakt/ropc
synced 2026-06-08 16:36:27 +00:00
166 lines
4.8 KiB
OCaml
166 lines
4.8 KiB
OCaml
open Printf
|
|
|
|
type reg = EAX | EBX | ECX | EDX | ESI | EDI | EBP | ESP
|
|
type op = ADD | SUB | MUL | DIV | XOR | OR | AND
|
|
type gadget =
|
|
| LoadConst of reg * int (* reg, stack offset *)
|
|
| CopyReg of reg * reg (* dst reg = src reg *)
|
|
| BinOp of reg * reg * op * reg (* dst reg = src1 OP src2 *)
|
|
| ReadMem of reg * reg * int32 (* dst = [addr_reg + offset] *)
|
|
| WriteMem of reg * int32 * reg (* [addr_reg + offset] = src *)
|
|
| ReadMemOp of reg * op * reg * int32 (* dst OP= [addr_reg + offset] *)
|
|
| WriteMemOp of reg * int32 * op * reg (* [addr_reg + offset] OP= src_reg *)
|
|
| Lahf
|
|
| OpEsp of op * reg * int (* esp = esp op reg, where op=+/-, sf =
|
|
stack_fix *)
|
|
|
|
(* (offset_start, offset_end) *)
|
|
type fmeta = FileMeta of int * int
|
|
(* gadget, file meta, modified registers, stack_fix *)
|
|
type gmeta = GMeta of gadget * fmeta * reg list * int
|
|
(* filename, (data section start, data section end), gadget list
|
|
type used for marshaling candidates for verification *)
|
|
type gcontainer = GContainer of string * (int * int) * gmeta list
|
|
|
|
let rEGS = [EAX; EBX; ECX; EDX; ESI; EDI; EBP; ESP;]
|
|
let rEGS_NO_ESP = [EAX; EBX; ECX; EDX; ESI; EDI; EBP;]
|
|
|
|
let dump_reg r =
|
|
match r with
|
|
| EAX -> "eax"
|
|
| EBX -> "ebx"
|
|
| ECX -> "ecx"
|
|
| EDX -> "edx"
|
|
| ESI -> "esi"
|
|
| EDI -> "edi"
|
|
| EBP -> "ebp"
|
|
| ESP -> "esp"
|
|
|
|
let dump_op op =
|
|
match op with
|
|
| ADD -> "+"
|
|
| SUB -> "-"
|
|
| MUL -> "*"
|
|
| DIV -> "/"
|
|
| XOR -> "^"
|
|
| AND -> "&"
|
|
| OR -> "|"
|
|
|
|
let dump_filemeta fm =
|
|
let FileMeta(off_s, off_e) = fm in
|
|
let s = sprintf "(s: 0x%x, e: 0x%x)" off_s off_e in
|
|
s
|
|
|
|
|
|
let dump_gadget g =
|
|
match g with
|
|
| LoadConst(r, off) -> sprintf "LoadConst(%s, 0x%x)" (dump_reg r) off
|
|
| CopyReg(r1, r2) -> sprintf "CopyReg(%s, %s)" (dump_reg r1) (dump_reg r2)
|
|
| BinOp(r_dst,r1,op,r2) -> sprintf "BinOp(%s, %s, %s, %s)" (dump_reg r_dst) (dump_reg r1) (dump_op op) (dump_reg r2)
|
|
| ReadMem(r_dst, r_addr, off) -> sprintf "ReadMem(%s = [%s+0x%lx])" (dump_reg r_dst) (dump_reg r_addr) off
|
|
| WriteMem(r_addr, off, r_src) -> sprintf "WriteMem([%s+0x%lx] = %s)" (dump_reg r_addr) off (dump_reg r_src)
|
|
| ReadMemOp(r_dst, op, r_addr, off) -> sprintf "ReadMemOp(%s %s= [%s+0x%lx])" (dump_reg r_dst) (dump_op op) (dump_reg r_addr) off
|
|
| WriteMemOp(r_addr, off, op, r_src) -> sprintf "WriteMemOp([%s+0x%lx] %s= %s)" (dump_reg r_addr) off (dump_op op) (dump_reg r_src)
|
|
| OpEsp(op, r, sf) -> sprintf "OpEsp(%s, %s, %d)" (dump_op op) (dump_reg r) sf
|
|
| Lahf -> "Lahf"
|
|
|
|
|
|
let uniq eq l =
|
|
let rec aux l last uni dupes =
|
|
match l with
|
|
| hd::tl ->
|
|
if eq hd last = 0 then
|
|
aux tl last uni (hd::dupes)
|
|
else
|
|
aux tl hd (hd::uni) dupes
|
|
| [] -> uni, dupes
|
|
in
|
|
match l with
|
|
| [] -> l,l
|
|
| hd::[] -> l, []
|
|
| hd::tl -> aux tl hd [hd] []
|
|
|
|
|
|
let unique eq l =
|
|
let u, _ = uniq eq l in
|
|
u
|
|
|
|
let nonunique eq l =
|
|
let _, nu = uniq eq l in
|
|
nu
|
|
|
|
let generic_unique l =
|
|
let l = List.sort compare l in
|
|
unique compare l
|
|
|
|
let create_hashtable size init =
|
|
let tbl = Hashtbl.create size in
|
|
List.iter (fun (key, data) -> Hashtbl.add tbl key data) init;
|
|
tbl
|
|
|
|
let file_exc filename e =
|
|
Format.printf "Cannot open file \"%s\": %s\n" filename (Printexc.to_string e);
|
|
assert false
|
|
|
|
let open_file fn fopen =
|
|
try
|
|
let co = fopen fn in
|
|
co
|
|
with Sys_error _ as e ->
|
|
file_exc fn e
|
|
|
|
let open_file_in fn = open_file fn open_in_bin
|
|
let open_file_out fn = open_file fn open_out_bin
|
|
|
|
let write_str_to_file filename str =
|
|
let co = open_file_out filename in
|
|
(* let co = Format.formatter_of_out_channel co in*)
|
|
output_string co str;
|
|
close_out co
|
|
|
|
let read_file fn =
|
|
let ic = open_file_in fn in
|
|
let n = in_channel_length ic in
|
|
let s = String.create n in
|
|
really_input ic s 0 n;
|
|
close_in ic;
|
|
(s)
|
|
|
|
let marshal_to_file fn thing =
|
|
let co = open_file_out fn in
|
|
Marshal.to_channel co thing []
|
|
|
|
let unmarshal_from_file fn =
|
|
let ic = open_file_in fn in
|
|
let obj = Marshal.from_channel ic in
|
|
obj
|
|
|
|
(* this assumes that RET is the last instruction *)
|
|
let drop_last stmts =
|
|
let stmts = List.rev (List.tl (List.rev stmts)) in
|
|
stmts
|
|
|
|
let find_all p l =
|
|
let f acc x = if p x then (x::acc) else acc in
|
|
List.fold_left f [] l
|
|
|
|
let generic_dumper f_dump l =
|
|
let f _ x = Printf.printf "%s;" (f_dump x) in
|
|
let _ = List.fold_left f () l in
|
|
()
|
|
|
|
let dump_int_list l =
|
|
let f acc x =
|
|
let s = string_of_int x in
|
|
acc^";"^s
|
|
in
|
|
List.fold_left f "" l
|
|
|
|
let get_gadgets gmetas =
|
|
let strip acc gm =
|
|
let GMeta(g,_,_,_) = gm in
|
|
g::acc
|
|
in
|
|
let gadgets = List.fold_left strip [] gmetas in
|
|
gadgets
|