Files
DorkNet/DorkNet.Quest/scripts/inject_needed.py
Alexa 975753deac feat: DorkNet.Quest, a sideload patcher for the 2023 Quest client
Patches the Quest build of Rec Room 2023.03.21 (20230317 / 2128210, the
same appVersion as the PC client) to connect to a DorkNet server, using
one native hook library loaded via DT_NEEDED on libmain.so.

- host rewrite onto <svc>.<ServerHost> or a {service}-dev.example.com template
- Photon app ids and region injection (PhotonRegion must match PC)
- TLS / pinning / image-signature bypass, integrity callbacks neutralised
- no-Meta-account build; the server treats platform id 0/1/blank as a
  placeholder and keys those accounts by device id
- build.ps1 -Obb packages a DorkNet-<ver>.xapk with one-command
  installers for Windows and macOS/Linux; app is named via AppName
- README, docs/quest.md and NOTICE updated; credits RecFlare and
  And64InlineHook (MIT)

Tested on a Quest 2: all hooks arm, requests reach the dev server.
2026-10-15 20:29:32 +03:00

44 lines
1.3 KiB
Python

#!/usr/bin/env python3
"""Add a DT_NEEDED entry to libmain.so so the Android loader pulls in
libdorknet.so before Unity starts.
libmain.so is tiny (the Unity bootstrap shim) and lists libil2cpp etc. as
DT_NEEDED; adding one more makes the loader map our hook library first. This is
the same mechanism RecFlare uses on Quest. Idempotent: a second run is a no-op.
Usage: inject_needed.py <libmain.so> <needed-soname> (e.g. libdorknet.so)
"""
import sys
import lief
def main():
if len(sys.argv) != 3:
raise SystemExit("usage: inject_needed.py <libmain.so> <soname>")
path, soname = sys.argv[1], sys.argv[2]
binary = lief.ELF.parse(path)
if binary is None:
raise SystemExit(f"could not parse {path}")
existing = [e.name for e in binary.dynamic_entries
if e.tag == lief.ELF.DynamicEntry.TAG.NEEDED]
if soname in existing:
print(f"{soname} already a DT_NEEDED of {path}; nothing to do")
return
binary.add_library(soname)
binary.write(path)
print(f"added DT_NEEDED {soname} to {path}")
check = lief.ELF.parse(path)
names = [e.name for e in check.dynamic_entries
if e.tag == lief.ELF.DynamicEntry.TAG.NEEDED]
if soname not in names:
raise SystemExit("injection did not stick")
print("verified:", ", ".join(names))
if __name__ == "__main__":
main()