Replace patchelf crack with Freeloader LD_PRELOAD approach
- Multi-stage Dockerfile: discover patterns from PMS binary (capstone), compile .so with zig (musl), layer onto lscr.io/linuxserver/plex - Uses LD_PRELOAD instead of patchelf (which corrupts Plex's musl loader) - Auto-discovery: broad structural patterns with string-anchored fallback (//feature) and relationship-based fallback (BITSET_REF within BS_INIT) - hook.cpp uses __has_include for generated patterns with hardcoded fallbacks - Custom wrapper.sh (no traffic_logger preload) - Vendored Freeloader source (github.com/authrequest/Freeloader, AGPL-3.0) - Removed stale plexmediaserver_crack.so binary - Supports Plex 1.43.3+ (verified against 1.43.2 and 1.43.3)
This commit is contained in:
1 parent
4399a8288d
commit
72f4661bdc
72 files changed
+77927
-17
No files matched your search
@@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Verifier: reads the live Plex process to confirm the crack installed.
|
||||
# arg1 = PID of "Plex Media Server"
|
||||
# Checks:
|
||||
# - apply_feature_list_xml (file vaddr 0x1167490) prologue overwritten with a
|
||||
# trampoline JMP (FF 25 ...) => hook installed.
|
||||
# - g_feature_bitset_slots (file vaddr 0x15AE5D8, 14 x u64) => feature bits.
|
||||
import sys, struct, binascii
|
||||
|
||||
pid = int(sys.argv[1])
|
||||
MAIN = "/usr/lib/plexmediaserver/Plex Media Server"
|
||||
APPLY = 0x1167490
|
||||
BITSET = 0x15AE5D8
|
||||
|
||||
base = None
|
||||
with open("/proc/%d/maps" % pid) as f:
|
||||
for line in f:
|
||||
if line.rstrip().endswith(MAIN):
|
||||
base = int(line.split("-", 1)[0], 16)
|
||||
break
|
||||
if base is None:
|
||||
print("ERROR: base mapping not found")
|
||||
sys.exit(1)
|
||||
print("base = 0x%x" % base)
|
||||
|
||||
def rd(off, n):
|
||||
with open("/proc/%d/mem" % pid, "rb") as f:
|
||||
f.seek(base + off)
|
||||
return f.read(n)
|
||||
|
||||
fn = rd(APPLY, 16)
|
||||
print("apply_feature_list_xml[0:16] = " + binascii.hexlify(fn).decode())
|
||||
print("hook installed (prologue == jmp FF 25)? %s" % (fn[:2] == b"\xff\x25"))
|
||||
|
||||
qs = struct.unpack("<14Q", rd(BITSET, 112))
|
||||
for i, q in enumerate(qs):
|
||||
print(" slot %2d = 0x%016x" % (i, q))
|
||||
print("all 14 qwords fully 0xFF..F? %s" % all(q == 0xFFFFFFFFFFFFFFFF for q in qs))
|
||||
print("all used low-bytes set (every feature enabled)? %s" % all((q & 0xFF) == 0xFF for q in qs))
|
||||
Reference in new issue
Block a user