Skip to content

Initialize Addresses section offsets and fail loudly if a section is missing#143

Open
JustinMDotNet wants to merge 1 commit into
wopss:masterfrom
JustinMDotNet:fix/addresses-section-offsets-init
Open

Initialize Addresses section offsets and fail loudly if a section is missing#143
JustinMDotNet wants to merge 1 commit into
wopss:masterfrom
JustinMDotNet:fix/addresses-section-offsets-init

Conversation

@JustinMDotNet

Copy link
Copy Markdown

Closes #134.

What this changes

Two small changes inside the Addresses machinery so the section-offset bug stops being silent:

  1. Default-initialize m_codeOffset, m_dataOffset, and m_rdataOffset to 0 in Addresses.hpp. They had no in-class initializer and were never set in the constructor, so on a module that did not have .text, .data, and .rdata they were read as indeterminate memory.
  2. Have LoadSections() track which of the three sections it actually found, and bail out via the existing SHOW_MESSAGE_BOX_AND_EXIT_FILE_LINE path if any are missing. That turns a silent address-corruption bug into a visible startup failure with file/line context.

Why

Every detour target address goes through these offsets in Addresses.cpp:108-119. With the original code, a missing section meant:

  • Garbage offset added to every address from that segment → DetourAttach patches arbitrary memory → first hooked call dies in another module, or worse, silently corrupts unrelated code.
  • If the garbage happens to be zero, you get hooks that look correct but are all shifted by exactly the missing section's RVA. That is the worst case for debugging.

Cyberpunk's shipping .exe has all three sections, so this is latent for the normal install today. The reachable paths are the PluginSystem::Load(m_paths.GetExe(), false) self-probe (for any host executable that is not the normal game) and any future patch or third-party tool that renames or merges sections (packers, EAC/DRM wrappers, VMProtect, etc.).

What I tested

Read-only review and a local rebuild. I did not try to construct a synthetic exe missing one of the sections; the fix is mechanical enough that I am comfortable with the change without a runtime repro. Happy to add one if you would prefer.

Notes

  • The error string includes which of the three sections were found, so a user-submitted screenshot of the message box should be enough to diagnose the underlying packer/rename.
  • TerminateProcess is already what SHOW_MESSAGE_BOX_AND_EXIT_FILE_LINE does, so the trailing return; is unreachable but harmless and matches the rest of LoadSections().

The m_codeOffset, m_dataOffset, and m_rdataOffset fields on Addresses
had no in-class initializer and no constructor init. LoadSections only
wrote them inside matching strcmp branches, with no else and no
default. If the host module ever lacks one of .text, .data, or .rdata
(packed exes, hosted-process scenarios, future game patches), the
corresponding offset would be read as indeterminate memory and added
to every resolved address, silently producing wild detour targets.

Default the three fields to 0 at declaration so they at least hold a
defined value, and have LoadSections track which of the three sections
it actually found. If any are missing, bail out via the existing
SHOW_MESSAGE_BOX_AND_EXIT_FILE_LINE path so the failure is visible at
startup instead of corrupting hook addresses later.

Fixes wopss#134

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@alphanin9

Copy link
Copy Markdown
Contributor

...why would CDPR start using obfuscator/whatever else would change default MSVC section names? Game is DRM-free

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Critical: uninitialized PE section offsets in Addresses can shift every hook target

3 participants