Skip to content

Copy the contents of the ELF file used for symbol resolution into ano… - #988

Open
yuaniho wants to merge 2 commits into
JingMatrix:masterfrom
yuaniho:anonymous-elf-mapping
Open

yuaniho wants to merge 2 commits into
JingMatrix:masterfrom
yuaniho:anonymous-elf-mapping

Conversation

@yuaniho

@yuaniho yuaniho commented Sep 30, 2026 •

Copy link
Copy Markdown

Abstract

Copy the contents of the ELF file used for symbol resolution into anonymous memory to avoid creating an additional mapping for the same ELF file in /proc/self/maps. This prevents certain applications from mistaking this read-only resolution mapping for the actual module load base address, which would otherwise cause a crash.

Discovery

After switching the framework from LSPosed to Vector, I found that an older module—which previously worked fine—stopped functioning, and the target application would crash upon startup. Initially, I suspected a compatibility issue arising from the module's migration from API 82 to API 102, so I rewrote the module to comply with API 102 standards. However, the problem persisted: the module failed to work, and the target application continued to crash and exit.
Subsequently, I analyzed the crash logs and process memory mappings, and compared the relevant source code between Vector and LSPosed. I ultimately determined that the issue was unrelated to the module API; instead, it was caused by the ELF file mapping that Vector creates and retains for symbol resolution.

Crash Analysis

The program counter at the time of the crash was:
pc = 0x73017eff90
art::Runtime::DisableVerifier()+0

An additional libart.so mapping existed in the target process:
0x73011bd000-0x7301b70000 r-- offset 0 /apex/com.android.art/lib64/libart.so

The symbol value for art::Runtime::DisableVerifier() within the ELF file is:
0x632f90

Adding the start address of the additional mapping to the symbol value:
0x73011bd000 + 0x632f90 = 0x73017eff90

The calculated result matches the actual crash address exactly.

This indicates that the target application mistakenly identified the ELF symbol resolution mapping created by Vector as the actual load base address of libart.so and calculated the address of DisableVerifier() based on it. However, this mapping is intended solely for reading and parsing ELF symbols; it has r-- permissions and lacks execute permissions. When the target application jumps to this address to execute code, a SEGV_ACCERR crash occurs.

Changes

  • Allocated the ELF parsing buffer using MAP_PRIVATE | MAP_ANONYMOUS.
  • Copied the entire file using pread().

Verification

Tested using a locally built Vector module in the following environment:

  • Device: Redmi K40
  • Android Version: 13

Before the modification, the protected target process crashed when jumping to DisableVerifier, which was located in an additional read-only memory mapping.

After the modification:

  • Both legacy and new module loading functions in Vector work correctly;
  • ART symbol lookup and hooking functions work correctly;
  • The target application that previously crashed now launches successfully;

Yuan added 2 commits October 1, 2026 03:50
…nymous memory to avoid an additional mapping of the same ELF file in `/proc/self/maps`, thereby preventing certain applications from mistakenly identifying this read-only resolution mapping as the actual module load base address and crashing.
…nymous memory to avoid an additional mapping of the same ELF file in `/proc/self/maps`, thereby preventing certain applications from mistakenly identifying this read-only resolution mapping as the actual module load base address and crashing.
@yuaniho
yuaniho marked this pull request as ready for review October 2, 2026 07:09
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.

1 participant