Commit graph

52 commits

Author SHA1 Message Date
okhsunrog
33faf8f8aa fix: address race conditions, UB, and correctness issues across all components
kmod:
- Add explicit rcu_read_lock() around ifa->idev->dev->name dereferences
  in inet6_fill_entry, inet_fill_entry, and rtnl_fill_entry
- Remove racy READ_ONCE fast-path in is_target_uid; uncontended spin_lock
  is ~5ns on ARMv8 and the optimization had incorrect TOCTOU semantics
- Fix dev_ifconf_ret: return immediately on copy_from_user/copy_to_user
  failure instead of breaking the loop and writing back a wrong ifc_len
- Fail module load if zero kretprobes register; warn on partial registration

lsposed:
- Fix isSystemServer check-then-set race: use AtomicBoolean.compareAndSet
  to prevent duplicate hook installation from concurrent handleLoadPackage
- Fix NC hook partial state corruption: save all values before mutating,
  restore on exception, only set ThreadLocals after all mutations succeed
- Fix NI/LP hooks: replace param.result=null (which skips writeToParcel
  and corrupts the Parcel stream) with save-mutate-restore pattern
- Synchronize loadTargetUids() with double-checked locking; always cache
  result (even empty) to avoid file I/O on every Binder call
- Fix suExec: drain stderr on background thread, destroy process in finally

zygisk:
- Use std::sync::Once for shadowhook initialization instead of AtomicBool
- Handle write() return value on memfd: loop on short writes, return error
- Make netlink parsers (read_u32_ne/read_u16_ne) return Option instead of
  panicking on out-of-bounds access
2026-04-12 23:06:48 +03:00
okhsunrog
38c62e2c6c chore: ignore stray zip files in repo root 2026-04-12 05:41:08 +03:00
okhsunrog
4c9e437330 docs: clarify root grant differs between Magisk and KernelSU-Next 2026-04-12 05:37:07 +03:00
okhsunrog
9f101f66e8 docs: mention root access for VPN Hide app, explain reboot requirement
The app needs root (su) to write target files. LSPosed hooks are
injected into system_server at boot, so a reboot is required after
enabling the module — system_server must restart with hooks active.
2026-04-12 05:30:14 +03:00
okhsunrog
7b867c8b64 chore: add VERSION file and update-version.sh, bump to v0.4.0
Single VERSION file in repo root as the source of truth. The script
update-version.sh propagates it to all 5 locations: kmod module.prop,
zygisk module.prop, zygisk Cargo.toml, lsposed build.gradle.kts,
test-app build.gradle.kts. versionCode = major*10000 + minor*100 + patch.
2026-04-12 03:23:16 +03:00
okhsunrog
1ee26e1de8 docs: add VPN Hide app as primary target management method
The lsposed APK now includes a Compose target picker UI that works
with both kmod and zygisk on any root solution. Update all READMEs
to recommend the app over WebUI (which is KernelSU-only).
2026-04-12 03:17:59 +03:00
okhsunrog
c52a6711ff fix: UID resolution in save commands used printf \n escapes instead of real newlines
The shell variable $UIDS accumulated UIDs with literal \n (two chars)
instead of actual newlines. printf "$UIDS" wrote garbage to
/proc/vpnhide_targets and vpnhide_uids.txt. The empty-targets case
used bare > redirect which never triggers the proc write handler.

Fix: accumulate UIDs with real newlines (like service.sh does), use
echo "$UIDS" for output, and echo (writes \n) for the empty case so
the kmod write handler fires and clears the UID list.

Affects: APK target picker, kmod WebUI, zygisk WebUI.
2026-04-12 03:14:59 +03:00
okhsunrog
ce1143d2ea feat: replace lsposed status screen with Compose target picker UI
Migrate from AppCompat + XML to Jetpack Compose with Material3 and
dynamic colors. The new UI lists all installed apps with icons, names,
and package names. Supports text search, system app filter (selected
system apps always visible), and saves targets to all module paths
(kmod, zygisk, Magisk copy, /proc, UIDs file) via su.

- Add version catalog, upgrade Gradle 8.12, AGP 8.9.3, Kotlin 2.1.20
- Add QUERY_ALL_PACKAGES permission for Android 11+ visibility
- Remove old XML layout and AppCompat dependency
2026-04-12 02:42:23 +03:00
okhsunrog
3bf30ee81a feat: add action.sh for Magisk (show targets and status) 2026-04-12 02:08:57 +03:00
okhsunrog
a8bed7e044 security: restrict target list visibility from apps
- /proc/vpnhide_targets: change from 0644 to 0600 (root only).
  Apps could read the UID list and discover which apps are targeted.
- Remove /data/local/tmp/vpnhide_targets.txt copies from service.sh
  and WebUI (no longer needed after get_module_dir() fix).
2026-04-12 02:06:39 +03:00
okhsunrog
6a4862fb69 fix: use Zygisk get_module_dir() fd to read targets
On Magisk, SELinux blocks all /data/adb/ access from forked processes.
Zygisk's get_module_dir() returns an fd opened with root privileges —
use openat() on it to read targets.txt regardless of SELinux context.

Removes /data/local/tmp workaround.
2026-04-12 01:59:24 +03:00
okhsunrog
88b37dc21c fix: cache targets in on_load (zygote context) before fork+setuid 2026-04-12 01:53:26 +03:00
okhsunrog
df13f64fa4 fix: copy targets to /data/local/tmp/ for Magisk SELinux compat 2026-04-12 01:43:53 +03:00
okhsunrog
37edc3c04d fix: zygisk targets fallback to module dir for Magisk SELinux compat
On Magisk, SELinux blocks zygote from reading /data/adb/vpnhide_zygisk/
(Permission denied). Fall back to /data/adb/modules/vpnhide_zygisk/targets.txt
which zygote can read on both Magisk and KernelSU.

- service.sh copies targets.txt to module dir on boot
- WebUI copies on save
- Rust code tries persistent path first, falls back to module dir
2026-04-12 01:39:19 +03:00
okhsunrog
a9a76b840c docs: remove incorrect vermagic bypass claims 2026-04-12 01:18:32 +03:00
okhsunrog
2bc7d164fd docs: mention getAllNetworks() coverage in lsposed README 2026-04-12 01:12:27 +03:00
okhsunrog
41e2086549 docs: add getAllNetworks() to coverage table, update check count to 24 2026-04-12 01:11:23 +03:00
okhsunrog
ef80915a63 test: add getAllNetworks() VPN scan check (24 total) 2026-04-12 01:10:05 +03:00
okhsunrog
de958af450 docs: add architecture notes for all 6 kmod hooks 2026-04-11 23:34:20 +03:00
okhsunrog
9019869e7d docs: add links to component READMEs 2026-04-11 23:29:53 +03:00
okhsunrog
a61df0729c docs: recommend force-stop after changing target apps 2026-04-11 23:24:47 +03:00
okhsunrog
21ba266a80 docs: update component READMEs to reflect current architecture 2026-04-11 23:24:25 +03:00
okhsunrog
c8ab6933e8 docs: fix Pixel GKI generation info 2026-04-11 23:20:58 +03:00
okhsunrog
32e78292c6 docs: simplify BUILDING.md, add DDK Docker build as primary method 2026-04-11 23:16:56 +03:00
okhsunrog
03d91e7f73 docs: clarify kmod as recommended, explain GKI ≠ Android version 2026-04-11 23:15:05 +03:00
okhsunrog
edb77d20db docs: restructure README for new users, add install instructions 2026-04-11 23:11:48 +03:00
okhsunrog
5107412d04 ci: rename APK artifacts to vpnhide-lsposed.apk and vpnhide-test.apk 2026-04-11 23:07:03 +03:00
okhsunrog
5d5bfaa482 ci: auto-detect clang version in DDK image 2026-04-11 22:58:41 +03:00
okhsunrog
f071e7877b ci: use DDK images for kmod, build all 7 GKI generations
Replace custom kernel source cloning + prepare with pre-built DDK
Docker images (ghcr.io/ylarod/ddk-min). These include kernel headers,
Module.symvers, and AOSP clang for each GKI generation.

Now builds for: android12-5.10, android13-5.10, android13-5.15,
android14-5.15, android14-6.1, android15-6.6, android16-6.12.

