Skip to content

Commit 5f69b48

Browse files
committed
pe(write): factor into write_certificates
We had the write certificate logic in the `TryIntoCtx`, but it makes sense to have it separated to let consumers call it manually.
1 parent ef92e09 commit 5f69b48

File tree

1 file changed

+22
-38
lines changed

1 file changed

+22
-38
lines changed

src/pe/mod.rs

Lines changed: 22 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -356,44 +356,28 @@ impl<'a> PE<'a> {
356356
written_data_size);
357357
}
358358
}
359-
if let Some(opt_header) = self.header.optional_header {
360-
// Takes care of:
361-
// - export table (.edata)
362-
// - import table (.idata)
363-
// - bound import table
364-
// - import address table
365-
// - delay import tables
366-
// - resource table (.rsrc)
367-
// - exception table (.pdata)
368-
// - base relocation table (.reloc)
369-
// - debug table (.debug)
370-
// - load config table
371-
// - tls table (.tls)
372-
// - architecture (reserved, 0 for now)
373-
// - global ptr is a "empty" data directory (header-only)
374-
// - clr runtime header (.cormeta is object-only)
375-
for (dt_type, dd) in opt_header.data_directories.dirs() {
376-
// - attribute certificate table is a bit special
377-
// its size is not the real size of all certificates
378-
// you can check the parse logic to understand how that works
379-
if dt_type == DataDirectoryType::CertificateTable {
380-
let mut certificate_start = dd.virtual_address.try_into()?;
381-
for certificate in &self.certificates {
382-
bytes.gwrite_with(certificate, &mut certificate_start, ctx)?;
383-
max_offset = max(max_offset, certificate_start);
384-
}
385-
} else {
386-
let offset = dd.offset.ok_or(Self::Error::Malformed(
387-
"Data directory was not read with offset information, cannot rewrite"
388-
.into(),
389-
))?;
390-
let dd_written = bytes.pwrite(dd.data(&self.bytes)?, offset)?;
391-
max_offset = max(max_offset, offset);
392-
debug!(
393-
"writing {:?} at {} for {} bytes",
394-
dt_type, offset, dd_written
395-
);
396-
}
359+
360+
Ok(*offset)
361+
}
362+
363+
pub fn write_certificates(
364+
&self,
365+
bytes: &mut [u8],
366+
ctx: scroll::Endian,
367+
) -> Result<usize, error::Error> {
368+
let opt_header = self
369+
.header
370+
.optional_header
371+
.ok_or(error::Error::Malformed(format!(
372+
"This PE binary has no optional header; it is required to write certificates"
373+
)))?;
374+
let mut max_offset = 0;
375+
376+
if let Some(certificate_directory) = opt_header.data_directories.get_certificate_table() {
377+
let mut certificate_start = certificate_directory.virtual_address.try_into()?;
378+
for certificate in &self.certificates {
379+
bytes.gwrite_with(certificate, &mut certificate_start, ctx)?;
380+
max_offset = max(certificate_start, max_offset);
397381
}
398382
}
399383

0 commit comments

Comments
 (0)