Conversation
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
marked this pull request as ready for review
October 2, 2026 07:09
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.somapping 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.soand calculated the address ofDisableVerifier()based on it. However, this mapping is intended solely for reading and parsing ELF symbols; it hasr--permissions and lacks execute permissions. When the target application jumps to this address to execute code, aSEGV_ACCERRcrash occurs.Changes
MAP_PRIVATE | MAP_ANONYMOUS.pread().Verification
Tested using a locally built Vector module in the following environment:
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: