Skip to content

Commit

Permalink
pe(write): factor into write_certificates
Browse files Browse the repository at this point in the history
We had the write certificate logic in the `TryIntoCtx`, but it makes
sense to have it separated to let consumers call it manually.
  • Loading branch information
RaitoBezarius committed Nov 20, 2023
1 parent ef92e09 commit 5f69b48
Showing 1 changed file with 22 additions and 38 deletions.
60 changes: 22 additions & 38 deletions src/pe/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -356,44 +356,28 @@ impl<'a> PE<'a> {
written_data_size);
}
}
if let Some(opt_header) = self.header.optional_header {
// Takes care of:
// - export table (.edata)
// - import table (.idata)
// - bound import table
// - import address table
// - delay import tables
// - resource table (.rsrc)
// - exception table (.pdata)
// - base relocation table (.reloc)
// - debug table (.debug)
// - load config table
// - tls table (.tls)
// - architecture (reserved, 0 for now)
// - global ptr is a "empty" data directory (header-only)
// - clr runtime header (.cormeta is object-only)
for (dt_type, dd) in opt_header.data_directories.dirs() {
// - attribute certificate table is a bit special
// its size is not the real size of all certificates
// you can check the parse logic to understand how that works
if dt_type == DataDirectoryType::CertificateTable {
let mut certificate_start = dd.virtual_address.try_into()?;
for certificate in &self.certificates {
bytes.gwrite_with(certificate, &mut certificate_start, ctx)?;
max_offset = max(max_offset, certificate_start);
}
} else {
let offset = dd.offset.ok_or(Self::Error::Malformed(
"Data directory was not read with offset information, cannot rewrite"
.into(),
))?;
let dd_written = bytes.pwrite(dd.data(&self.bytes)?, offset)?;
max_offset = max(max_offset, offset);
debug!(
"writing {:?} at {} for {} bytes",
dt_type, offset, dd_written
);
}

Ok(*offset)
}

pub fn write_certificates(
&self,
bytes: &mut [u8],
ctx: scroll::Endian,
) -> Result<usize, error::Error> {
let opt_header = self
.header
.optional_header
.ok_or(error::Error::Malformed(format!(
"This PE binary has no optional header; it is required to write certificates"
)))?;
let mut max_offset = 0;

if let Some(certificate_directory) = opt_header.data_directories.get_certificate_table() {
let mut certificate_start = certificate_directory.virtual_address.try_into()?;
for certificate in &self.certificates {
bytes.gwrite_with(certificate, &mut certificate_start, ctx)?;
max_offset = max(certificate_start, max_offset);
}
}

Expand Down

0 comments on commit 5f69b48

Please sign in to comment.