Drop sha256 files from releases.
2026-04-11 22:55:49 +03:00
okhsunrog
de7c4eaaf4 ci: add rustfmt and clippy to Docker image 2026-04-11 22:36:01 +03:00
okhsunrog
efed29f7d5 ci: add Rust lint job (fmt + clippy for both crates) 2026-04-11 22:29:40 +03:00
okhsunrog
7f5792c6f1 fix: resolve all clippy warnings and fmt issues in both Rust crates 2026-04-11 22:29:16 +03:00
okhsunrog
e413debe45 refactor: replace C++ native checks with Rust
Port all 15 native VPN detection checks from C++ to Rust using
jni + libc crates. Gradle triggers cargo-ndk automatically via
a preBuild dependency — single `./gradlew installDebug` builds
everything.

- Remove CMakeLists.txt and native-lib.cpp
- Add test-app/native/ Rust crate with Cargo.toml and src/lib.rs
- Gradle buildRustNative task runs cargo-ndk, copies .so to jniLibs
- Update CI test-app job with Rust + NDK setup
- 23/23 checks pass on device
2026-04-11 22:19:59 +03:00
okhsunrog
5eaebd0a12 license: unify entire project under MIT 2026-04-11 21:58:07 +03:00
okhsunrog
fe2a104572 ci: unify into single workflow with parallel builds
Replace separate kmod/zygisk/lsposed workflows with one ci.yml.
Four jobs run in parallel: kmod, zygisk, lsposed, test-app.
A release job depends on all four and runs only on tag pushes,
creating a GitHub release with all artifacts and checksums.
2026-04-11 21:46:49 +03:00
okhsunrog
1849ead690 ci: add flex, bison, libssl-dev, libelf-dev to Docker image 2026-04-11 21:10:30 +03:00
okhsunrog
50176322d3 ci: add AOSP clang to PATH for host tool compilation 2026-04-11 21:07:57 +03:00
okhsunrog
617d7c3213 ci: specify branch for AOSP clang sparse checkout 2026-04-11 20:57:19 +03:00
okhsunrog
5ee50935c4 ci: use AOSP clang in Docker image, fix kmod build
- Add Google's AOSP clang (clang-r487747c, same as Pixel kernel build)
  to the CI Docker image via sparse checkout. Distro clang caused ABI
  mismatches leading to bootloops on device.
- Update kmod workflow to use the Docker image + AOSP clang instead of
  system clang from apt.
- Replace symvers with real vmlinux.symvers from Pixel kernel build
  (8050 symbols vs 4060 from device .ko extraction).
- Add kmod build deps (bc, kmod, cpio, binutils-aarch64) to Docker image.
2026-04-11 20:53:20 +03:00
okhsunrog
a49c8bfea7 docs: add detection coverage table, update component descriptions 2026-04-11 20:41:24 +03:00
okhsunrog
b827daebca test: remove informational DNS servers check 2026-04-11 20:38:50 +03:00
okhsunrog
cd9bea8d1e feat: zygisk module writes UIDs for lsposed system_server hooks
Add service.sh to zygisk module that resolves package names → UIDs
and writes /data/system/vpnhide_uids.txt on boot — same contract as
kmod's service.sh. This enables the lsposed system_server hooks to
work with zygisk (previously they only worked with kmod).

Also update the zygisk WebUI to resolve and write UIDs on save,
so changes apply immediately without reboot.
2026-04-11 20:27:36 +03:00
okhsunrog
b7ea88069f refactor: strip lsposed module to system_server-only hooks
Remove all in-process app hooks (NetworkCapabilities, NetworkInfo,
ConnectivityManager, LinkProperties, NetworkInterface, System.getProperty).
These are redundant: system_server writeToParcel hooks cover all Java
API detection paths without touching the app's process, and native
detection is handled by vpnhide-kmod or vpnhide-zygisk.

In-process hooks were also counterproductive for anti-tamper SDK apps —
they modify the app's memory, which is exactly what those SDKs detect.

