-
Notifications
You must be signed in to change notification settings - Fork 280
Expand file tree
/
Copy pathmain.rs
More file actions
136 lines (123 loc) · 4.35 KB
/
main.rs
File metadata and controls
136 lines (123 loc) · 4.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
use std::env;
use binaryninja::binaryview::BinaryViewExt;
use binaryninja::mlil;
use binaryninja::mlil::{MediumLevelILLiftedOperand, MediumLevelILFunction, MediumLevelILLiftedInstruction};
use binaryninja::types::Variable;
fn print_indent(indent: usize) {
print!("{:<indent$}", "")
}
fn print_operation<I: mlil::Form>(operation: &MediumLevelILLiftedInstruction<I>) {
print!("{}", operation.name());
}
fn print_variable<I: mlil::Form>(func: &MediumLevelILFunction<I>, var: &Variable) {
print!("{}", func.get_function().get_variable_name(var));
}
fn print_il_expr<I: mlil::Form>(instr: &MediumLevelILLiftedInstruction<I>, mut indent: usize) {
print_indent(indent);
print_operation(instr);
println!();
indent += 1;
use MediumLevelILLiftedOperand::*;
for (_name, operand) in instr.operands() {
match operand {
Int(int) => {
print_indent(indent);
println!("int 0x{:x}", int);
}
Float(float) => {
print_indent(indent);
println!("int {:e}", float);
}
Expr(expr) => print_il_expr(&expr, indent),
Var(var) => {
print_indent(indent);
print!("var ");
print_variable(&instr.function, &var);
println!();
}
VarSsa(var) => {
print_indent(indent);
print!("ssa var ");
print_variable(&instr.function, &var.variable);
println!("#{}", var.version);
}
IntList(list) => {
print_indent(indent);
print!("index list ");
for i in list {
print!("{i} ");
}
println!();
}
VarList(list) => {
print_indent(indent);
print!("var list ");
for i in list {
print_variable(&instr.function, &i);
print!(" ");
}
println!();
}
VarSsaList(list) => {
print_indent(indent);
print!("ssa var list ");
for i in list {
print_variable(&instr.function, &i.variable);
print!("#{} ", i.version);
}
println!();
}
ExprList(list) => {
print_indent(indent);
println!("expr list");
for i in list {
print_il_expr(&i, indent + 1);
}
}
TargetMap(list) => {
print_indent(indent);
print!("target map ");
for (i, f) in list {
print!("({i}, {f}) ");
}
println!();
}
ConstantData(_) => println!("contantdata"),
Intrinsic(intrinsic) => println!("intrinsic {}", intrinsic.name()),
}
}
}
// Standalone executables need to provide a main function for rustc
// Plugins should refer to `binaryninja::command::*` for the various registration callbacks.
fn main() {
let mut args = env::args();
let _ = args.next().unwrap();
let Some(filename) = args.next() else {
panic!("Expected input filename\n");
};
// This loads all the core architecture, platform, etc plugins
// Standalone executables probably need to call this, but plugins do not
println!("Loading plugins...");
let _headless_session = binaryninja::headless::Session::new();
// Your code here...
println!("Loading binary...");
let bv = binaryninja::load(filename).expect("Couldn't open binary file");
// Go through all functions in the binary
for func in bv.functions().iter() {
let sym = func.symbol();
println!("Function {}:", sym.full_name());
let Ok(il) = func.medium_level_il() else {
println!(" Does not have MLIL\n");
continue;
};
// Loop through all blocks in the function
for block in il.basic_blocks().iter() {
// Loop though each instruction in the block
for instr in block.iter() {
// Generically parse the IL tree and display the parts
print_il_expr(&instr.lift(), 2);
}
}
println!();
}
}