Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ exclude = ["senbei-wasm"]
resolver = "2"

[workspace.package]
version = "1.3.0"
version = "1.3.1"
edition = "2024"
rust-version = "1.98.1"
license = "AGPL-3.0-only"
Expand Down
52 changes: 52 additions & 0 deletions senbei-engine/src/windows/exe/pipeline/pe32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -976,6 +976,58 @@ impl<'a> Unpacker<'a> {
}
}

// ---- Re-arm TLS field base relocations (PE32 DLL) ----
// The packer neutralizes the four relocations covering the TLS
// directory's VA fields (Start/EndAddressOfRawData, AddressOfIndex,
// AddressOfCallBacks) by demoting them to IMAGE_REL_BASED_ABSOLUTE
// padding, because its own loader fixes TLS up by hand. Restored
// verbatim, a DLL mapped off its preferred base keeps stale VAs in its
// TLS directory, and the OS loader faults in LdrpAllocateTlsEntry when
// it writes the TLS slot index through the unrelocated AddressOfIndex.
// Promote those entries back to IMAGE_REL_BASED_HIGHLOW. EXE output
// is untouched: its BaseReloc directory is zeroed above, and its
// goldens must stay byte-identical.
if is_dll && tls_dir_rva > 0 {
let reloc_rva = get_u32(&self.decompressed, exe_pe.wrapping_add(0xA0));
let reloc_size = get_u32(&self.decompressed, exe_pe.wrapping_add(0xA4));
let reloc_end = reloc_rva.wrapping_add(reloc_size);
let dlen = self.decompressed.len() as u32;
if reloc_rva > 0 && reloc_size >= 8 && reloc_end <= dlen {
let mut rearmed = 0u32;
let mut block = reloc_rva;
while block.wrapping_add(8) <= reloc_end {
let page = get_u32(&self.decompressed, block);
let block_size = get_u32(&self.decompressed, block.wrapping_add(4));
if block_size < 8
|| !block_size.is_multiple_of(2)
|| block.wrapping_add(block_size) > reloc_end
{
break;
}
let entries = (block_size - 8) / 2;
for i in 0..entries {
let entry_off = block.wrapping_add(8).wrapping_add(i.wrapping_mul(2));
let entry = get_u16(&self.decompressed, entry_off);
let entry_rva = page.wrapping_add((entry & 0x0FFF) as u32);
// IMAGE_REL_BASED_ABSOLUTE with a real offset is
// neutralized, not padding (padding keeps offset 0).
if entry >> 12 == 0
&& entry & 0x0FFF != 0
&& entry_rva >= tls_dir_rva
&& entry_rva < tls_dir_rva.wrapping_add(16)
{
write_u16(&mut self.decompressed, entry_off, (entry | 0x3000) as u32);
rearmed = rearmed.wrapping_add(1);
}
}
block = block.wrapping_add(block_size);
}
if verbose && rearmed > 0 {
println!(" re-armed {} TLS field relocations", rearmed);
}
}
}

// ---- Import table (PE32, 4-byte thunks) ----
if verbose {
println!("[8/9] Decrypting import strings (PE32)...");
Expand Down
14 changes: 7 additions & 7 deletions senbei-wasm/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion senbei-wasm/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "senbei-wasm"
version = "1.3.0"
version = "1.3.1"
edition = "2024"
rust-version = "1.98.1"
description = "WebAssembly bindings for senbei (browser frontend assets live in web/)"
Expand Down
Loading