The module now only needs "System Framework" in LSPosed scope.
~600 lines removed.
2026-04-11 20:15:27 +03:00
okhsunrog
47bce3bc58 fix: add kmod/module/vpnhide_kmod.ko to gitignore 2026-04-11 20:05:03 +03:00
okhsunrog
3bfedecc51 fix: remove /proc/net/* redirect hooks from lsposed module
The hookProcNetFiles() hook redirected FileInputStream/FileReader for
/proc/net/* paths to /dev/null inside the app process. This is
counterproductive: SELinux already blocks untrusted_app from reading
these files (EACCES), and the redirect changes the behavior from
"access denied" to "access succeeds, empty data" — a detectable
anomaly that anti-tamper SDKs could notice.

Also fix Java /proc/net/route check in test app to treat EACCES as
PASS, consistent with the native checks.
2026-04-11 20:00:43 +03:00
okhsunrog
00ad12cfc2 test: comprehensive VPN detection coverage audit (23 checks)
Add 9 new native checks covering all known VPN detection vectors:
netlink RTM_GETROUTE, /proc/net/ipv6_route, /proc/net/tcp{,6},
/proc/net/udp{,6}, /proc/net/dev, /proc/net/fib_trie, /sys/class/net.

Result: all new paths are blocked by SELinux for untrusted apps.
No additional kernel hooks needed — our 6 kretprobes already cover
every reachable detection vector. 23/23 checks pass.
2026-04-11 19:31:53 +03:00
okhsunrog
c391d90432 feat: add dev_ifconf, inet6/inet_fill_ifaddr hooks for full VPN hiding
Kernel module:
- Add dev_ifconf hook to filter SIOCGIFCONF interface enumeration
  (goes through sock_ioctl -> dev_ifconf, not dev_ioctl)
- Add inet6_fill_ifaddr and inet_fill_ifaddr hooks to filter RTM_GETADDR
  netlink responses. getifaddrs() was leaking tun0 via the address dump
  even though RTM_GETLINK was filtered. Uses skb_trim to undo the fill
  and return 0 (not -EMSGSIZE which causes infinite retry on empty skb).
- All 6 kretprobes now cover: ioctl, SIOCGIFCONF, netlink link dumps,
  netlink address dumps (IPv4+IPv6), and /proc/net/route.

Test app:
- Treat SELinux EACCES/EPERM as PASS — if the app can't access the
  resource, it can't detect VPN through it either.
- Test results: 14/14 passed with VPN active.
2026-04-11 19:09:00 +03:00
okhsunrog
e35cf1a6b9 refactor: overhaul kmod build system, fix kernel module bugs
Build system:
- Replace hardcoded paths in Makefile with env vars (KERNEL_SRC, CLANG_DIR)
- Add .env.example and .envrc for direnv-based config
- Simplify build-zip.sh to delegate to make instead of duplicating build command
- Rewrite BUILDING.md: 5-step happy path with direnv, standalone prep as appendix
- Remove redundant quick-reference script and step 7 (manual module.lds hack)

Kernel module (vpnhide_kmod.c):
- Fix fib_route_seq_show hook: save seq_file pointer and buffer position in entry
  handler instead of reading regs->regs[0] in return handler (which holds the
  return value on arm64, not the original argument). Rewrite buffer scanning as
  clean forward iteration with memmove compaction.
- Remove dead SIOCGIFCONF case from dev_ioctl hook (confirmed in kernel source:
  SIOCGIFCONF goes through sock_ioctl -> dev_ifconf, not dev_ioctl on GKI 6.1)
- Fix header comment: remove false tcp4_seq_show claim, correct rtnl symbol name

Test app:
- Auto-run checks on launch (LaunchedEffect) for easier adb-driven testing
2026-04-11 18:50:18 +03:00
okhsunrog
60b3235dc0 docs: redesign README hierarchy for monorepo
Root README is now the single source for shared content (verified
against, split tunneling, threat model, component overview). Sub-READMEs
focus on component-specific technical details and link back to root.

- Remove ~700 lines of duplicated content across sub-READMEs
- Update all cross-references to use monorepo relative paths
- Add test-app to components table
- Update zygisk README: mark openat/recvmsg/SIOCGIFCONF as implemented
- Fix stale links to archived repos
2026-04-11 16:20:33 +03:00
okhsunrog
ca23630e57 refactor: remove commercial app names, rewrite test app in Compose
- Remove specific commercial app/bank names from all READMEs, comments,
  and log messages to avoid legal issues. Open-source detection tools
  (RKNHardering, YourVPNDead) are kept with links.
- Rewrite test-app in Jetpack Compose with Material3 dynamic colors,
  edge-to-edge, system dark/light theme support.
- Make test UI more verbose with detailed result cards.
- Add full logcat output for all checks (tag: VPNHideTest) for
  automated testing by AI agents.
- Fix 16KB page alignment for Android 15+.
2026-04-11 16:09:31 +03:00