// SPDX-License-Identifier: Apache-2.0
///|
pub fn PEImage::diff(self : Self, other : Self) -> Array[DiffItem] {
let changes = []
compare_field(
changes,
"format",
format_text(self.format),
format_text(other.format),
)
compare_field(
changes,
"machine",
architecture_name(self.machine),
architecture_name(other.machine),
)
compare_field(
changes,
"subsystem",
subsystem_name(self.subsystem),
subsystem_name(other.subsystem),
)
compare_field(
changes,
"image-base",
self.image_base.to_string(),
other.image_base.to_string(),
)
compare_field(
changes,
"entry-point",
self.entry_point.to_string(),
other.entry_point.to_string(),
)
compare_field(
changes,
"image-size",
self.size_of_image.to_string(),
other.size_of_image.to_string(),
)
compare_field(
changes,
"dll-characteristics",
self.dll_characteristics.to_string(),
other.dll_characteristics.to_string(),
)
compare_field(
changes,
"sections",
sections_signature(self),
sections_signature(other),
)
compare_field(
changes,
"imports",
imports_signature(self),
imports_signature(other),
)
compare_field(
changes,
"exports",
exports_signature(self),
exports_signature(other),
)
compare_field(
changes,
"directories",
directories_signature(self),
directories_signature(other),
)
compare_field(
changes,
"bound-imports",
bound_imports_signature(self),
bound_imports_signature(other),
)
compare_field(changes, "clr", clr_signature(self), clr_signature(other))
compare_field(
changes,
"certificates",
certificates_signature(self),
certificates_signature(other),
)
compare_field(
changes,
"overlay",
overlay_signature(self),
overlay_signature(other),
)
compare_field(
changes,
"checksum",
checksum_signature(self),
checksum_signature(other),
)
compare_field(
changes,
"security-diagnostics",
diagnostics_signature(self),
diagnostics_signature(other),
)
changes
}
///|
fn compare_field(
changes : Array[DiffItem],
field : String,
before : String,
after : String,
) -> Unit {
if before != after {
changes.push({ field, before, after, })
}
}
///|
fn sections_signature(image : PEImage) -> String {
let values = []
for section in image.sections {
values.push(
"\{section.name}:\{section.virtual_size}/\{section.raw_size}/\{section.characteristics}",
)
}
values.join(",")
}
///|
fn imports_signature(image : PEImage) -> String {
try {
let values = []
for library in image.imports() {
values.push("\{library.name}(\{library.symbols.length()})")
}
values.join(",")
} catch {
PeError(_, _) => ""
}
}
///|
fn exports_signature(image : PEImage) -> String {
try {
let values = []
for symbol in image.exports() {
values.push(symbol.name)
}
values.join(",")
} catch {
PeError(_, _) => ""
}
}
///|
fn directories_signature(image : PEImage) -> String {
let values = []
for directory in image.directories {
if directory.virtual_address != 0UL && directory.size > 0 {
values.push(directory.name)
}
}
values.join(",")
}
///|
fn bound_imports_signature(image : PEImage) -> String {
try {
let values = []
for item in image.bound_imports() {
values.push("\{item.name}(\{item.forwarders.length()})")
}
values.join(",")
} catch {
PeError(_, _) => ""
}
}
///|
fn clr_signature(image : PEImage) -> String {
try {
match image.clr_header() {
Some(header) =>
"\{header.metadata_rva}/\{header.metadata_size}/\{header.entry_point_token}"
None => ""
}
} catch {
PeError(_, _) => ""
}
}
///|
fn certificates_signature(image : PEImage) -> String {
try {
let values = []
for record in image.certificates() {
values.push("\{record.certificate_type}:\{record.length}")
}
values.join(",")
} catch {
PeError(_, _) => ""
}
}
///|
fn overlay_signature(image : PEImage) -> String {
match image.overlay() {
Some(overlay) => "\{overlay.offset}:\{overlay.size}"
None => ""
}
}
///|
fn checksum_signature(image : PEImage) -> String {
let checksum = image.checksum_info()
"\{checksum.present}/\{checksum.valid}/\{checksum.computed}"
}
///|
fn diagnostics_signature(image : PEImage) -> String {
let values = []
for diagnostic in image.security_diagnostics() {
values.push(diagnostic.code)
}
values.join(",")
}
///|
fn format_text(format : PEFormat) -> String {
if format is PE32 {
"PE32"
} else {
"PE32+"
}
}