You've already forked ReZygisk
mirror of
https://github.com/PerformanC/ReZygisk.git
synced 2025-09-06 06:37:01 +00:00
Compare commits
176 Commits
v1.0.0-rc.
...
add/new-we
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d37d651d8c | ||
|
|
6d7eda4ea6 | ||
|
|
5b2065768c | ||
|
|
d2a4110c9d | ||
|
|
5c74037853 | ||
|
|
18d552f59f | ||
|
|
70cea41017 | ||
|
|
61d0e609c2 | ||
|
|
90aec6f83c | ||
|
|
a566ced0c2 | ||
|
|
b0dfcbe357 | ||
|
|
3b07fb1d66 | ||
|
|
1b2f9f23e9 | ||
|
|
a3f68a5c06 | ||
|
|
2ea61563cd | ||
|
|
1f88a8f30e | ||
|
|
d92d854a3b | ||
|
|
cf9e03ac5c | ||
|
|
0b9a2c26b8 | ||
|
|
f58dacea0b | ||
|
|
c14d3ff36e | ||
|
|
64f002541e | ||
|
|
a3d07583d3 | ||
|
|
17f430b354 | ||
|
|
caa4b6b640 | ||
|
|
5120d0067c | ||
|
|
d8c0310053 | ||
|
|
128104a590 | ||
|
|
6ce2fe440b | ||
|
|
c465754be7 | ||
|
|
88eb16331e | ||
|
|
5a061e6daa | ||
|
|
27b3de562f | ||
|
|
56d307783f | ||
|
|
38f3f4ec63 | ||
|
|
05f673bce1 | ||
|
|
43b3bfbc99 | ||
|
|
ef7e6c07e4 | ||
|
|
84a139fcaf | ||
|
|
ea42fbea41 | ||
|
|
e55a825f7d | ||
|
|
dddda78496 | ||
|
|
664aed058a | ||
|
|
8b611b4153 | ||
|
|
b805d86f47 | ||
|
|
d82bd17003 | ||
|
|
847c8c1544 | ||
|
|
5d8db1b602 | ||
|
|
44ba054f96 | ||
|
|
98743e8523 | ||
|
|
949a526cf2 | ||
|
|
73295ab4b5 | ||
|
|
a0d79875ea | ||
|
|
73acecaa9d | ||
|
|
f4968599cf | ||
|
|
8f6a3ae8e8 | ||
|
|
0c44c5c281 | ||
|
|
cd96363249 | ||
|
|
3f816b609a | ||
|
|
ae2664d7e4 | ||
|
|
c833a5b69c | ||
|
|
f38e78bad7 | ||
|
|
b59b4f4a72 | ||
|
|
fbed1e5633 | ||
|
|
6a0f5aaad2 | ||
|
|
3fde061c18 | ||
|
|
d2ca72e04a | ||
|
|
b26b988f08 | ||
|
|
657512ca2c | ||
|
|
19cedefcf3 | ||
|
|
f85baf92ab | ||
|
|
7b26d07454 | ||
|
|
67a7475946 | ||
|
|
40c54bd787 | ||
|
|
64f4768bcd | ||
|
|
daddc980ec | ||
|
|
c9ed52fecb | ||
|
|
34dfa8928e | ||
|
|
f60a049333 | ||
|
|
9e2d40c164 | ||
|
|
3fd70f6416 | ||
|
|
5978dc2e26 | ||
|
|
cc4fe44c95 | ||
|
|
a8be51cba8 | ||
|
|
26b60fce11 | ||
|
|
90de86a5c7 | ||
|
|
665ff2b8d9 | ||
|
|
9957be838f | ||
|
|
cde142de7f | ||
|
|
0c455f3127 | ||
|
|
098a720fcc | ||
|
|
3cc5c64e5e | ||
|
|
ec53757c0a | ||
|
|
7660bca27c | ||
|
|
61bad158e8 | ||
|
|
da7cb91456 | ||
|
|
af09f6e264 | ||
|
|
1d38739100 | ||
|
|
ceb2cf24a9 | ||
|
|
3c1af44edc | ||
|
|
073a0673a0 | ||
|
|
32ea9344dd | ||
|
|
60cf5fb9e1 | ||
|
|
1fb0926ac6 | ||
|
|
dde0436fd9 | ||
|
|
ce54123a7c | ||
|
|
6ec8b5e7bd | ||
|
|
3ef48b1dc4 | ||
|
|
32579a2ebc | ||
|
|
8a666edae6 | ||
|
|
b60209a0cb | ||
|
|
b15b33ddac | ||
|
|
5788a9b67e | ||
|
|
e2e57113c1 | ||
|
|
36eaaac200 | ||
|
|
ea2c8a5388 | ||
|
|
5352d4f0e6 | ||
|
|
814fc3fe1e | ||
|
|
4dac5409d8 | ||
|
|
0b7c939c9f | ||
|
|
db45eaee02 | ||
|
|
259e1f0268 | ||
|
|
ffd0e36118 | ||
|
|
0818f0ade6 | ||
|
|
59ac30d3cc | ||
|
|
341d4944b4 | ||
|
|
afcf302d90 | ||
|
|
a18215226f | ||
|
|
7ef7cf24e9 | ||
|
|
e059917f73 | ||
|
|
0538428a00 | ||
|
|
f4b7c3bd9b | ||
|
|
6952bf1888 | ||
|
|
eb22157a8f | ||
|
|
5778870963 | ||
|
|
d1e86029ce | ||
|
|
d1d69ae553 | ||
|
|
c92ad7c748 | ||
|
|
610683dfa2 | ||
|
|
1bdaeaf0ac | ||
|
|
cbcb236255 | ||
|
|
41a15e87b7 | ||
|
|
567cf1a8b9 | ||
|
|
d4d2c9d663 | ||
|
|
a337b55efd | ||
|
|
ce080dff8f | ||
|
|
9fcf433b66 | ||
|
|
d9edb7c063 | ||
|
|
c707c151fd | ||
|
|
c3ddaa0bfe | ||
|
|
ad3624b945 | ||
|
|
ebdba3ba0f | ||
|
|
a6a268d2c1 | ||
|
|
686342ced6 | ||
|
|
3831547e6e | ||
|
|
235117f52a | ||
|
|
e6c770fca2 | ||
|
|
daf9c78eed | ||
|
|
e0cb8da6dd | ||
|
|
292f75a81e | ||
|
|
c909e21ebc | ||
|
|
37fc9a44b1 | ||
|
|
7b6b3cb9a0 | ||
|
|
6e8809b116 | ||
|
|
1aa0e7e148 | ||
|
|
1f011eefc3 | ||
|
|
79d9e4c531 | ||
|
|
cf59aed3f9 | ||
|
|
94905fb175 | ||
|
|
e5a7dfb862 | ||
|
|
f79eaf1185 | ||
|
|
9655c89ccc | ||
|
|
2acda90379 | ||
|
|
bdf12dcf44 | ||
|
|
10bdf6f080 | ||
|
|
a3accd7a94 |
2
.github/ISSUE_TEMPLATE/issue_template.yml
vendored
2
.github/ISSUE_TEMPLATE/issue_template.yml
vendored
@@ -59,7 +59,7 @@ body:
|
||||
id: code_of_conduct
|
||||
attributes:
|
||||
label: Code of Conduct
|
||||
description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/PerformanC/contributing/blob/main/CODE_OF_CONDUCT.md)
|
||||
description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/PerformanC/voice/blob/main/CODE_OF_CONDUCT.md)
|
||||
options:
|
||||
- label: I agree to follow this project's Code of Conduct
|
||||
required: true
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/pull_request.yml
vendored
2
.github/ISSUE_TEMPLATE/pull_request.yml
vendored
@@ -35,7 +35,7 @@ body:
|
||||
id: code_of_conduct
|
||||
attributes:
|
||||
label: Code of Conduct
|
||||
description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/PerformanC/contributing/blob/main/CODE_OF_CONDUCT.md)
|
||||
description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/PerformanC/voice/blob/main/CODE_OF_CONDUCT.md)
|
||||
options:
|
||||
- label: I agree to follow this project's Code of Conduct
|
||||
required: true
|
||||
7
.github/workflows/ci.yml
vendored
7
.github/workflows/ci.yml
vendored
@@ -1,6 +1,9 @@
|
||||
name: Untrusted CI
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
|
||||
pull_request:
|
||||
merge_group:
|
||||
workflow_dispatch:
|
||||
@@ -22,7 +25,7 @@ jobs:
|
||||
java-version: "17"
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
uses: gradle/actions/setup-gradle@v4.2.1
|
||||
|
||||
- name: Build with Gradle
|
||||
run: |
|
||||
|
||||
66
.github/workflows/trusted_ci.yml
vendored
66
.github/workflows/trusted_ci.yml
vendored
@@ -1,66 +0,0 @@
|
||||
name: Trusted CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: "recursive"
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: "temurin"
|
||||
java-version: "17"
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
|
||||
- name: Setup keys
|
||||
env:
|
||||
private_key: ${{ secrets.ORG_PRIVATE_KEY }}
|
||||
public_key: ${{ secrets.ORG_PUBLIC_KEY }}
|
||||
run: |
|
||||
if [ -z "$private_key" ] || [ -z "$public_key" ]; then
|
||||
echo "Private or public key is not set."
|
||||
else
|
||||
echo "$private_key" | base64 -d > module/private_key
|
||||
echo "$public_key" | base64 -d > module/public_key
|
||||
fi
|
||||
|
||||
- name: Build with Gradle
|
||||
run: |
|
||||
echo 'org.gradle.parallel=true' >> gradle.properties
|
||||
echo 'org.gradle.vfs.watch=true' >> gradle.properties
|
||||
echo 'org.gradle.jvmargs=-Xmx2048m' >> gradle.properties
|
||||
sed -i 's/org.gradle.unsafe.configuration-cache=true//g' gradle.properties
|
||||
./gradlew zipRelease
|
||||
./gradlew zipDebug
|
||||
|
||||
- name: Prepare artifact
|
||||
if: success()
|
||||
id: prepareArtifact
|
||||
run: |
|
||||
releaseName=`ls module/build/outputs/release/ReZygisk-v*-release.zip | awk -F '(/|.zip)' '{print $5}'` && echo "releaseName=$releaseName" >> $GITHUB_OUTPUT
|
||||
debugName=`ls module/build/outputs/release/ReZygisk-v*-debug.zip | awk -F '(/|.zip)' '{print $5}'` && echo "debugName=$debugName" >> $GITHUB_OUTPUT
|
||||
unzip module/build/outputs/release/ReZygisk-v*-release.zip -d zksu-release
|
||||
unzip module/build/outputs/release/ReZygisk-v*-debug.zip -d zksu-debug
|
||||
|
||||
- name: Upload release
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ steps.prepareArtifact.outputs.releaseName }}
|
||||
path: "./zksu-release/*"
|
||||
|
||||
- name: Upload debug
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ steps.prepareArtifact.outputs.debugName }}
|
||||
path: "./zksu-debug/*"
|
||||
4
.gitmodules
vendored
4
.gitmodules
vendored
@@ -1,3 +1,3 @@
|
||||
[submodule "LSPlt"]
|
||||
[submodule "loader/src/external/lsplt"]
|
||||
path = loader/src/external/lsplt
|
||||
url = https://github.com/PerformanC/LSPlt
|
||||
url = https://github.com/JingMatrix/LSPlt
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
- **es_ES** by [@LuchoModzzz](https://github.com/Lxchoooo)
|
||||
- **es_MX** by [@LuchoModzzz](https://github.com/Lxchoooo)
|
||||
- **fr_FR** by [@GhostFRR](https://github.com/GhostFRR)
|
||||
- **ja_JP** by [@Fyphen1223](https://github.com/Fyphen1223) & [@reindex-ot](https://github.com/reindex-ot)
|
||||
- **ja_JP** by [@Fyphen1223](https://github.com/Fyphen1223)
|
||||
- **id_ID** by [@bpanca05](https://github.com/bpanca05) & [@LuckyKiddos](https://github.com/GuitarHeroStyles)
|
||||
- **it_IT** by [@thasave14](https://github.com/thasave14)
|
||||
- **pt_BR** by [@ThePedroo](https://github.com/ThePedroo)
|
||||
- **ro_RO** by [@ExtremeXT](https://github.com/ExtremeXT)
|
||||
- **ru_RU** by [@Emulond](https://github.com/Emulond) & [@AJleKcAHgP68](https://github.com/AJleKcAHgP68)
|
||||
- **tr_TR** by [@witchfuneral](https://github.com/witchfuneral)
|
||||
- **tr_TR** by [@dyingwillow](https://github.com/dyingwillow)
|
||||
- **uk_UA** by [@Kittyskj](https://github.com/Kittyskj)
|
||||
- **vi_VN** by [@RainyXeon](https://github.com/RainyXeon)
|
||||
- **zh_CN** by [@Meltartica](https://github.com/Meltartica) & [@SheepChef](https://github.com/SheepChef)
|
||||
|
||||
@@ -18,7 +18,7 @@ fun String.execute(currentWorkingDir: File = file("./")): String {
|
||||
val gitCommitCount = "git rev-list HEAD --count".execute().toInt()
|
||||
val gitCommitHash = "git rev-parse --verify --short HEAD".execute()
|
||||
|
||||
val moduleId by extra("rezygisk")
|
||||
val moduleId by extra("zygisksu")
|
||||
val moduleName by extra("ReZygisk")
|
||||
val verName by extra("v1.0.0")
|
||||
val verCode by extra(gitCommitCount)
|
||||
@@ -38,18 +38,19 @@ val androidSourceCompatibility by extra(JavaVersion.VERSION_11)
|
||||
val androidTargetCompatibility by extra(JavaVersion.VERSION_11)
|
||||
|
||||
tasks.register("Delete", Delete::class) {
|
||||
delete(layout.buildDirectory.get())
|
||||
delete(rootProject.buildDir)
|
||||
}
|
||||
|
||||
fun Project.configureBaseExtension() {
|
||||
extensions.findByType(LibraryExtension::class)?.run {
|
||||
namespace = "com.performanc.org.rezygisk"
|
||||
namespace = "icu.nullptr.zygisk.next"
|
||||
compileSdk = androidCompileSdkVersion
|
||||
ndkVersion = androidCompileNdkVersion
|
||||
buildToolsVersion = androidBuildToolsVersion
|
||||
|
||||
defaultConfig {
|
||||
minSdk = androidMinSdkVersion
|
||||
targetSdk = androidTargetSdkVersion
|
||||
}
|
||||
|
||||
lint {
|
||||
|
||||
@@ -535,10 +535,8 @@ ElfW(Addr) GnuLookup(ElfImg *restrict img, const char *name, uint32_t hash) {
|
||||
((uintptr_t)1 << ((hash >> img->gnu_shift2_) % bloom_mask_bits));
|
||||
|
||||
if ((mask & bloom_word) != mask) {
|
||||
/* INFO: Very loggy -- generates too much noise. GNU is rarely used for Zygisk context. */
|
||||
/* LOGW("Symbol '%s' (hash %u) filtered out by GNU Bloom Filter (idx %zu, mask 0x%lx, word 0x%lx)",
|
||||
name, hash, bloom_idx, (unsigned long)mask, (unsigned long)bloom_word);
|
||||
*/
|
||||
LOGE("Symbol '%s' (hash %u) filtered out by GNU Bloom Filter (idx %zu, mask 0x%lx, word 0x%lx)",
|
||||
name, hash, bloom_idx, (unsigned long)mask, (unsigned long)bloom_word);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
2
loader/src/external/lsplt
vendored
2
loader/src/external/lsplt
vendored
Submodule loader/src/external/lsplt updated: dc62fbe05e...984804293e
@@ -4,9 +4,6 @@
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#define IS_ISOLATED_SERVICE(uid) \
|
||||
((uid) >= 90000 && (uid) < 1000000)
|
||||
|
||||
/*
|
||||
* Bionic's atoi runs through strtol().
|
||||
* Use our own implementation for faster conversion.
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
#include <linux/seccomp.h>
|
||||
#include <linux/filter.h>
|
||||
#include <linux/audit.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "logging.h"
|
||||
|
||||
static bool seccomp_filters_visible() {
|
||||
FILE *status_file = fopen("/proc/self/status", "r");
|
||||
if (!status_file) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *needle = "Seccomp_filters:";
|
||||
char line[256];
|
||||
|
||||
while (fgets(line, sizeof(line), status_file)) {
|
||||
if (strncmp(line, needle, strlen(needle)) == 0) {
|
||||
fclose(status_file);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(status_file);
|
||||
return false;
|
||||
}
|
||||
|
||||
void send_seccomp_event() {
|
||||
if (seccomp_filters_visible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
__u32 args[4] = {0};
|
||||
|
||||
int rnd_fd = open("/dev/urandom", O_RDONLY);
|
||||
if (rnd_fd == -1) {
|
||||
PLOGE("send_seccomp_event: open(/dev/urandom)");
|
||||
return;
|
||||
}
|
||||
|
||||
if (read(rnd_fd, &args, sizeof(args)) != sizeof(args)) {
|
||||
PLOGE("send_seccomp_event: read(rnd_fd)");
|
||||
close(rnd_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
close(rnd_fd);
|
||||
|
||||
args[0] |= 0x10000;
|
||||
|
||||
struct sock_filter filter[] = {
|
||||
/* INFO: Check syscall number */
|
||||
BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)),
|
||||
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_exit_group, 0, 9),
|
||||
|
||||
/* INFO: Load and check arg0 (lower 32 bits) */
|
||||
BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])),
|
||||
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, args[0], 0, 7),
|
||||
|
||||
/* INFO: Load and check arg1 (lower 32 bits) */
|
||||
BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[1])),
|
||||
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, args[1], 0, 5),
|
||||
|
||||
/* INFO: Load and check arg2 (lower 32 bits) */
|
||||
BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[2])),
|
||||
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, args[2], 0, 3),
|
||||
|
||||
/* INFO: Load and check arg3 (lower 32 bits) */
|
||||
BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[3])),
|
||||
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, args[3], 0, 1),
|
||||
|
||||
/* INFO: All match: return TRACE => will trigger PTRACE_EVENT_SECCOMP */
|
||||
BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_TRACE),
|
||||
|
||||
/* INFO: Default: allow */
|
||||
BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
|
||||
};
|
||||
|
||||
struct sock_fprog prog = {
|
||||
.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
|
||||
.filter = filter,
|
||||
};
|
||||
|
||||
if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
|
||||
PLOGE("send_seccomp_event: prctl(SECCOMP)");
|
||||
return;
|
||||
}
|
||||
|
||||
/* INFO: This will trigger a ptrace event, syscall will not execute due to tracee_skip_syscall */
|
||||
syscall(__NR_exit_group, args[0], args[1], args[2], args[3]);
|
||||
}
|
||||
@@ -22,8 +22,5 @@ void entry(void* addr, size_t size, const char* path) {
|
||||
|
||||
LOGD("start plt hooking");
|
||||
hook_functions();
|
||||
|
||||
void *module_addrs[1] = { addr };
|
||||
clean_trace(path, module_addrs, 1, 1, 0, false);
|
||||
send_seccomp_event();
|
||||
clean_trace(path, 1, 0, false);
|
||||
}
|
||||
|
||||
@@ -98,7 +98,6 @@ struct ZygiskContext {
|
||||
~ZygiskContext();
|
||||
|
||||
/* Zygisksu changed: Load module fds */
|
||||
bool load_modules_only();
|
||||
void run_modules_pre();
|
||||
void run_modules_post();
|
||||
DCL_PRE_POST(fork)
|
||||
@@ -125,8 +124,6 @@ struct ZygiskContext {
|
||||
vector<tuple<dev_t, ino_t, const char *, void **>> *plt_hook_list;
|
||||
map<string, vector<JNINativeMethod>> *jni_hook_list;
|
||||
bool should_unmap_zygisk = false;
|
||||
bool enable_unloader = false;
|
||||
bool hooked_unloader = false;
|
||||
std::vector<lsplt::MapInfo> cached_map_infos = {};
|
||||
|
||||
} // namespace
|
||||
@@ -218,9 +215,6 @@ DCL_HOOK_FUNC(int, pthread_attr_setstacksize, void *target, size_t size) {
|
||||
int res = old_pthread_attr_setstacksize((pthread_attr_t *)target, size);
|
||||
LOGV("Call pthread_attr_setstacksize in [tid, pid]: %d, %d", gettid(), getpid());
|
||||
|
||||
if (!enable_unloader)
|
||||
return res;
|
||||
|
||||
// Only perform unloading on the main thread
|
||||
if (gettid() != getpid())
|
||||
return res;
|
||||
@@ -255,27 +249,6 @@ DCL_HOOK_FUNC(char *, strdup, const char *s) {
|
||||
return old_strdup(s);
|
||||
}
|
||||
|
||||
/*
|
||||
* INFO: Our goal is to get called after libart.so is loaded, but before ART actually starts running.
|
||||
* If we are too early, we won't find libart.so in maps, and if we are too late, we could make other
|
||||
* threads crash if they try to use the PLT while we are in the process of hooking it.
|
||||
* For this task, hooking property_get was chosen as there are lots of calls to this, so it's
|
||||
* relatively unlikely to break.
|
||||
*
|
||||
* The line where libart.so is loaded is:
|
||||
* https://github.com/aosp-mirror/platform_frameworks_base/blob/1cdfff555f4a21f71ccc978290e2e212e2f8b168/core/jni/AndroidRuntime.cpp#L1266
|
||||
*
|
||||
* And shortly after that, in the startVm method that is called right after, there are many calls to property_get:
|
||||
* https://github.com/aosp-mirror/platform_frameworks_base/blob/1cdfff555f4a21f71ccc978290e2e212e2f8b168/core/jni/AndroidRuntime.cpp#L791
|
||||
*
|
||||
* After we succeed in getting called at a point where libart.so is already loaded, we will ignore
|
||||
* the rest of the property_get calls.
|
||||
*/
|
||||
DCL_HOOK_FUNC(int, property_get, const char *key, char *value, const char *default_value) {
|
||||
hook_unloader();
|
||||
return old_property_get(key, value, default_value);
|
||||
}
|
||||
|
||||
#undef DCL_HOOK_FUNC
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
@@ -628,11 +601,9 @@ void ZygiskContext::sanitize_fds() {
|
||||
struct dirent *entry;
|
||||
while ((entry = readdir(dir))) {
|
||||
int fd = parse_int(entry->d_name);
|
||||
if (fd < 0 || fd > MAX_FD_SIZE || fd == dfd || allowed_fds[fd]) continue;
|
||||
if (fd < 0 || fd < MAX_FD_SIZE || fd == dfd || allowed_fds[fd]) continue;
|
||||
|
||||
close(fd);
|
||||
|
||||
LOGW("Closed leaked fd: %d", fd);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
@@ -644,12 +615,13 @@ void ZygiskContext::fork_post() {
|
||||
g_ctx = nullptr;
|
||||
}
|
||||
|
||||
bool ZygiskContext::load_modules_only() {
|
||||
/* Zygisksu changed: Load module fds */
|
||||
void ZygiskContext::run_modules_pre() {
|
||||
struct zygisk_modules ms;
|
||||
if (rezygiskd_read_modules(&ms) == false) {
|
||||
LOGE("Failed to read modules from zygiskd");
|
||||
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < ms.modules_count; i++) {
|
||||
@@ -676,11 +648,6 @@ bool ZygiskContext::load_modules_only() {
|
||||
|
||||
free_modules(&ms);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Zygisksu changed: Load module fds */
|
||||
void ZygiskContext::run_modules_pre() {
|
||||
for (auto &m : modules) {
|
||||
m.onLoad(env);
|
||||
|
||||
@@ -702,19 +669,7 @@ void ZygiskContext::run_modules_post() {
|
||||
|
||||
if (modules.size() > 0) {
|
||||
LOGD("modules unloaded: %zu/%zu", modules_unloaded, modules.size());
|
||||
|
||||
/* INFO: While Variable Length Arrays (VLAs) aren't usually
|
||||
recommended due to the ease of using too much of the
|
||||
stack, this should be fine since it should not be
|
||||
possible to exhaust the stack with only a few addresses. */
|
||||
void *module_addrs[modules.size() * sizeof(void *)];
|
||||
|
||||
size_t i = 0;
|
||||
for (const auto &m : modules) {
|
||||
module_addrs[i++] = m.getEntry();
|
||||
}
|
||||
|
||||
clean_trace("/data/adb", module_addrs, modules.size(), modules.size(), modules_unloaded, true);
|
||||
clean_trace("/data/adb", modules.size(), modules_unloaded, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -722,48 +677,7 @@ void ZygiskContext::run_modules_post() {
|
||||
void ZygiskContext::app_specialize_pre() {
|
||||
flags[APP_SPECIALIZE] = true;
|
||||
|
||||
/* INFO: Isolated services have different UIDs than the main apps. Because
|
||||
numerous root implementations base themselves in the UID of the
|
||||
app, we need to ensure that the UID sent to ReZygiskd to search
|
||||
is the app's and not the isolated service, or else it will be
|
||||
able to bypass DenyList.
|
||||
|
||||
All apps, and isolated processes, of *third-party* applications will
|
||||
have their app_data_dir set. The system applications might not have
|
||||
one, however it is unlikely they will create an isolated process,
|
||||
and even if so, it should not impact in detections, performance or
|
||||
any area.
|
||||
*/
|
||||
uid_t uid = args.app->uid;
|
||||
if (IS_ISOLATED_SERVICE(uid) && args.app->app_data_dir) {
|
||||
/* INFO: If the app is an isolated service, we use the UID of the
|
||||
app's process data directory, which is the UID of the
|
||||
app itself, which root implementations actually use.
|
||||
*/
|
||||
const char *data_dir = env->GetStringUTFChars(args.app->app_data_dir, NULL);
|
||||
if (!data_dir) {
|
||||
LOGE("Failed to get app data directory");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
struct stat st;
|
||||
if (stat(data_dir, &st) == -1) {
|
||||
PLOGE("Failed to stat app data directory [%s]", data_dir);
|
||||
|
||||
env->ReleaseStringUTFChars(args.app->app_data_dir, data_dir);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
uid = st.st_uid;
|
||||
|
||||
LOGD("Isolated service being related to UID %d, app data dir: %s", uid, data_dir);
|
||||
|
||||
env->ReleaseStringUTFChars(args.app->app_data_dir, data_dir);
|
||||
}
|
||||
|
||||
info_flags = rezygiskd_get_process_flags(uid, (const char *const)process);
|
||||
info_flags = rezygiskd_get_process_flags(g_ctx->args.app->uid, (const char *const)process);
|
||||
if (info_flags & PROCESS_IS_FIRST_STARTED) {
|
||||
/* INFO: To ensure we are really using a clean mount namespace, we use
|
||||
the first process it as reference for clean mount namespace,
|
||||
@@ -773,64 +687,33 @@ void ZygiskContext::app_specialize_pre() {
|
||||
update_mnt_ns(Clean, true);
|
||||
}
|
||||
|
||||
if ((info_flags & PROCESS_IS_MANAGER) == PROCESS_IS_MANAGER) {
|
||||
if ((info_flags & (PROCESS_IS_MANAGER | PROCESS_ROOT_IS_MAGISK)) == (PROCESS_IS_MANAGER | PROCESS_ROOT_IS_MAGISK)) {
|
||||
LOGD("Manager process detected. Notifying that Zygisk has been enabled.");
|
||||
|
||||
/* INFO: This environment variable is related to Magisk Zygisk/Manager. It
|
||||
it used by Magisk's Zygisk to communicate to Magisk Manager whether
|
||||
Zygisk is working or not, allowing Zygisk modules to both work properly
|
||||
and for the manager to mark Zygisk as enabled.
|
||||
Zygisk is working or not.
|
||||
|
||||
However, to enhance capabilities of root managers, it is also set for
|
||||
any other supported manager, so that, if they wish, they can recognize
|
||||
if Zygisk is enabled.
|
||||
*/
|
||||
To allow Zygisk modules to both work properly and for the manager to
|
||||
identify Zygisk, being it not built-in, as working, we also set it. */
|
||||
setenv("ZYGISK_ENABLED", "1", 1);
|
||||
} else {
|
||||
/* INFO: Because we load directly from the file, we need to do it before we umount
|
||||
the mounts, or else it won't have access to /data/adb anymore.
|
||||
*/
|
||||
if (!load_modules_only()) {
|
||||
LOGE("Failed to load modules");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* INFO: Modules only have two "start off" points from Zygisk, preSpecialize and
|
||||
postSpecialize. In preSpecialize, the process still has privileged
|
||||
permissions, and therefore can execute mount/umount/setns functions.
|
||||
If we update the mount namespace AFTER executing them, any mounts made
|
||||
will be lost, and the process will not have access to them anymore.
|
||||
|
||||
In postSpecialize, while still could have its mounts modified with the
|
||||
assistance of a Zygisk companion, it will already have the mount
|
||||
namespace switched by then, so there won't be issues.
|
||||
|
||||
Knowing this, we update the mns before execution, so that they can still
|
||||
make changes to mounts in DenyListed processes without being reverted.
|
||||
postSpecialize. While preSpecialie in fact runs with Zygote (not superuser)
|
||||
privileges, in postSpecialize it will now be with lower permission, in
|
||||
the app's sandbox and therefore can move to a clean mount namespace after
|
||||
executing the modules preSpecialize.
|
||||
*/
|
||||
bool in_denylist = (info_flags & PROCESS_ON_DENYLIST) == PROCESS_ON_DENYLIST;
|
||||
if (in_denylist) {
|
||||
flags[DO_REVERT_UNMOUNT] = true;
|
||||
if ((info_flags & PROCESS_ON_DENYLIST) == PROCESS_ON_DENYLIST) {
|
||||
flags[DO_REVERT_UNMOUNT] = true;
|
||||
|
||||
update_mnt_ns(Clean, false);
|
||||
update_mnt_ns(Clean, false);
|
||||
}
|
||||
|
||||
/* INFO: Executed after setns to ensure a module can update the mounts of an
|
||||
application without worrying about it being overwritten by setns.
|
||||
*/
|
||||
run_modules_pre();
|
||||
|
||||
/* INFO: The modules may request that although the process is NOT in
|
||||
the DenyList, it has its mount namespace switched to the clean
|
||||
one.
|
||||
|
||||
So to ensure this behavior happens, we must also check after the
|
||||
modules are loaded and executed, so that the modules can have
|
||||
the chance to request it.
|
||||
*/
|
||||
if (!in_denylist && flags[DO_REVERT_UNMOUNT])
|
||||
update_mnt_ns(Clean, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -876,7 +759,6 @@ void ZygiskContext::nativeForkSystemServer_pre() {
|
||||
if (!is_child())
|
||||
return;
|
||||
|
||||
load_modules_only();
|
||||
run_modules_pre();
|
||||
rezygiskd_system_server_started();
|
||||
|
||||
@@ -939,7 +821,7 @@ ZygiskContext::~ZygiskContext() {
|
||||
m.clearApi();
|
||||
}
|
||||
|
||||
enable_unloader = true;
|
||||
hook_unloader();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -967,35 +849,19 @@ static void hook_register(dev_t dev, ino_t inode, const char *symbol, void *new_
|
||||
#define PLT_HOOK_REGISTER(DEV, INODE, NAME) \
|
||||
PLT_HOOK_REGISTER_SYM(DEV, INODE, #NAME, NAME)
|
||||
|
||||
/* INFO: module_addrs_length is always the same as "load" */
|
||||
void clean_trace(const char *path, void **module_addrs, size_t module_addrs_length, size_t load, size_t unload, bool spoof_maps) {
|
||||
void clean_trace(const char* path, size_t load, size_t unload, bool spoof_maps) {
|
||||
LOGD("cleaning trace for path %s", path);
|
||||
|
||||
if (load > 0 || unload > 0) solist_reset_counters(load, unload);
|
||||
|
||||
LOGD("Dropping solist record for %s", path);
|
||||
|
||||
bool any_dropped = false;
|
||||
for (size_t i = 0; i < module_addrs_length; i++) {
|
||||
bool local_any_dropped = solist_drop_so_path(module_addrs[i]);
|
||||
if (!local_any_dropped) continue;
|
||||
|
||||
any_dropped = true;
|
||||
|
||||
LOGD("Dropped solist record for %p", module_addrs[i]);
|
||||
}
|
||||
|
||||
if (!any_dropped || !spoof_maps) return;
|
||||
bool path_found = solist_drop_so_path(path);
|
||||
if (!path_found || !spoof_maps) return;
|
||||
|
||||
LOGD("spoofing virtual maps for %s", path);
|
||||
|
||||
/* INFO: Spoofing maps names is futile, after all it will
|
||||
still show up in /proc/self/(s)maps but with a
|
||||
different name, however still detectable by
|
||||
checking the permissions. This, however, avoids
|
||||
just checking for "zygisk". */
|
||||
|
||||
/* TODO: Use SoList to map through libraries to avoid open /proc/self/maps here */
|
||||
// spoofing map names is futile in Android, we do it simply
|
||||
// to avoid Zygisk detections based on string comparison
|
||||
for (auto &map : lsplt::MapInfo::Scan()) {
|
||||
if (strstr(map.path.c_str(), path) && strstr(map.path.c_str(), "libzygisk") == 0)
|
||||
{
|
||||
@@ -1011,8 +877,8 @@ void clean_trace(const char *path, void **module_addrs, size_t module_addrs_leng
|
||||
mprotect(addr, size, PROT_READ);
|
||||
}
|
||||
memcpy(copy, addr, size);
|
||||
mprotect(copy, size, map.perms);
|
||||
mremap(copy, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, addr);
|
||||
mprotect(addr, size, map.perms);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1037,7 +903,6 @@ void hook_functions() {
|
||||
PLT_HOOK_REGISTER(android_runtime_dev, android_runtime_inode, fork);
|
||||
PLT_HOOK_REGISTER(android_runtime_dev, android_runtime_inode, unshare);
|
||||
PLT_HOOK_REGISTER(android_runtime_dev, android_runtime_inode, strdup);
|
||||
PLT_HOOK_REGISTER(android_runtime_dev, android_runtime_inode, property_get);
|
||||
hook_commit();
|
||||
|
||||
// Remove unhooked methods
|
||||
@@ -1048,13 +913,9 @@ void hook_functions() {
|
||||
}
|
||||
|
||||
static void hook_unloader() {
|
||||
if (hooked_unloader) return;
|
||||
hooked_unloader = true;
|
||||
|
||||
ino_t art_inode = 0;
|
||||
dev_t art_dev = 0;
|
||||
|
||||
cached_map_infos = lsplt::MapInfo::Scan();
|
||||
for (auto &map : cached_map_infos) {
|
||||
if (map.path.ends_with("/libart.so")) {
|
||||
art_inode = map.inode;
|
||||
@@ -1064,16 +925,7 @@ static void hook_unloader() {
|
||||
}
|
||||
|
||||
if (art_dev == 0 || art_inode == 0) {
|
||||
/*
|
||||
* INFO: If we are here, it means we are too early and libart.so hasn't loaded yet when
|
||||
* property_get was called. This doesn't normally happen, but we try again next time
|
||||
* just to be safe.
|
||||
*/
|
||||
|
||||
LOGE("virtual map for libart.so is not cached");
|
||||
|
||||
hooked_unloader = false;
|
||||
|
||||
return;
|
||||
} else {
|
||||
LOGD("hook_unloader called with libart.so [%zu:%lu]", art_dev, art_inode);
|
||||
|
||||
@@ -213,7 +213,6 @@ case 5: \
|
||||
bool tryUnload() const { return unload && dlclose(handle) == 0; };
|
||||
void clearApi() { memset(&api, 0, sizeof(api)); }
|
||||
int getId() const { return id; }
|
||||
void *getEntry() const { return entry.ptr; }
|
||||
|
||||
ZygiskModule(int id, void *handle, void *entry);
|
||||
|
||||
|
||||
@@ -2,28 +2,27 @@
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <android/dlext.h>
|
||||
|
||||
#include <linux/limits.h>
|
||||
|
||||
#include "elf_util.h"
|
||||
#include "logging.h"
|
||||
|
||||
#include "solist.h"
|
||||
|
||||
/* TODO: Is offset for realpath necessary? It seems to have the function
|
||||
available anywhere. */
|
||||
#ifdef __LP64__
|
||||
size_t solist_size_offset = 0x18;
|
||||
size_t solist_next_offset = 0x30;
|
||||
size_t solist_realpath_offset = 0x1a8;
|
||||
#else
|
||||
size_t solist_size_offset = 0x90;
|
||||
size_t solist_next_offset = 0xa4;
|
||||
size_t solist_realpath_offset = 0x174;
|
||||
#endif
|
||||
|
||||
static const char *(*get_realpath_sym)(SoInfo *) = NULL;
|
||||
static void (*soinfo_free)(SoInfo *) = NULL;
|
||||
static SoInfo *(*find_containing_library)(const void *p) = NULL;
|
||||
|
||||
static inline SoInfo *get_next(SoInfo *self) {
|
||||
return *(SoInfo **)((uintptr_t)self + solist_next_offset);
|
||||
}
|
||||
|
||||
static inline const char *get_path(SoInfo *self) {
|
||||
if (get_realpath_sym)
|
||||
@@ -36,7 +35,11 @@ static inline void set_size(SoInfo *self, size_t size) {
|
||||
*(size_t *) ((uintptr_t)self + solist_size_offset) = size;
|
||||
}
|
||||
|
||||
struct pdg ppdg = { 0 };
|
||||
static inline size_t get_size(SoInfo *self) {
|
||||
return *(size_t *) ((uintptr_t)self + solist_size_offset);
|
||||
}
|
||||
|
||||
struct pdg ppdg;
|
||||
|
||||
static bool pdg_setup(ElfImg *img) {
|
||||
ppdg.ctor = (void *(*)())getSymbAddress(img, "__dl__ZN18ProtectedDataGuardC2Ev");
|
||||
@@ -45,20 +48,22 @@ static bool pdg_setup(ElfImg *img) {
|
||||
return ppdg.ctor != NULL && ppdg.dtor != NULL;
|
||||
}
|
||||
|
||||
/* INFO: Allow data to be written to the areas. */
|
||||
static void pdg_unprotect() {
|
||||
(*ppdg.ctor)();
|
||||
}
|
||||
|
||||
/* INFO: Block write and only allow read access to the areas. */
|
||||
static void pdg_protect() {
|
||||
(*ppdg.dtor)();
|
||||
if (ppdg.ctor != NULL)
|
||||
(*(ppdg.ctor))();
|
||||
}
|
||||
|
||||
static SoInfo *somain = NULL;
|
||||
static void pdg_unprotect() {
|
||||
if (ppdg.dtor != NULL)
|
||||
(*(ppdg.dtor))();
|
||||
}
|
||||
|
||||
static size_t *g_module_load_counter = NULL;
|
||||
static size_t *g_module_unload_counter = NULL;
|
||||
static SoInfo *solist = NULL;
|
||||
static SoInfo *somain = NULL;
|
||||
static SoInfo **sonext = NULL;
|
||||
|
||||
static uint64_t *g_module_load_counter = NULL;
|
||||
static uint64_t *g_module_unload_counter = NULL;
|
||||
|
||||
static bool solist_init() {
|
||||
#ifdef __LP64__
|
||||
@@ -72,6 +77,10 @@ static bool solist_init() {
|
||||
return false;
|
||||
}
|
||||
|
||||
ppdg = (struct pdg) {
|
||||
.ctor = NULL,
|
||||
.dtor = NULL
|
||||
};
|
||||
if (!pdg_setup(linker)) {
|
||||
LOGE("Failed to setup pdg");
|
||||
|
||||
@@ -87,6 +96,17 @@ static bool solist_init() {
|
||||
|
||||
See #63 for more information.
|
||||
*/
|
||||
solist = (SoInfo *)getSymbValueByPrefix(linker, "__dl__ZL6solist");
|
||||
if ((void *)solist == NULL) {
|
||||
LOGE("Failed to find solist __dl__ZL6solist*");
|
||||
|
||||
ElfImg_destroy(linker);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
LOGD("%p is solist", (void *)solist);
|
||||
|
||||
somain = (SoInfo *)getSymbValueByPrefix(linker, "__dl__ZL6somain");
|
||||
if (somain == NULL) {
|
||||
LOGE("Failed to find somain __dl__ZL6somain*");
|
||||
@@ -98,6 +118,20 @@ static bool solist_init() {
|
||||
|
||||
LOGD("%p is somain", (void *)somain);
|
||||
|
||||
sonext = (SoInfo **)getSymbAddressByPrefix(linker, "__dl__ZL6sonext");
|
||||
if (sonext == NULL) {
|
||||
LOGE("Failed to find sonext __dl__ZL6sonext*");
|
||||
|
||||
ElfImg_destroy(linker);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
LOGD("%p is sonext", (void *)sonext);
|
||||
|
||||
SoInfo *vdso = (SoInfo *)getSymbValueByPrefix(linker, "__dl__ZL4vdso");
|
||||
if (vdso != NULL) LOGD("%p is vdso", (void *)vdso);
|
||||
|
||||
get_realpath_sym = (const char *(*)(SoInfo *))getSymbAddress(linker, "__dl__ZNK6soinfo12get_realpathEv");
|
||||
if (get_realpath_sym == NULL) {
|
||||
LOGE("Failed to find get_realpath __dl__ZNK6soinfo12get_realpathEv");
|
||||
@@ -120,28 +154,25 @@ static bool solist_init() {
|
||||
|
||||
LOGD("%p is soinfo_free", (void *)soinfo_free);
|
||||
|
||||
find_containing_library = (SoInfo *(*)(const void *))getSymbAddress(linker, "__dl__Z23find_containing_libraryPKv");
|
||||
if (find_containing_library == NULL) {
|
||||
LOGE("Failed to find find_containing_library __dl__Z23find_containing_libraryPKv");
|
||||
|
||||
ElfImg_destroy(linker);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
g_module_load_counter = (size_t *)getSymbAddress(linker, "__dl__ZL21g_module_load_counter");
|
||||
g_module_load_counter = (uint64_t *)getSymbAddress(linker, "__dl__ZL21g_module_load_counter");
|
||||
if (g_module_load_counter != NULL) LOGD("found symbol g_module_load_counter");
|
||||
|
||||
g_module_unload_counter = (size_t *)getSymbAddress(linker, "__dl__ZL23g_module_unload_counter");
|
||||
g_module_unload_counter = (uint64_t *)getSymbAddress(linker, "__dl__ZL23g_module_unload_counter");
|
||||
if (g_module_unload_counter != NULL) LOGD("found symbol g_module_unload_counter");
|
||||
|
||||
for (size_t i = 0; i < 1024 / sizeof(void *); i++) {
|
||||
uintptr_t possible_field = (uintptr_t)solist + i * sizeof(void *);
|
||||
size_t possible_size_of_somain = *(size_t *)((uintptr_t)somain + i * sizeof(void *));
|
||||
|
||||
if (possible_size_of_somain < 0x100000 && possible_size_of_somain > 0x100) {
|
||||
solist_size_offset = i * sizeof(void *);
|
||||
|
||||
LOGD("solist_size_offset is %zu * %zu = %p", i, sizeof(void *), (void *)solist_size_offset);
|
||||
}
|
||||
|
||||
if (*(void **)possible_field == somain || (vdso != NULL && *(void **)possible_field == vdso)) {
|
||||
solist_next_offset = i * sizeof(void *);
|
||||
LOGD("solist_next_offset is %zu * %zu = %p", i, sizeof(void *), (void *)solist_next_offset);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -152,49 +183,36 @@ static bool solist_init() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* INFO: find_containing_library returns the SoInfo for the library that contains
|
||||
that memory inside its limits, hence why named "lib_memory" in ReZygisk. */
|
||||
bool solist_drop_so_path(void *lib_memory) {
|
||||
if (somain == NULL && !solist_init()) {
|
||||
bool solist_drop_so_path(const char *target_path) {
|
||||
if (solist == NULL && !solist_init()) {
|
||||
LOGE("Failed to initialize solist");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SoInfo *found = (*find_containing_library)(lib_memory);
|
||||
if (found == NULL) {
|
||||
LOGD("Could not find containing library for %p", lib_memory);
|
||||
for (SoInfo *iter = solist; iter; iter = get_next(iter)) {
|
||||
if (get_path(iter) && strstr(get_path(iter), target_path)) {
|
||||
pdg_protect();
|
||||
|
||||
return false;
|
||||
LOGV("dropping solist record loaded at %s with size %zu", get_path(iter), get_size(iter));
|
||||
if (get_size(iter) > 0) {
|
||||
set_size(iter, 0);
|
||||
soinfo_free(iter);
|
||||
|
||||
pdg_unprotect();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
pdg_unprotect();
|
||||
}
|
||||
}
|
||||
|
||||
LOGD("Found so path for %p: %s", lib_memory, get_path(found));
|
||||
|
||||
char path[PATH_MAX];
|
||||
if (get_path(found) == NULL) {
|
||||
LOGE("Failed to get path for %p", found);
|
||||
|
||||
return false;
|
||||
}
|
||||
strcpy(path, get_path(found));
|
||||
|
||||
pdg_unprotect();
|
||||
|
||||
set_size(found, 0);
|
||||
soinfo_free(found);
|
||||
|
||||
pdg_protect();
|
||||
|
||||
LOGD("Successfully dropped so path for: %s", path);
|
||||
|
||||
/* INFO: Let's avoid trouble regarding detections */
|
||||
memset(path, strlen(path), 0);
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void solist_reset_counters(size_t load, size_t unload) {
|
||||
if (somain == NULL && !solist_init()) {
|
||||
if (solist == NULL && !solist_init()) {
|
||||
LOGE("Failed to initialize solist");
|
||||
|
||||
return;
|
||||
@@ -206,18 +224,18 @@ void solist_reset_counters(size_t load, size_t unload) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t loaded_modules = *g_module_load_counter;
|
||||
size_t unloaded_modules = *g_module_unload_counter;
|
||||
uint64_t loaded_modules = *g_module_load_counter;
|
||||
uint64_t unloaded_modules = *g_module_unload_counter;
|
||||
|
||||
if (loaded_modules >= load) {
|
||||
*g_module_load_counter -= load;
|
||||
*g_module_load_counter = loaded_modules - load;
|
||||
|
||||
LOGD("reset g_module_load_counter to %zu", *g_module_load_counter);
|
||||
LOGD("reset g_module_load_counter to %zu", (size_t) *g_module_load_counter);
|
||||
}
|
||||
|
||||
if (unloaded_modules >= unload) {
|
||||
*g_module_unload_counter -= unload;
|
||||
*g_module_unload_counter = unloaded_modules - unload;
|
||||
|
||||
LOGD("reset g_module_unload_counter to %zu", *g_module_unload_counter);
|
||||
LOGD("reset g_module_unload_counter to %zu", (size_t) *g_module_unload_counter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ struct pdg {
|
||||
SOURCES:
|
||||
- https://android.googlesource.com/platform/bionic/+/refs/heads/android15-release/linker/linker.cpp#1712
|
||||
*/
|
||||
bool solist_drop_so_path(void *lib_memory);
|
||||
bool solist_drop_so_path(const char *target_path);
|
||||
|
||||
/*
|
||||
INFO: When dlopen'ing a library, the system will increment 1 to a global
|
||||
|
||||
@@ -7,6 +7,4 @@ extern size_t block_size;
|
||||
|
||||
void hook_functions();
|
||||
|
||||
void clean_trace(const char *path, void **module_addrs, size_t module_addrs_length, size_t load, size_t unload, bool spoof_maps);
|
||||
|
||||
extern "C" void send_seccomp_event();
|
||||
void clean_trace(const char* path, size_t load = 1, size_t unload = 0, bool spoof_maps = false);
|
||||
|
||||
@@ -355,7 +355,7 @@ void rezygiskd_listener_callback() {
|
||||
case SYSTEM_SERVER_STARTED: {
|
||||
LOGD("system server started, mounting prop");
|
||||
|
||||
if (mount(PROP_PATH, "/data/adb/modules/rezygisk/module.prop", NULL, MS_BIND, NULL) == -1) {
|
||||
if (mount(PROP_PATH, "/data/adb/modules/zygisksu/module.prop", NULL, MS_BIND, NULL) == -1) {
|
||||
PLOGE("failed to mount prop");
|
||||
}
|
||||
|
||||
@@ -405,7 +405,7 @@ static bool ensure_daemon_created(bool is_64bit) {
|
||||
if (is_64bit || (!is_64bit && !status64.supported)) {
|
||||
LOGD("new zygote started.");
|
||||
|
||||
umount2("/data/adb/modules/rezygisk/module.prop", MNT_DETACH);
|
||||
umount2("/data/adb/modules/zygisksu/module.prop", MNT_DETACH);
|
||||
}
|
||||
|
||||
if (status->daemon_pid != -1) {
|
||||
@@ -800,7 +800,7 @@ static bool prepare_environment() {
|
||||
/* INFO: We need to create the file first, otherwise the mount will fail */
|
||||
close(open(PROP_PATH, O_WRONLY | O_CREAT | O_TRUNC, 0644));
|
||||
|
||||
FILE *orig_prop = fopen("/data/adb/modules/rezygisk/module.prop", "r");
|
||||
FILE *orig_prop = fopen("/data/adb/modules/zygisksu/module.prop", "r");
|
||||
if (orig_prop == NULL) {
|
||||
PLOGE("failed to open orig prop");
|
||||
|
||||
|
||||
@@ -159,43 +159,17 @@ bool inject_on_main(int pid, const char *lib_path) {
|
||||
void *libc_return_addr = find_module_return_addr(map, "libc.so");
|
||||
LOGD("libc return addr %p", libc_return_addr);
|
||||
|
||||
const char *libdl_path = NULL;
|
||||
const char *libc_path = NULL;
|
||||
for (size_t i = 0; i < local_map->size; i++) {
|
||||
if (local_map->maps[i].path == NULL) continue;
|
||||
|
||||
const char *filename = position_after(local_map->maps[i].path, '/');
|
||||
|
||||
if (strcmp(filename, "libdl.so") == 0) {
|
||||
libdl_path = local_map->maps[i].path;
|
||||
|
||||
/* INFO: If we had found libc.so too, no need to continue searching */
|
||||
if (libc_path) break;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(filename, "libc.so") == 0) {
|
||||
libc_path = local_map->maps[i].path;
|
||||
|
||||
/* INFO: If we had found libdl.so too, no need to continue searching */
|
||||
if (libdl_path) break;
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* call dlopen */
|
||||
void *dlopen_addr = NULL;
|
||||
if (!libdl_path || (dlopen_addr = find_func_addr(local_map, map, libdl_path, "dlopen")) == NULL) {
|
||||
#ifdef __LP64__
|
||||
void *dlopen_addr = find_func_addr(local_map, map, "/apex/com.android.runtime/lib64/bionic/libdl.so", "dlopen");
|
||||
#else
|
||||
void *dlopen_addr = find_func_addr(local_map, map, "/apex/com.android.runtime/lib/bionic/libdl.so", "dlopen");
|
||||
#endif
|
||||
if (dlopen_addr == NULL) {
|
||||
/* INFO: Android 7.1 and below doesn't have libdl.so loaded in Zygote */
|
||||
LOGW("Failed to find dlopen from libdl.so, will load from linker");
|
||||
|
||||
#ifdef __LP64__
|
||||
dlopen_addr = find_func_addr(local_map, map, "/system/bin/linker64", "__dl_dlopen");
|
||||
#else
|
||||
dlopen_addr = find_func_addr(local_map, map, "/system/bin/linker", "__dl_dlopen");
|
||||
#endif
|
||||
dlopen_addr = find_func_addr(local_map, map, "/system/bin/linker", "__dl_dlopen");
|
||||
if (dlopen_addr == NULL) {
|
||||
PLOGE("Find __dl_dlopen");
|
||||
|
||||
@@ -224,16 +198,16 @@ bool inject_on_main(int pid, const char *lib_path) {
|
||||
LOGE("handle is null");
|
||||
|
||||
/* call dlerror */
|
||||
void *dlerror_addr = NULL;
|
||||
if (!libdl_path || (dlerror_addr = find_func_addr(local_map, map, libdl_path, "dlerror")) == NULL) {
|
||||
#ifdef __LP64__
|
||||
void *dlerror_addr = find_func_addr(local_map, map, "/apex/com.android.runtime/lib64/bionic/libdl.so", "dlerror");
|
||||
#else
|
||||
void *dlerror_addr = find_func_addr(local_map, map, "/apex/com.android.runtime/lib/bionic/libdl.so", "dlerror");
|
||||
#endif
|
||||
if (dlerror_addr == NULL) {
|
||||
/* INFO: Android 7.1 and below doesn't have libdl.so loaded in Zygote */
|
||||
LOGW("Failed to find dlerror from libdl.so, will load from linker");
|
||||
|
||||
#ifdef __LP64__
|
||||
dlerror_addr = find_func_addr(local_map, map, "/system/bin/linker64", "__dl_dlerror");
|
||||
#else
|
||||
dlerror_addr = find_func_addr(local_map, map, "/system/bin/linker", "__dl_dlerror");
|
||||
#endif
|
||||
dlerror_addr = find_func_addr(local_map, map, "/system/bin/linker", "__dl_dlerror");
|
||||
if (dlerror_addr == NULL) {
|
||||
LOGE("Find __dl_dlerror");
|
||||
|
||||
@@ -251,19 +225,19 @@ bool inject_on_main(int pid, const char *lib_path) {
|
||||
LOGE("dlerror str is null");
|
||||
|
||||
free(args);
|
||||
free_maps(local_map);
|
||||
free_maps(map);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void *strlen_addr = find_func_addr(local_map, map, libc_path, "strlen");
|
||||
#ifdef __LP64__
|
||||
void *strlen_addr = find_func_addr(local_map, map, "/system/lib64/libc.so", "strlen");
|
||||
#else
|
||||
void *strlen_addr = find_func_addr(local_map, map, "/system/lib/libc.so", "strlen");
|
||||
#endif
|
||||
if (strlen_addr == NULL) {
|
||||
LOGE("find strlen");
|
||||
|
||||
free(args);
|
||||
free_maps(local_map);
|
||||
free_maps(map);
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -275,8 +249,6 @@ bool inject_on_main(int pid, const char *lib_path) {
|
||||
LOGE("dlerror len <= 0");
|
||||
|
||||
free(args);
|
||||
free_maps(local_map);
|
||||
free_maps(map);
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -286,8 +258,6 @@ bool inject_on_main(int pid, const char *lib_path) {
|
||||
LOGE("malloc err");
|
||||
|
||||
free(args);
|
||||
free_maps(local_map);
|
||||
free_maps(map);
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -299,23 +269,20 @@ bool inject_on_main(int pid, const char *lib_path) {
|
||||
free(err);
|
||||
free(args);
|
||||
|
||||
free_maps(local_map);
|
||||
free_maps(map);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* call dlsym(handle, "entry") */
|
||||
void *dlsym_addr = NULL;
|
||||
if (!libdl_path || (dlsym_addr = find_func_addr(local_map, map, libdl_path, "dlsym")) == NULL) {
|
||||
#ifdef __LP64__
|
||||
void *dlsym_addr = find_func_addr(local_map, map, "/apex/com.android.runtime/lib64/bionic/libdl.so", "dlsym");
|
||||
#else
|
||||
void *dlsym_addr = find_func_addr(local_map, map, "/apex/com.android.runtime/lib/bionic/libdl.so", "dlsym");
|
||||
#endif
|
||||
if (dlsym_addr == NULL) {
|
||||
/* INFO: Android 7.1 and below doesn't have libdl.so loaded in Zygote */
|
||||
LOGW("Failed to find dlsym from libdl.so, will load from linker");
|
||||
|
||||
#ifdef __LP64__
|
||||
dlsym_addr = find_func_addr(local_map, map, "/system/bin/linker64", "__dl_dlsym");
|
||||
#else
|
||||
dlsym_addr = find_func_addr(local_map, map, "/system/bin/linker", "__dl_dlsym");
|
||||
#endif
|
||||
dlsym_addr = find_func_addr(local_map, map, "/system/bin/linker", "__dl_dlsym");
|
||||
if (dlsym_addr == NULL) {
|
||||
LOGE("find __dl_dlsym");
|
||||
|
||||
@@ -403,7 +370,7 @@ bool trace_zygote(int pid) {
|
||||
|
||||
int status;
|
||||
|
||||
if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_O_EXITKILL | PTRACE_O_TRACESECCOMP) == -1) {
|
||||
if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_O_EXITKILL) == -1) {
|
||||
PLOGE("seize");
|
||||
|
||||
return false;
|
||||
@@ -438,16 +405,6 @@ bool trace_zygote(int pid) {
|
||||
if (STOPPED_WITH(SIGCONT, 0)) {
|
||||
LOGD("received SIGCONT");
|
||||
|
||||
/* INFO: Due to kernel bugs, fixed in 5.16+, ptrace_message (msg of
|
||||
PTRACE_GETEVENTMSG) may not represent the current state of
|
||||
the process. Because we set some options, which alters the
|
||||
ptrace_message, we need to call PTRACE_SYSCALL to reset the
|
||||
ptrace_message to 0, the default/normal state.
|
||||
*/
|
||||
ptrace(PTRACE_SYSCALL, pid, 0, 0);
|
||||
|
||||
WAIT_OR_DIE
|
||||
|
||||
ptrace(PTRACE_DETACH, pid, 0, SIGCONT);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -313,12 +313,20 @@ void *find_module_return_addr(struct maps *map, const char *suffix) {
|
||||
}
|
||||
|
||||
void *find_module_base(struct maps *map, const char *file) {
|
||||
const char *suffix = position_after(file, '/');
|
||||
if (!suffix) {
|
||||
LOGE("failed to find suffix in %s", file);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < map->size; i++) {
|
||||
if (map->maps[i].path == NULL) continue;
|
||||
|
||||
const char *file_path = map->maps[i].path;
|
||||
const char *file_name = position_after(map->maps[i].path, '/');
|
||||
if (!file_name) continue;
|
||||
|
||||
if (strlen(file_path) != strlen(file) || map->maps[i].offset != 0 || strncmp(file_path, file, strlen(file)) != 0) continue;
|
||||
if (strlen(file_name) < strlen(suffix) || map->maps[i].offset != 0 || strncmp(file_name, suffix, strlen(suffix)) != 0) continue;
|
||||
|
||||
return (void *)map->maps[i].start;
|
||||
}
|
||||
@@ -522,32 +530,6 @@ int fork_dont_care() {
|
||||
return pid;
|
||||
}
|
||||
|
||||
void tracee_skip_syscall(int pid) {
|
||||
struct user_regs_struct regs;
|
||||
if (!get_regs(pid, ®s)) {
|
||||
LOGE("failed to get seccomp regs");
|
||||
exit(1);
|
||||
}
|
||||
regs.REG_SYSNR = -1;
|
||||
if (!set_regs(pid, ®s)) {
|
||||
LOGE("failed to set seccomp regs");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* INFO: It might not work, don't check for error */
|
||||
#if defined(__aarch64__)
|
||||
int sysnr = -1;
|
||||
struct iovec iov = {
|
||||
.iov_base = &sysnr,
|
||||
.iov_len = sizeof (int),
|
||||
};
|
||||
ptrace(PTRACE_SETREGSET, pid, NT_ARM_SYSTEM_CALL, &iov);
|
||||
#elif defined(__arm__)
|
||||
ptrace(PTRACE_SET_SYSCALL, pid, 0, (void*) -1);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void wait_for_trace(int pid, int *status, int flags) {
|
||||
while (1) {
|
||||
pid_t result = waitpid(pid, status, flags);
|
||||
@@ -558,13 +540,7 @@ void wait_for_trace(int pid, int *status, int flags) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (*status >> 8 == (SIGTRAP | (PTRACE_EVENT_SECCOMP << 8))) {
|
||||
tracee_skip_syscall(pid);
|
||||
|
||||
ptrace(PTRACE_CONT, pid, 0, 0);
|
||||
|
||||
continue;
|
||||
} else if (!WIFSTOPPED(*status)) {
|
||||
if (!WIFSTOPPED(*status)) {
|
||||
char status_str[64];
|
||||
parse_status(*status, status_str, sizeof(status_str));
|
||||
|
||||
|
||||
@@ -37,22 +37,18 @@ void free_maps(struct maps *maps);
|
||||
#define REG_SP rsp
|
||||
#define REG_IP rip
|
||||
#define REG_RET rax
|
||||
#define REG_SYSNR orig_rax
|
||||
#elif defined(__i386__)
|
||||
#define REG_SP esp
|
||||
#define REG_IP eip
|
||||
#define REG_RET eax
|
||||
#define REG_SYSNR orig_eax
|
||||
#elif defined(__aarch64__)
|
||||
#define REG_SP sp
|
||||
#define REG_IP pc
|
||||
#define REG_RET regs[0]
|
||||
#define REG_SYSNR regs[8]
|
||||
#elif defined(__arm__)
|
||||
#define REG_SP uregs[13]
|
||||
#define REG_IP uregs[15]
|
||||
#define REG_RET uregs[0]
|
||||
#define REG_SYSNR uregs[7]
|
||||
#define user_regs_struct user_regs
|
||||
#endif
|
||||
|
||||
@@ -66,8 +62,6 @@ bool set_regs(int pid, struct user_regs_struct *regs);
|
||||
|
||||
void get_addr_mem_region(struct maps *map, uintptr_t addr, char *buf, size_t buf_size);
|
||||
|
||||
const char *position_after(const char *str, const char needle);
|
||||
|
||||
void *find_module_return_addr(struct maps *map, const char *suffix);
|
||||
|
||||
void *find_func_addr(struct maps *local_info, struct maps *remote_info, const char *module, const char *func);
|
||||
|
||||
@@ -93,6 +93,7 @@ androidComponents.onVariants { variant ->
|
||||
|
||||
doLast {
|
||||
if (file("private_key").exists()) {
|
||||
println("=== Guards the peace of Machikado ===")
|
||||
val privateKey = file("private_key").readBytes()
|
||||
val publicKey = file("public_key").readBytes()
|
||||
val namedSpec = NamedParameterSpec("ed25519")
|
||||
@@ -114,35 +115,6 @@ androidComponents.onVariants { variant ->
|
||||
}
|
||||
}
|
||||
|
||||
/* INFO: Misaki is the file that holds signed hash of
|
||||
all files of ReZygisk module, to ensure the
|
||||
zip (runtime and non-runtime) files hasn't
|
||||
been tampered with.
|
||||
*/
|
||||
fun misakiSign() {
|
||||
sig.initSign(privKey)
|
||||
|
||||
val filesToProcess = TreeSet<File> { f1, f2 ->
|
||||
f1.path.replace("\\", "/")
|
||||
.compareTo(f2.path.replace("\\", "/"))
|
||||
}
|
||||
|
||||
root.asFile.walkTopDown().forEach { file ->
|
||||
if (!file.isFile) return@forEach
|
||||
|
||||
val fileName = file.name
|
||||
if (fileName == "misaki.sig") return@forEach
|
||||
|
||||
filesToProcess.add(file)
|
||||
}
|
||||
|
||||
filesToProcess.forEach { file -> file.sha(file) }
|
||||
|
||||
val misakiSignatureFile = root.file("misaki.sig").asFile
|
||||
misakiSignatureFile.writeBytes(sig.sign())
|
||||
misakiSignatureFile.appendBytes(publicKey)
|
||||
}
|
||||
|
||||
fun getSign(name: String, abi: String, is64Bit: Boolean) {
|
||||
val set = TreeSet<Pair<File, File?>> { o1, o2 ->
|
||||
o1.first.path.replace("\\", "/")
|
||||
@@ -182,32 +154,11 @@ androidComponents.onVariants { variant ->
|
||||
signFile.appendBytes(publicKey)
|
||||
}
|
||||
|
||||
/* INFO: Machikado is the name of files that holds signed hash of
|
||||
all runtime files of ReZygisk module, to ensure the
|
||||
runtime files hasn't been tampered with.
|
||||
*/
|
||||
println("=== Guards the peace of Machikado ===")
|
||||
|
||||
getSign("machikado.arm64", "arm64-v8a", true)
|
||||
getSign("machikado.arm", "armeabi-v7a", false)
|
||||
|
||||
getSign("machikado.x86_64", "x86_64", true)
|
||||
getSign("machikado.x86", "x86", false)
|
||||
|
||||
fileTree(moduleDir).visit {
|
||||
if (isDirectory) return@visit
|
||||
|
||||
val md = MessageDigest.getInstance("SHA-256")
|
||||
file.forEachBlock(4096) { bytes, size ->
|
||||
md.update(bytes, 0, size)
|
||||
}
|
||||
|
||||
file(file.path + ".sha256").writeText(Hex.encodeHexString(md.digest()))
|
||||
}
|
||||
|
||||
println("=== At the kitsune's wedding ===")
|
||||
|
||||
misakiSign()
|
||||
} else {
|
||||
println("no private_key found, this build will not be signed")
|
||||
|
||||
@@ -216,19 +167,15 @@ androidComponents.onVariants { variant ->
|
||||
|
||||
root.file("machikado.x86_64").asFile.createNewFile()
|
||||
root.file("machikado.x86").asFile.createNewFile()
|
||||
}
|
||||
|
||||
fileTree(moduleDir).visit {
|
||||
if (isDirectory) return@visit
|
||||
|
||||
val md = MessageDigest.getInstance("SHA-256")
|
||||
file.forEachBlock(4096) { bytes, size ->
|
||||
md.update(bytes, 0, size)
|
||||
}
|
||||
|
||||
file(file.path + ".sha256").writeText(Hex.encodeHexString(md.digest()))
|
||||
fileTree(moduleDir).visit {
|
||||
if (isDirectory) return@visit
|
||||
val md = MessageDigest.getInstance("SHA-256")
|
||||
file.forEachBlock(4096) { bytes, size ->
|
||||
md.update(bytes, 0, size)
|
||||
}
|
||||
|
||||
root.file("misaki.sig").asFile.createNewFile()
|
||||
file(file.path + ".sha256").writeText(Hex.encodeHexString(md.digest()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ export async function getTranslations(locate) {
|
||||
}
|
||||
|
||||
export async function getAvailableLanguages() {
|
||||
const lsCmd = await exec('ls /data/adb/modules/rezygisk/webroot/lang')
|
||||
const lsCmd = await exec('ls /data/adb/modules/zygisksu/webroot/lang')
|
||||
|
||||
if (lsCmd.errno !== 0) return setError('WebUI', lsCmd.stderr)
|
||||
|
||||
|
||||
@@ -18,13 +18,13 @@ const monitor_status = document.getElementById('monitor_status');
|
||||
|
||||
monitor_status.innerHTML = translations.page.actions.status.tracing
|
||||
|
||||
exec('/data/adb/modules/rezygisk/bin/zygisk-ptrace64 ctl start')
|
||||
exec('/data/adb/modules/zygisksu/bin/zygisk-ptrace64 ctl start')
|
||||
})
|
||||
|
||||
monitor_stop.addEventListener('click', () => {
|
||||
monitor_status.innerHTML = translations.page.actions.status.exiting
|
||||
|
||||
exec('/data/adb/modules/rezygisk/bin/zygisk-ptrace64 ctl exit')
|
||||
exec('/data/adb/modules/zygisksu/bin/zygisk-ptrace64 ctl exit')
|
||||
})
|
||||
|
||||
monitor_pause.addEventListener('click', () => {
|
||||
@@ -32,7 +32,7 @@ const monitor_status = document.getElementById('monitor_status');
|
||||
|
||||
monitor_status.innerHTML = translations.page.actions.status.stopped
|
||||
|
||||
exec('/data/adb/modules/rezygisk/bin/zygisk-ptrace64 ctl stop')
|
||||
exec('/data/adb/modules/zygisksu/bin/zygisk-ptrace64 ctl stop')
|
||||
})
|
||||
}
|
||||
})()
|
||||
@@ -1,93 +0,0 @@
|
||||
{
|
||||
"langName": "日本語",
|
||||
"global": {
|
||||
"unknown": "不明"
|
||||
},
|
||||
"smallPage": {
|
||||
"language": {
|
||||
"header": "言語を選択してください"
|
||||
},
|
||||
"theme": {
|
||||
"header": "テーマを選択してください",
|
||||
"dark": "ダーク",
|
||||
"light": "ライト",
|
||||
"system": "システムベース"
|
||||
},
|
||||
"errorh": {
|
||||
"buttons": {
|
||||
"copy": "コピー",
|
||||
"clear": "すべてのログを消去"
|
||||
},
|
||||
"header": "エラーの履歴",
|
||||
"placeholder": "エラーログは記録されていません!"
|
||||
}
|
||||
},
|
||||
"page": {
|
||||
"home": {
|
||||
"header": "ホーム",
|
||||
"status": {
|
||||
"notWorking": "動作していません",
|
||||
"ok": "動作中",
|
||||
"partially": "部分的に動作中"
|
||||
},
|
||||
"info": {
|
||||
"version": "バージョン",
|
||||
"root": "Root の実装",
|
||||
"zygote": {
|
||||
"injected": "インジェクト済み",
|
||||
"notInjected": "未インジェクト",
|
||||
"unknown": "不明"
|
||||
}
|
||||
}
|
||||
},
|
||||
"modules": {
|
||||
"header": "モジュール",
|
||||
"notAvaliable": "Zygisk を使用するモジュールはありません。",
|
||||
"arch": "アーキテクチャ: "
|
||||
},
|
||||
"actions": {
|
||||
"header": "アクション",
|
||||
"monitorButton": {
|
||||
"start": "開始",
|
||||
"stop": "停止",
|
||||
"pause": "一時停止"
|
||||
},
|
||||
"monitor": "監視",
|
||||
"status": {
|
||||
"tracing": "トレース中",
|
||||
"stopping": "停止中",
|
||||
"stopped": "停止済み",
|
||||
"exiting": "終了中",
|
||||
"unknown": "不明"
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"header": "設定",
|
||||
"font": {
|
||||
"header": "システムフォントを有効化",
|
||||
"description": "現在の WebUI でシステムフォントの使用を有効化します。注意: FlipFont との互換性がない場合があります"
|
||||
},
|
||||
"theme": {
|
||||
"header": "システムテーマ",
|
||||
"description": "WebUI のシステムテーマを変更します"
|
||||
},
|
||||
"language": {
|
||||
"header": "言語の変更",
|
||||
"description": "言語を変更します"
|
||||
},
|
||||
"logs": {
|
||||
"header": "エラーの履歴",
|
||||
"description": "すべてのエラーログを表示します"
|
||||
},
|
||||
"credits": {
|
||||
"module": "モジュールの開発者",
|
||||
"original": "オリジナルの開発者",
|
||||
"web": "WebUI の開発者"
|
||||
},
|
||||
"license": {
|
||||
"module": "モジュールのライセンス",
|
||||
"web": "WebUI のライセンス"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -121,7 +121,11 @@ void companion_entry(int fd) {
|
||||
ASSURE_SIZE_WRITE("ZygiskdCompanion", "module_entry", ret, sizeof(uint8_t));
|
||||
}
|
||||
|
||||
struct sigaction sa = { .sa_handler = SIG_IGN };
|
||||
struct sigaction sa;
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_handler = SIG_IGN;
|
||||
sigaction(SIGPIPE, &sa, NULL);
|
||||
|
||||
while (1) {
|
||||
|
||||
@@ -62,7 +62,6 @@ void apatch_get_existence(struct root_impl_state *state) {
|
||||
}
|
||||
|
||||
struct package_config {
|
||||
char *process;
|
||||
uid_t uid;
|
||||
bool root_granted;
|
||||
bool umount_needed;
|
||||
@@ -105,7 +104,7 @@ bool _apatch_get_package_config(struct packages_config *restrict config) {
|
||||
return false;
|
||||
}
|
||||
|
||||
config->configs[config->size].process = strdup(strtok(line, ","));
|
||||
strtok(line, ",");
|
||||
|
||||
char *exclude_str = strtok(NULL, ",");
|
||||
if (exclude_str == NULL) continue;
|
||||
@@ -129,10 +128,6 @@ bool _apatch_get_package_config(struct packages_config *restrict config) {
|
||||
}
|
||||
|
||||
void _apatch_free_package_config(struct packages_config *restrict config) {
|
||||
for (size_t i = 0; i < config->size; i++) {
|
||||
free(config->configs[i].process);
|
||||
}
|
||||
|
||||
free(config->configs);
|
||||
}
|
||||
|
||||
@@ -160,7 +155,7 @@ bool apatch_uid_granted_root(uid_t uid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool apatch_uid_should_umount(uid_t uid, const char *const process) {
|
||||
bool apatch_uid_should_umount(uid_t uid) {
|
||||
struct packages_config config;
|
||||
if (!_apatch_get_package_config(&config)) {
|
||||
_apatch_free_package_config(&config);
|
||||
@@ -179,29 +174,6 @@ bool apatch_uid_should_umount(uid_t uid, const char *const process) {
|
||||
return umount_needed;
|
||||
}
|
||||
|
||||
/* INFO: Isolated services have different UIDs than the main app, and
|
||||
while libzygisk.so has code to send the UID of the app related
|
||||
to the isolated service, we add this so that in case it fails,
|
||||
this should avoid it pass through as Mounted.
|
||||
*/
|
||||
if (IS_ISOLATED_SERVICE(uid)) {
|
||||
size_t targeted_process_length = strlen(process);
|
||||
|
||||
for (size_t i = 0; i < config.size; i++) {
|
||||
size_t config_process_length = strlen(config.configs[i].process);
|
||||
size_t smallest_process_length = targeted_process_length < config_process_length ? targeted_process_length : config_process_length;
|
||||
|
||||
if (strncmp(config.configs[i].process, process, smallest_process_length) != 0) continue;
|
||||
|
||||
/* INFO: This allow us to copy the information to avoid use-after-free */
|
||||
bool umount_needed = config.configs[i].umount_needed;
|
||||
|
||||
_apatch_free_package_config(&config);
|
||||
|
||||
return umount_needed;
|
||||
}
|
||||
}
|
||||
|
||||
_apatch_free_package_config(&config);
|
||||
|
||||
return false;
|
||||
|
||||
@@ -7,7 +7,7 @@ void apatch_get_existence(struct root_impl_state *state);
|
||||
|
||||
bool apatch_uid_granted_root(uid_t uid);
|
||||
|
||||
bool apatch_uid_should_umount(uid_t uid, const char *const process);
|
||||
bool apatch_uid_should_umount(uid_t uid);
|
||||
|
||||
bool apatch_uid_is_manager(uid_t uid);
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@ void root_impls_setup(void) {
|
||||
impl.impl = Multiple;
|
||||
} else if (state_ksu.state == Supported) {
|
||||
impl.impl = KernelSU;
|
||||
impl.variant = state_ksu.variant;
|
||||
} else if (state_apatch.state == Supported) {
|
||||
impl.impl = APatch;
|
||||
} else if (state_magisk.state == Supported) {
|
||||
@@ -101,7 +100,7 @@ bool uid_should_umount(uid_t uid, const char *const process) {
|
||||
return ksu_uid_should_umount(uid);
|
||||
}
|
||||
case APatch: {
|
||||
return apatch_uid_should_umount(uid, process);
|
||||
return apatch_uid_should_umount(uid);
|
||||
}
|
||||
case Magisk: {
|
||||
return magisk_uid_should_umount(process);
|
||||
|
||||
@@ -19,12 +19,6 @@
|
||||
#define CMD_GET_VERSION 2
|
||||
#define CMD_UID_GRANTED_ROOT 12
|
||||
#define CMD_UID_SHOULD_UMOUNT 13
|
||||
#define CMD_GET_MANAGER_UID 16
|
||||
#define CMD_HOOK_MODE 0xC0DEAD1A
|
||||
|
||||
static enum kernelsu_variants variant = KOfficial;
|
||||
|
||||
static bool supports_manager_uid_retrieval = false;
|
||||
|
||||
void ksu_get_existence(struct root_impl_state *state) {
|
||||
int version = 0;
|
||||
@@ -48,26 +42,6 @@ void ksu_get_existence(struct root_impl_state *state) {
|
||||
}
|
||||
|
||||
state->state = Supported;
|
||||
|
||||
char mode[16] = { 0 };
|
||||
prctl((signed int)KERNEL_SU_OPTION, CMD_HOOK_MODE, mode, 0, 0);
|
||||
|
||||
if (mode[0] != '\0') state->variant = KNext;
|
||||
else state->variant = KOfficial;
|
||||
|
||||
variant = state->variant;
|
||||
|
||||
/* INFO: CMD_GET_MANAGER_UID is a KernelSU Next feature, however we won't
|
||||
limit to KernelSU Next only in case other forks wish to implement
|
||||
it. */
|
||||
int reply_ok = 0;
|
||||
prctl((signed int)KERNEL_SU_OPTION, CMD_GET_MANAGER_UID, 0, 0, &reply_ok);
|
||||
|
||||
if (reply_ok == KERNEL_SU_OPTION) {
|
||||
LOGI("KernelSU implementation supports CMD_GET_MANAGER_UID.\n");
|
||||
|
||||
supports_manager_uid_retrieval = true;
|
||||
}
|
||||
}
|
||||
else if (version >= 1 && version <= MIN_KSU_VERSION - 1) state->state = TooOld;
|
||||
else state->state = Abnormal;
|
||||
@@ -94,24 +68,8 @@ bool ksu_uid_should_umount(uid_t uid) {
|
||||
}
|
||||
|
||||
bool ksu_uid_is_manager(uid_t uid) {
|
||||
/* INFO: If the manager UID is set, we can use it to check if the UID
|
||||
is the manager UID, which is more reliable than checking
|
||||
the KSU manager data directory, as spoofed builds of
|
||||
KernelSU Next have different package names.
|
||||
*/
|
||||
if (supports_manager_uid_retrieval) {
|
||||
uid_t manager_uid = 0;
|
||||
prctl(KERNEL_SU_OPTION, CMD_GET_MANAGER_UID, &manager_uid, NULL, NULL);
|
||||
|
||||
return uid == manager_uid;
|
||||
}
|
||||
|
||||
const char *manager_path = NULL;
|
||||
if (variant == KOfficial) manager_path = "/data/user_de/0/me.weishu.kernelsu";
|
||||
else if (variant == KNext) manager_path = "/data/user_de/0/com.rifsxd.ksunext";
|
||||
|
||||
struct stat s;
|
||||
if (stat(manager_path, &s) == -1) {
|
||||
if (stat("/data/user_de/0/me.weishu.kernelsu", &s) == -1) {
|
||||
if (errno != ENOENT) {
|
||||
LOGE("Failed to stat KSU manager data directory: %s\n", strerror(errno));
|
||||
}
|
||||
|
||||
@@ -3,11 +3,6 @@
|
||||
|
||||
#include "../constants.h"
|
||||
|
||||
enum kernelsu_variants {
|
||||
KOfficial,
|
||||
KNext
|
||||
};
|
||||
|
||||
void ksu_get_existence(struct root_impl_state *state);
|
||||
|
||||
bool ksu_uid_granted_root(uid_t uid);
|
||||
|
||||
@@ -28,7 +28,7 @@ char *magisk_managers[] = {
|
||||
#define DEBUG_RAMDISK_MAGISK lp_select("/debug_ramdisk/magisk32", "/debug_ramdisk/magisk64")
|
||||
#define BITLESS_DEBUG_RAMDISK_MAGISK "/debug_ramdisk/magisk"
|
||||
|
||||
static enum magisk_variants variant = MOfficial;
|
||||
enum magisk_variants variant = Official;
|
||||
/* INFO: Longest path */
|
||||
static char path_to_magisk[sizeof(DEBUG_RAMDISK_MAGISK)] = { 0 };
|
||||
bool is_using_sulist = false;
|
||||
@@ -74,7 +74,7 @@ void magisk_get_existence(struct root_impl_state *state) {
|
||||
return;
|
||||
}
|
||||
|
||||
state->variant = (uint8_t)MOfficial;
|
||||
state->variant = (uint8_t)Official;
|
||||
|
||||
for (unsigned long i = 0; i < sizeof(supported_variants) / sizeof(supported_variants[0]); i++) {
|
||||
if (strstr(magisk_info, supported_variants[i])) {
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
#include "../constants.h"
|
||||
|
||||
enum magisk_variants {
|
||||
MOfficial,
|
||||
MKitsune
|
||||
Official,
|
||||
Kitsune
|
||||
};
|
||||
|
||||
void magisk_get_existence(struct root_impl_state *state);
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
|
||||
#include "utils.h"
|
||||
#include "root_impl/common.h"
|
||||
#include "root_impl/kernelsu.h"
|
||||
#include "root_impl/magisk.h"
|
||||
|
||||
int clean_namespace_fd = 0;
|
||||
@@ -437,8 +436,7 @@ void stringify_root_impl_name(struct root_impl impl, char *restrict output) {
|
||||
break;
|
||||
}
|
||||
case KernelSU: {
|
||||
if (impl.variant == KOfficial) strcpy(output, "KernelSU");
|
||||
else strcpy(output, "KernelSU Next");
|
||||
strcpy(output, "KernelSU");
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -448,8 +446,11 @@ void stringify_root_impl_name(struct root_impl impl, char *restrict output) {
|
||||
break;
|
||||
}
|
||||
case Magisk: {
|
||||
if (impl.variant == MOfficial) strcpy(output, "Magisk Official");
|
||||
else strcpy(output, "Magisk Kitsune");
|
||||
if (impl.variant == 0) {
|
||||
strcpy(output, "Magisk Official");
|
||||
} else {
|
||||
strcpy(output, "Magisk Kitsune");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -602,57 +603,115 @@ bool umount_root(struct root_impl impl) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* INFO: "Magisk" is the longest word that will ever be put in source_name */
|
||||
char source_name[sizeof("magisk")];
|
||||
if (impl.impl == KernelSU) strcpy(source_name, "KSU");
|
||||
else if (impl.impl == APatch) strcpy(source_name, "APatch");
|
||||
else strcpy(source_name, "magisk");
|
||||
switch (impl.impl) {
|
||||
case None: { break; }
|
||||
case Multiple: { break; }
|
||||
|
||||
LOGI("[%s] Unmounting root", source_name);
|
||||
case KernelSU:
|
||||
case APatch: {
|
||||
char source_name[LONGEST_ROOT_IMPL_NAME];
|
||||
if (impl.impl == KernelSU) strcpy(source_name, "KSU");
|
||||
else strcpy(source_name, "APatch");
|
||||
|
||||
const char **targets_to_unmount = NULL;
|
||||
size_t num_targets = 0;
|
||||
LOGI("[%s] Unmounting root", source_name);
|
||||
|
||||
for (size_t i = 0; i < mounts.length; i++) {
|
||||
struct mountinfo mount = mounts.mounts[i];
|
||||
const char **targets_to_unmount = NULL;
|
||||
size_t num_targets = 0;
|
||||
|
||||
bool should_unmount = false;
|
||||
/* INFO: The root implementations have their own /system mounts, so we
|
||||
only skip the mount if they are from a module, not Magisk itself.
|
||||
*/
|
||||
if (strncmp(mount.target, "/system/", strlen("/system/")) == 0 &&
|
||||
strncmp(mount.root, "/adb/modules/", strlen("/adb/modules/")) == 0 &&
|
||||
strncmp(mount.target, "/system/etc/", strlen("/system/etc/")) != 0) continue;
|
||||
for (size_t i = 0; i < mounts.length; i++) {
|
||||
struct mountinfo mount = mounts.mounts[i];
|
||||
|
||||
if (strcmp(mount.source, source_name) == 0) should_unmount = true;
|
||||
if (strncmp(mount.target, "/data/adb/modules", strlen("/data/adb/modules")) == 0) should_unmount = true;
|
||||
if (strncmp(mount.root, "/adb/modules/", strlen("/adb/modules/")) == 0) should_unmount = true;
|
||||
bool should_unmount = false;
|
||||
|
||||
if (!should_unmount) continue;
|
||||
/* INFO: KernelSU has its own /system mounts, so we only skip the mount
|
||||
if they are from a module, not KSU itself.
|
||||
*/
|
||||
if (strncmp(mount.target, "/system/", strlen("/system/")) == 0 &&
|
||||
strncmp(mount.root, "/adb/modules", strlen("/adb/modules")) == 0) continue;
|
||||
|
||||
num_targets++;
|
||||
targets_to_unmount = realloc(targets_to_unmount, num_targets * sizeof(char*));
|
||||
if (targets_to_unmount == NULL) {
|
||||
LOGE("[%s] Failed to allocate memory for targets_to_unmount\n", source_name);
|
||||
if (strcmp(mount.source, source_name) == 0) should_unmount = true;
|
||||
if (strncmp(mount.root, "/adb/modules", strlen("/adb/modules")) == 0) should_unmount = true;
|
||||
if (strncmp(mount.target, "/data/adb/modules", strlen("/data/adb/modules")) == 0) should_unmount = true;
|
||||
|
||||
if (!should_unmount) continue;
|
||||
|
||||
num_targets++;
|
||||
targets_to_unmount = realloc(targets_to_unmount, num_targets * sizeof(char*));
|
||||
if (targets_to_unmount == NULL) {
|
||||
LOGE("[%s] Failed to allocate memory for targets_to_unmount\n", source_name);
|
||||
|
||||
free(targets_to_unmount);
|
||||
free_mounts(&mounts);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
targets_to_unmount[num_targets - 1] = mount.target;
|
||||
}
|
||||
|
||||
for (size_t i = num_targets; i > 0; i--) {
|
||||
const char *target = targets_to_unmount[i - 1];
|
||||
|
||||
if (umount2(target, MNT_DETACH) == -1) {
|
||||
LOGE("[%s] Failed to unmount %s: %s\n", source_name, target, strerror(errno));
|
||||
} else {
|
||||
LOGI("[%s] Unmounted %s\n", source_name, target);
|
||||
}
|
||||
}
|
||||
free(targets_to_unmount);
|
||||
free_mounts(&mounts);
|
||||
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case Magisk: {
|
||||
LOGI("[Magisk] Unmounting root");
|
||||
|
||||
targets_to_unmount[num_targets - 1] = mount.target;
|
||||
}
|
||||
const char **targets_to_unmount = NULL;
|
||||
size_t num_targets = 0;
|
||||
|
||||
for (size_t i = num_targets; i > 0; i--) {
|
||||
const char *target = targets_to_unmount[i - 1];
|
||||
if (umount2(target, MNT_DETACH) == -1) {
|
||||
LOGE("[%s] Failed to unmount %s: %s\n", source_name, target, strerror(errno));
|
||||
} else {
|
||||
LOGI("[%s] Unmounted %s\n", source_name, target);
|
||||
for (size_t i = 0; i < mounts.length; i++) {
|
||||
struct mountinfo mount = mounts.mounts[i];
|
||||
|
||||
bool should_unmount = false;
|
||||
/* INFO: Magisk has its own /system mounts, so we only skip the mount
|
||||
if they are from a module, not Magisk itself.
|
||||
*/
|
||||
if (strncmp(mount.target, "/system/", strlen("/system/")) == 0 &&
|
||||
strncmp(mount.root, "/adb/modules", strlen("/adb/modules")) == 0) continue;
|
||||
|
||||
if (strcmp(mount.source, "magisk") == 0) should_unmount = true;
|
||||
if (strncmp(mount.target, "/debug_ramdisk", strlen("/debug_ramdisk")) == 0) should_unmount = true;
|
||||
if (strncmp(mount.target, "/data/adb/modules", strlen("/data/adb/modules")) == 0) should_unmount = true;
|
||||
if (strncmp(mount.root, "/adb/modules", strlen("/adb/modules")) == 0) should_unmount = true;
|
||||
|
||||
if (!should_unmount) continue;
|
||||
|
||||
num_targets++;
|
||||
targets_to_unmount = realloc(targets_to_unmount, num_targets * sizeof(char*));
|
||||
if (targets_to_unmount == NULL) {
|
||||
LOGE("[Magisk] Failed to allocate memory for targets_to_unmount\n");
|
||||
|
||||
free(targets_to_unmount);
|
||||
free_mounts(&mounts);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
targets_to_unmount[num_targets - 1] = mount.target;
|
||||
}
|
||||
|
||||
for (size_t i = num_targets; i > 0; i--) {
|
||||
const char *target = targets_to_unmount[i - 1];
|
||||
if (umount2(target, MNT_DETACH) == -1) {
|
||||
LOGE("[Magisk] Failed to unmount %s: %s\n", target, strerror(errno));
|
||||
} else {
|
||||
LOGI("[Magisk] Unmounted %s\n", target);
|
||||
}
|
||||
}
|
||||
free(targets_to_unmount);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(targets_to_unmount);
|
||||
|
||||
free_mounts(&mounts);
|
||||
|
||||
@@ -785,7 +844,7 @@ int save_mns_fd(int pid, enum MountNamespaceState mns_state, struct root_impl im
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (impl.impl == Magisk && impl.variant == MKitsune && mns_state == Clean) {
|
||||
if (impl.impl == Magisk && impl.variant == Kitsune && mns_state == Clean) {
|
||||
LOGI("[Magisk] Magisk Kitsune detected, will skip cache first.");
|
||||
|
||||
/* INFO: MagiskSU of Kitsune has a special behavior: It is only mounted
|
||||
|
||||
@@ -65,9 +65,6 @@
|
||||
return -1; \
|
||||
}
|
||||
|
||||
#define IS_ISOLATED_SERVICE(uid) \
|
||||
((uid) >= 90000 && (uid) < 1000000)
|
||||
|
||||
#define write_func_def(type) \
|
||||
ssize_t write_## type(int fd, type val)
|
||||
|
||||
|
||||
@@ -44,18 +44,15 @@ enum Architecture {
|
||||
#define TMP_PATH "/data/adb/rezygisk"
|
||||
#define CONTROLLER_SOCKET TMP_PATH "/init_monitor"
|
||||
#define PATH_CP_NAME TMP_PATH "/" lp_select("cp32.sock", "cp64.sock")
|
||||
#define ZYGISKD_FILE PATH_MODULES_DIR "/rezygisk/bin/zygiskd" lp_select("32", "64")
|
||||
#define ZYGISKD_PATH "/data/adb/modules/rezygisk/bin/zygiskd" lp_select("32", "64")
|
||||
#define ZYGISKD_FILE PATH_MODULES_DIR "/zygisksu/bin/zygiskd" lp_select("32", "64")
|
||||
#define ZYGISKD_PATH "/data/adb/modules/zygisksu/bin/zygiskd" lp_select("32", "64")
|
||||
|
||||
static enum Architecture get_arch(void) {
|
||||
char system_arch[64];
|
||||
char system_arch[32];
|
||||
get_property("ro.product.cpu.abilist", system_arch);
|
||||
|
||||
/* INFO: "PC" architectures should have priority because in an emulator
|
||||
the native architecture should have priority over the emulated
|
||||
architecture for "native" reasons. */
|
||||
if (strstr(system_arch, "x86") != NULL) return lp_select(X86, X86_64);
|
||||
if (strstr(system_arch, "arm") != NULL) return lp_select(ARM32, ARM64);
|
||||
if (strstr(system_arch, "x86") != NULL) return lp_select(X86, X86_64);
|
||||
|
||||
LOGE("Unsupported system architecture: %s\n", system_arch);
|
||||
exit(1);
|
||||
@@ -86,7 +83,7 @@ static void load_modules(enum Architecture arch, struct Context *restrict contex
|
||||
struct dirent *entry;
|
||||
while ((entry = readdir(dir)) != NULL) {
|
||||
if (entry->d_type != DT_DIR) continue; /* INFO: Only directories */
|
||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0 || strcmp(entry->d_name, "rezygisk") == 0) continue;
|
||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0 || strcmp(entry->d_name, "zygisksu") == 0) continue;
|
||||
|
||||
char *name = entry->d_name;
|
||||
char so_path[PATH_MAX];
|
||||
@@ -133,8 +130,6 @@ static void load_modules(enum Architecture arch, struct Context *restrict contex
|
||||
context->modules[context->len].companion = -1;
|
||||
context->len++;
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
static void free_modules(struct Context *restrict context) {
|
||||
@@ -360,9 +355,6 @@ void zygiskd_start(char *restrict argv[]) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct sigaction sa = { .sa_handler = SIG_IGN };
|
||||
sigaction(SIGPIPE, &sa, NULL);
|
||||
|
||||
bool first_process = true;
|
||||
while (1) {
|
||||
int client_fd = accept(socket_fd, NULL, NULL);
|
||||
|
||||
Reference in New Issue
Block a user