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
use std::collections::BTreeMap;
use std::ops::Bound::Included;
use yaxpeax_arch::AddressBase;
use memory::repr::FlatMemoryRepr;
use memory::{ModuleInfo, MemoryRepr, Named};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SourceInfo {
filename: String,
sha256: String,
}
impl SourceInfo {
pub fn new(filename: String, sha256: String) -> Self {
SourceInfo {
filename,
sha256,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ProgramSlice {
name: String,
source_info: Option<SourceInfo>,
entrypoint: Option<u64>,
chunks: BTreeMap<u64, Vec<u8>>,
}
impl ProgramSlice {
pub fn add_chunk(&mut self, addr: u64, data: Vec<u8>) {
self.chunks.insert(addr, data);
}
pub fn empty(name: String) -> ProgramSlice {
ProgramSlice {
name,
source_info: None,
entrypoint: None,
chunks: BTreeMap::new(),
}
}
pub fn with_source_info(&mut self, source_info: Option<SourceInfo>) -> &mut Self {
self.source_info = source_info;
self
}
pub fn with_entrypoint(&mut self, entrypoint: Option<u64>) -> &mut Self {
self.entrypoint = entrypoint;
self
}
pub fn of(data: Vec<u8>) -> FlatMemoryRepr {
let mut mem = FlatMemoryRepr::empty("anon_flat_repr".to_string());
mem.add(data, 0 as usize).unwrap();
mem
}
pub fn len(&self) -> usize {
if self.chunks.len() > 0 {
let end = *self.chunks.keys().last().unwrap() + self.chunks.values().last().unwrap().len() as u64;
(end - self.chunks.keys().next().unwrap()) as usize
} else {
0
}
}
}
impl <A: yaxpeax_arch::Arch> MemoryRepr<A> for ProgramSlice {
fn read(&self, addr: A::Address) -> Option<u8> {
let (start, data) = if let Some((start, data)) = self.chunks.range((Included(&0), Included(&(addr.to_linear() as u64)))).rev().next() {
(start, data)
} else {
return None;
};
let offset = addr.to_linear() as u64 - *start;
let offset = if offset <= std::usize::MAX as u64 {
offset as usize
} else {
return None;
};
if offset < data.len() {
Some(data[offset])
} else {
None
}
}
fn as_flat(&self) -> Option<FlatMemoryRepr> {
None
}
fn module_info(&self) -> Option<&ModuleInfo> { None }
fn module_for(&self, _addr: A::Address) -> Option<&dyn MemoryRepr<A>> {
None
}
fn size(&self) -> Option<u64> {
if self.chunks.len() > 0 {
let end = *self.chunks.keys().last().unwrap() + self.chunks.values().last().unwrap().len() as u64;
Some(end - self.chunks.keys().next().unwrap())
} else {
None
}
}
}
impl Named for ProgramSlice {
fn name(&self) -> &str {
&self.name
}
}