use crate::{Encoding, InputKind};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ContainerInfo {
input_kind: InputKind,
encoding: Option<Encoding>,
autoit_signature_offset: Option<usize>,
version_marker: Option<VersionMarkerInfo>,
payload_stream_offsets: Vec<usize>,
pe_script_resource: Option<PeScriptResourceInfo>,
packed_markers: Vec<PackedMarkerInfo>,
}
impl ContainerInfo {
#[must_use]
pub fn from_observations(
input_kind: InputKind,
encoding: Option<Encoding>,
observations: &[Observation],
) -> Self {
let mut info = Self {
input_kind,
encoding,
autoit_signature_offset: None,
version_marker: None,
payload_stream_offsets: Vec::new(),
pe_script_resource: None,
packed_markers: Vec::new(),
};
for observation in observations {
match *observation {
Observation::AutoItSignatureFound { offset } => {
info.autoit_signature_offset = Some(offset);
}
Observation::VersionMarkerFound { encoding, offset } => {
info.version_marker = Some(VersionMarkerInfo { encoding, offset });
}
Observation::PayloadStreamStartFound { offset } => {
info.payload_stream_offsets.push(offset);
}
Observation::PeScriptResourceFound {
type_id,
type_name,
name,
language_id,
rva,
offset,
size,
} => {
info.pe_script_resource = Some(PeScriptResourceInfo {
type_id,
type_name,
name,
language_id,
rva,
offset,
size,
});
}
Observation::PackedMarkerFound { name, offset } => {
info.packed_markers.push(PackedMarkerInfo { name, offset });
}
Observation::OuterPeHeaderFound
| Observation::FirstFileRecordDecrypted { .. }
| Observation::KnownSubtypeDecrypted { .. } => {}
}
}
info
}
#[must_use]
pub const fn input_kind(&self) -> InputKind {
self.input_kind
}
#[must_use]
pub const fn encoding(&self) -> Option<Encoding> {
self.encoding
}
#[must_use]
pub const fn autoit_signature_offset(&self) -> Option<usize> {
self.autoit_signature_offset
}
#[must_use]
pub const fn version_marker(&self) -> Option<VersionMarkerInfo> {
self.version_marker
}
#[must_use]
pub fn payload_stream_offsets(&self) -> &[usize] {
self.payload_stream_offsets.as_slice()
}
#[must_use]
pub const fn pe_script_resource(&self) -> Option<PeScriptResourceInfo> {
self.pe_script_resource
}
#[must_use]
pub fn packed_markers(&self) -> &[PackedMarkerInfo] {
self.packed_markers.as_slice()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct VersionMarkerInfo {
pub encoding: Encoding,
pub offset: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct PeScriptResourceInfo {
pub type_id: u16,
pub type_name: Option<&'static str>,
pub name: &'static str,
pub language_id: Option<u16>,
pub rva: u32,
pub offset: usize,
pub size: u32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct PackedMarkerInfo {
pub name: &'static str,
pub offset: usize,
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct ObservationLog {
entries: Vec<Observation>,
}
impl ObservationLog {
#[must_use]
pub const fn new() -> Self {
Self {
entries: Vec::new(),
}
}
pub fn push(&mut self, observation: Observation) {
self.entries.push(observation);
}
#[must_use]
pub fn entries(&self) -> &[Observation] {
self.entries.as_slice()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Observation {
OuterPeHeaderFound,
AutoItSignatureFound {
offset: usize,
},
VersionMarkerFound {
encoding: Encoding,
offset: usize,
},
PayloadStreamStartFound {
offset: usize,
},
PeScriptResourceFound {
type_id: u16,
type_name: Option<&'static str>,
name: &'static str,
language_id: Option<u16>,
rva: u32,
offset: usize,
size: u32,
},
PackedMarkerFound {
name: &'static str,
offset: usize,
},
FirstFileRecordDecrypted {
encoding: Encoding,
offset: usize,
},
KnownSubtypeDecrypted {
encoding: Encoding,
offset: usize,
subtype: KnownSubtype,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum KnownSubtype {
TokenizedScript,
UnicodeScript,
PlainScript,
}