diff --git a/Cargo.lock b/Cargo.lock index 4047856..98039fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -402,7 +402,7 @@ dependencies = [ [[package]] name = "senbei-cli" -version = "1.3.0" +version = "1.3.1" dependencies = [ "senbei-engine", "senbei-io", @@ -413,7 +413,7 @@ dependencies = [ [[package]] name = "senbei-crypto" -version = "1.3.0" +version = "1.3.1" dependencies = [ "aes", "thiserror", @@ -421,7 +421,7 @@ dependencies = [ [[package]] name = "senbei-elf" -version = "1.3.0" +version = "1.3.1" dependencies = [ "goblin", "thiserror", @@ -429,7 +429,7 @@ dependencies = [ [[package]] name = "senbei-engine" -version = "1.3.0" +version = "1.3.1" dependencies = [ "memmap2", "senbei-crypto", @@ -444,7 +444,7 @@ dependencies = [ [[package]] name = "senbei-io" -version = "1.3.0" +version = "1.3.1" dependencies = [ "anyhow", "indicatif", @@ -465,7 +465,7 @@ dependencies = [ [[package]] name = "senbei-metadata" -version = "1.3.0" +version = "1.3.1" dependencies = [ "serde", "thiserror", @@ -473,7 +473,7 @@ dependencies = [ [[package]] name = "senbei-pe" -version = "1.3.0" +version = "1.3.1" dependencies = [ "thiserror", ] diff --git a/Cargo.toml b/Cargo.toml index e7b583f..42a146a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/senbei-engine/src/windows/exe/pipeline/pe32.rs b/senbei-engine/src/windows/exe/pipeline/pe32.rs index 4ddb6bb..66827e1 100644 --- a/senbei-engine/src/windows/exe/pipeline/pe32.rs +++ b/senbei-engine/src/windows/exe/pipeline/pe32.rs @@ -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)..."); diff --git a/senbei-wasm/Cargo.lock b/senbei-wasm/Cargo.lock index f9912af..22a80df 100644 --- a/senbei-wasm/Cargo.lock +++ b/senbei-wasm/Cargo.lock @@ -412,7 +412,7 @@ dependencies = [ [[package]] name = "senbei-crypto" -version = "1.3.0" +version = "1.3.1" dependencies = [ "aes", "thiserror", @@ -420,7 +420,7 @@ dependencies = [ [[package]] name = "senbei-elf" -version = "1.3.0" +version = "1.3.1" dependencies = [ "goblin", "thiserror", @@ -428,7 +428,7 @@ dependencies = [ [[package]] name = "senbei-engine" -version = "1.3.0" +version = "1.3.1" dependencies = [ "memmap2", "senbei-crypto", @@ -443,7 +443,7 @@ dependencies = [ [[package]] name = "senbei-io" -version = "1.3.0" +version = "1.3.1" dependencies = [ "anyhow", "indicatif", @@ -464,7 +464,7 @@ dependencies = [ [[package]] name = "senbei-metadata" -version = "1.3.0" +version = "1.3.1" dependencies = [ "serde", "thiserror", @@ -472,14 +472,14 @@ dependencies = [ [[package]] name = "senbei-pe" -version = "1.3.0" +version = "1.3.1" dependencies = [ "thiserror", ] [[package]] name = "senbei-wasm" -version = "1.3.0" +version = "1.3.1" dependencies = [ "console_error_panic_hook", "senbei-engine", diff --git a/senbei-wasm/Cargo.toml b/senbei-wasm/Cargo.toml index 966a1e5..b071f5c 100644 --- a/senbei-wasm/Cargo.toml +++ b/senbei-wasm/Cargo.toml @@ -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/)"