176 Commits

Author SHA1 Message Date
ThePedroo
d37d651d8c improve: immediatly set monitor status after set in WebUI
This commit improves the "Actions" tab by immediatly changing visually the monitor status in the WebUI once modified.
2025-05-18 13:06:14 -03:00
ThePedroo
6d7eda4ea6 fix: extracting sha256 sum of webroot files
This commit fixes the issue where "webroot" files would have its sha256 hash extracted to the installation directory by using unzip "-x" flag to exclude ".sha256" files with that.
2025-05-18 12:44:51 -03:00
Pedro.js
5b2065768c Merge branch 'main' into add/new-webui
Signed-off-by: Pedro.js <pedroolimpioguerra@gmail.com>
2025-05-18 12:25:46 -03:00
ThePedroo
d2a4110c9d fix: improper handling of unknown/exited zygote status in WebUI
This commit fixes the issue where the daemon info would not be found, causing a crash in WebUI due to accessing properties of "undefined" object.
2025-05-18 12:21:32 -03:00
ThePedroo
5c74037853 fix: WebUI translations file names and line ending
This commit fixes the file names of some translations of WebUI strings and the missing new space in their end.
2025-05-18 11:56:46 -03:00
Lucky Kiddos
18d552f59f update: WebUI id_ID translations (#160)
This commit updates WebUI Indonesian translation to improve clarity.

Signed-off-by: Lucky Kiddos <95188840+GuitarHeroStyles@users.noreply.github.com>
2025-05-13 15:59:13 -03:00
Lxchoooo
70cea41017 add: es_ES and es_MX translations to the WebUI (#157)
This commit adds both Spanish and Mexico Spanish translations to the ReZygisk WebUI.
2025-05-04 19:29:04 -03:00
ThePedroo
61d0e609c2 add: es_AR translations to the WebUI; fix: fr_FR file extension
This commit adds the Argentina Spanish translations to ReZygisk WebUI and fixes French translations file not having ".json".

Co-authored-by: Flopster101 <nahuelgomez329@gmail.com>
2025-05-04 18:33:35 -03:00
GhostFRR
90aec6f83c add: fr_FR.json translations to WebUI (#156)
This commit adds French translations to ReZygisk WebUI.

Signed-off-by: GhostFRR <ghost.game.fr@gmail.com>
2025-05-04 18:13:43 -03:00
thasave14
a566ced0c2 add: it_IT translations for the WebUI (#154)
This commit adds Italian translations for ReZygisk WebUI.

Signed-off-by: thasave14 <93542339+thasave14@users.noreply.github.com>
2025-05-03 22:33:11 -03:00
ThePedroo
b0dfcbe357 improve: webroot extraction
This commit improves the "webroot" folder extraction in "customize.sh" by simplifying into a single unzip command.
2025-05-03 06:46:25 -03:00
ThePedroo
3b07fb1d66 fix: WebUI loaded modules list parsing
This commit fixes the code that parses the loaded modules from ReZygisk "module.prop", which previously would only load the first module as it used "info[1]".
2025-05-03 06:45:07 -03:00
ZGX089ッ
1b2f9f23e9 fix: some translation in ar_EG.json (#153)
Signed-off-by: ZGX089ッ <159061718+ZG089@users.noreply.github.com>
2025-05-03 16:39:30 +07:00
ThePedroo
a3f68a5c06 update: translations; add: new translations; remove: incomplete translations
This commit updates and adds new translations based on contributions on Crowdin. If you are the contributor of any of the added ones, or participated in the updates of any, please, submit a PR adding your proper credit as the "README.md" suggests. Also removes translations that are incomplete at the moment of this commit. The credits for those will not be removed.
2025-05-03 01:08:46 -03:00
Alice w/🌧️
2ea61563cd add: ar_EG to extractor
Signed-off-by: Alice w/🌧️ <rainyxeon@gmail.com>
2025-04-30 21:46:40 +07:00
RainyXeon
1f88a8f30e add: temporary fix for translation as some code in home translate broken 2025-04-30 19:23:36 +07:00
RainyXeon
d92d854a3b add: experiment RTL layout feature 2025-04-30 19:17:04 +07:00
ZGX089ッ
cf9e03ac5c add: Arabic Translation (#150)
* feat: Added Arabic Translation

Signed-off-by: ZGX089ッ <159061718+ZG089@users.noreply.github.com>

* Update TRANSLATOR.md

Signed-off-by: ZGX089ッ <159061718+ZG089@users.noreply.github.com>

---------

Signed-off-by: ZGX089ッ <159061718+ZG089@users.noreply.github.com>
2025-04-30 19:12:57 +07:00
ThePedroo
0b9a2c26b8 fix: WebUI ReZygisk info retrieval
This commit fixes how the WebUI retrieves ReZygisk information, such as if it is working, which modules are loaded, etc.
2025-04-29 13:33:36 -03:00
RainyXeon
f58dacea0b fix: debug log 2025-04-29 18:14:00 +07:00
RainyXeon
c14d3ff36e add: debug log for chrome dev tools (don't remove) 2025-04-29 17:34:44 +07:00
Alice w/🌧️
64f002541e fix: misconfiguration on section header
Signed-off-by: Alice w/🌧️ <rainyxeon@gmail.com>
2025-04-23 23:04:10 +07:00
Alice w/🌧️
a3d07583d3 improve: spacing on Rezygisk section header
Signed-off-by: Alice w/🌧️ <rainyxeon@gmail.com>
2025-04-23 23:02:40 +07:00
RainyXeon
17f430b354 improve: some small space on section header 2025-04-23 21:06:51 +07:00
ThePedroo
caa4b6b640 improve: reduce size of section headers
This commit reduce the size of section headers to make it more appropriate.
2025-04-23 03:08:49 -03:00
ThePedroo
5120d0067c remove: webroot data from machikado creation
This commit removes "webroot" files from being used for "machikado" file creation, as it doesn't affect core functionality. For safety a new approach will be created later.
2025-04-23 02:29:54 -03:00
ThePedroo
d8c0310053 improve: use module name, not module id; add: show Android/Kernel version in WebUI
This commit improves the WebUI module listing by listing the module name rather than the module id, and also adds 2 fields in the WebUI, so that it shows the Android version and Kernel release string.
2025-04-23 02:27:10 -03:00
ThePedroo
128104a590 fix: merge conflicts
This commit fixes merge conflicts while merging to main.
2025-04-23 00:22:33 -03:00
GhostFRR
6ce2fe440b add: @GhostFRR to TRANSLATOR.md (#134)
This commit adds "@GhostFRR" to the "TRANSLATOR.MD" credits for translating the WebUI strings to French.

Signed-off-by: GhostFRR <ghost.game.fr@gmail.com>
2025-04-17 14:09:23 -03:00
Kitty
c465754be7 add: ukrainian translations to WebUI (#100)
This commit adds Ukrainian translations for the WebUI available languages.

Signed-off-by: Kitty <73357005+Kittyskj@users.noreply.github.com>
Co-authored-by: Pedro.js <pedroolimpioguerra@gmail.com>
2025-04-12 20:57:18 -03:00
Lucky Kiddos
88eb16331e update: id_ID translations (#107)
This commit updates the translations for Indonesia language with proper grammar.

Signed-off-by: Lucky Kiddos <95188840+GuitarHeroStyles@users.noreply.github.com>
2025-01-11 01:13:22 -03:00
Kirill Kuznetsov
5a061e6daa fix: ru_RU language name translation (#86)
This commit fixes russian language name translation, which previously said, in russian, "English (USA)".

Signed-off-by: Kirill Kuznetsov <kdevlab@yandex.ru>
2024-11-24 15:24:49 -03:00
Willow Hayley Lovelace
27b3de562f add: Turkish language for WebUI (#85)
Co-authored-by: witch <witch@dyingwillow.dev>
2024-11-23 14:47:23 +07:00
Berlian Panca
56d307783f add: indonesian language for WebUI (#83)
This commit will add support for indonesian language in webui, following commits:

* Add Indonesian language for WebUI

* Sort TRANSLATOR.md contributor alphabetically
2024-11-15 15:18:20 +07:00
unexpected unresolved
38f3f4ec63 fix: wrong file name (installer)
Signed-off-by: unexpected unresolved <xeondev@xeondex.onmicrosoft.com>
2024-11-13 22:45:10 +07:00
unexpected unresolved
05f673bce1 fix: wrong file name (build)
Signed-off-by: unexpected unresolved <xeondev@xeondex.onmicrosoft.com>
2024-11-13 22:44:00 +07:00
RainyXeon
43b3bfbc99 fix: language cannot translated fully 2024-11-13 18:44:05 +07:00
SheepChef
ef7e6c07e4 update: translations for zh_CN (#79)
This commit updates the translations for Simplified Chinese so that it is fully translated.

Signed-off-by: SheepChef <50871867+SheepChef@users.noreply.github.com>
2024-11-13 07:01:03 -03:00
unexpected unresolved
84a139fcaf add: new translation for vi_VN
Signed-off-by: unexpected unresolved <xeondev@xeondex.onmicrosoft.com>
2024-11-13 06:36:44 +07:00
ThePedroo
ea42fbea41 fix: monitor information
This commit fixes monitor information, which now is properly working and named, and also has proper status words.
2024-11-12 20:25:57 -03:00
ThePedroo
e55a825f7d fix: 64-bit/32-bit-only device detection
This commit fixes the detection made by ReZygisk WebUI that makes it be aware of whether the device's CPU is capable of 64-bit or 32-bit only, allowing it to properly mark as Fully functioning or just partially.
2024-11-12 17:39:57 -03:00
SheepChef
dddda78496 update: zh_CN translations (#78)
This commit updates the Simplified Chinese translations for the WebUI.

Signed-off-by: SheepChef <50871867+SheepChef@users.noreply.github.com>
2024-11-12 14:48:00 -03:00
RainyXeon
664aed058a fix: translation not completely for webui 2024-11-12 20:04:16 +07:00
RainyXeon
8b611b4153 add: some small padding for header 2024-11-12 19:40:23 +07:00
RainyXeon
b805d86f47 fix: go back icon not change the color 2024-11-12 18:43:05 +07:00
ThePedroo
d82bd17003 fix: re-declaring constant variable
This commit fixes the issue where two variables with the same name would overlap, causing a re-declaration of a constant (imutable) variable
2024-11-12 04:22:54 -03:00
unexpected unresolved
847c8c1544 remove: light icon data for errorh page
Signed-off-by: unexpected unresolved <minh15052008@gmail.com>
2024-11-12 14:29:02 +07:00
unexpected unresolved
5d8db1b602 remove: button icon in light theme
Signed-off-by: unexpected unresolved <minh15052008@gmail.com>
2024-11-12 14:28:11 +07:00
RainyXeon
44ba054f96 fix: error history header 2024-11-12 14:16:41 +07:00
RainyXeon
98743e8523 add: new ui for error history page
remove: modal support (initial)
2024-11-12 14:12:53 +07:00
ThePedroo
949a526cf2 fix: Web UI not loading
This commit fixes the issue where the Web UI doesn't load by properly implementing the saving of the status of ReZygisk so that it can be displayed easily, which wasn't properly implemented before.
2024-11-12 02:33:33 -03:00
ThePedroo
73295ab4b5 update: ReZygisk's Web UI license
This commit updates the Web UI of ReZygisk to a license with copyleft, making it harder to be used in proprietary projects.
2024-11-12 00:18:07 -03:00
RainyXeon
a0d79875ea add: new cache state storing and handling 2024-11-12 00:17:38 -03:00
ThePedroo
73acecaa9d improve: translations detection
This commit allows ReZygisk WebUI to dynamically fetch translations.
2024-11-12 00:17:37 -03:00
Blazzycrafter
f4968599cf add: de_DE translations (#62)
This commit adds German translations for ReZygisk WebUI.

Signed-off-by: Blazzycrafter <39300111+Blazzycrafter@users.noreply.github.com>
2024-11-12 00:17:37 -03:00
Igor
8f6a3ae8e8 update: ro_RO translations (#57)
This commit updates Romanian translations to translate untranslated phrases and fix some grammatically incorrect phrases.

Signed-off-by: Igor <sorocean.igor@gmail.com>
2024-11-12 00:17:36 -03:00
Blazzycrafter
0c44c5c281 add: de_DE translation credits (#52)
This commit adds the credit for Blazzycrafter, the contributor whom added German translations for ReZygisk WebUI.

Signed-off-by: Blazzycrafter <39300111+Blazzycrafter@users.noreply.github.com>
2024-11-12 00:17:36 -03:00
RainyXeon
cd96363249 remove: test code 2024-11-12 00:17:35 -03:00
RainyXeon
3f816b609a add: amoled and monochrome theme
This commit will add 2 new themes is monochrome and amoled
2024-11-12 00:17:35 -03:00
ThePedroo
ae2664d7e4 fix: zygisk-ptraceXX response parsing
This commit fixes the parsing of "ptrace" command.
2024-11-12 00:17:34 -03:00
RainyXeon
c833a5b69c fix: build failed for webui 2024-11-12 00:17:34 -03:00
RainyXeon
f38e78bad7 add: outfit font to replace product sans 2024-11-12 00:17:34 -03:00
unexpected unresolved
b59b4f4a72 improve: tablet navbar by decrease scale 2024-11-12 00:16:55 -03:00
RainyXeon
fbed1e5633 add: initial support for tablet/desktop mode
This commit will add initial support for tablet/desktop mode by trick the navbar a bit
2024-11-12 00:16:55 -03:00
RainyXeon
6a0f5aaad2 add: AJleKcAHgP68's russian translation credits
This commit will add AJleKcAHgP68's russian translation credits to TRANSLATION.md and webroot/js/language.js

Co-authored-by: AJleKcAHgP68 <78802768+AJleKcAHgP68@users.noreply.github.com>
2024-11-12 00:16:54 -03:00
AJleKcAHgP68
3fde061c18 improve: russian translation on ru_RU.json (#44)
Add RU translate

Signed-off-by: AJleKcAHgP68 <78802768+AJleKcAHgP68@users.noreply.github.com>
2024-11-12 00:16:54 -03:00
unexpected unresolved
d2ca72e04a add: credits for SheepChef on TRANSLATOR.md
Signed-off-by: unexpected unresolved <minh15052008@gmail.com>
2024-11-12 00:16:53 -03:00
unexpected unresolved
b26b988f08 fix: translation credits synchronization
Signed-off-by: unexpected unresolved <minh15052008@gmail.com>
2024-11-12 00:16:53 -03:00
SheepChef
657512ca2c fix: lines variable not declared; improve: style of web UI (#43)
This commit fixes an issue where "lines" variable would not be declared and improves the style of the web UI.

Signed-off-by: SheepChef <50871867+SheepChef@users.noreply.github.com>
Co-authored-by: Pedro.js <pedroolimpioguerra@gmail.com>
2024-11-12 00:16:52 -03:00
SheepChef
19cedefcf3 improve: chinese translation. (#42)
* Full Chinese Translation.

Translate all currently existing English strings to Chinese.

Signed-off-by: SheepChef <50871867+SheepChef@users.noreply.github.com>

* Update language.js

---------

Signed-off-by: SheepChef <50871867+SheepChef@users.noreply.github.com>
2024-11-12 00:16:52 -03:00
ThePedroo
f85baf92ab fix: pt_BR translation grammar
This commit fixes grammar mistakes in brazilian portuguese translation.
2024-11-12 00:16:51 -03:00
ThePedroo
7b26d07454 improve: Web UI loading speed
This commit improves the speed of loading of the Web UI.
2024-11-12 00:16:48 -03:00
Kirill Kuznetsov
67a7475946 fix #36: WebUI not working on 64 bit only devices 2024-11-12 00:12:04 -03:00
Pedro.js
40c54bd787 fix: untranslated string in Brazilian portuguese
This commit fixes the missing translations for Brazilian portuguese.

Signed-off-by: Pedro.js <pedroolimpioguerra@gmail.com>
2024-11-12 00:12:03 -03:00
ThePedroo
64f4768bcd remove: duplicated logs
This commit removes duplication of logs in ptrace binaries.
2024-11-12 00:12:00 -03:00
ThePedroo
daddc980ec fix: error upon loading Web UI
This commit fixes issues that caused the Web UI to not load.
2024-11-12 00:09:27 -03:00
unexpected unresolved
c9ed52fecb fix: light theme navbar
Signed-off-by: unexpected unresolved <minh15052008@gmail.com>
2024-11-12 00:09:27 -03:00
unexpected unresolved
34dfa8928e remove: useless fix for navbar
Signed-off-by: unexpected unresolved <minh15052008@gmail.com>
2024-11-12 00:09:26 -03:00
unexpected unresolved
f60a049333 fix: light icon for navbar in system based theme (not confirmed)
Signed-off-by: unexpected unresolved <minh15052008@gmail.com>
2024-11-12 00:09:26 -03:00
Pedro.js
9e2d40c164 update: Brazilian portuguese translations
This commit updates the translations of Brazilian portuguese of WebUI.

Signed-off-by: Pedro.js <pedroolimpioguerra@gmail.com>
2024-11-12 00:09:25 -03:00
RainyXeon
3fd70f6416 remove: unused string 2024-11-12 00:09:25 -03:00
RainyXeon
5978dc2e26 improve: no module avaliable div 2024-11-12 00:09:25 -03:00
RainyXeon
cc4fe44c95 fix: webui error when no zygigk module installed 2024-11-12 00:09:24 -03:00
unexpected unresolved
a8be51cba8 remove: flag from pt_BR translation 2024-11-12 00:09:23 -03:00
RainyXeon
26b60fce11 add: small page internal API and system based theme
yandev code style on webroot/js/smallPage/theme.js, need to be cleaned
2024-11-12 00:09:23 -03:00
ThePedroo
90de86a5c7 fix: error upon opening web UI without any zygisk modules
This commit fixes the toast error that appears when opening ReZygisk's web UI.
2024-11-12 00:09:22 -03:00
RainyXeon
665ff2b8d9 improve: fatal error screen design 2024-11-12 00:09:22 -03:00
RainyXeon
9957be838f add: fatal error screen 2024-11-12 00:09:22 -03:00
RainyXeon
cde142de7f fix: open link on webui instead of browser 2024-11-12 00:09:21 -03:00
RainyXeon
0c455f3127 fix: link open on webui not browser (not confirmed) 2024-11-12 00:09:21 -03:00
RainyXeon
098a720fcc remove: unused css style 2024-11-12 00:09:20 -03:00
RainyXeon
3cc5c64e5e add: credits and license card in settings page 2024-11-12 00:09:20 -03:00
RainyXeon
ec53757c0a add: animation for tab and navbar 2024-11-12 00:09:19 -03:00
RainyXeon
7660bca27c fix: reverse zygote status 2024-11-12 00:09:19 -03:00
RainyXeon
61bad158e8 improve: action page design; add: daemon status 2024-11-12 00:09:18 -03:00
RainyXeon
da7cb91456 improve: WebUI by sync card between tab 2024-11-12 00:09:18 -03:00
RainyXeon
af09f6e264 remove: unused zip file 2024-11-12 00:09:17 -03:00
RainyXeon
1d38739100 add: window.onerror event 2024-11-12 00:09:16 -03:00
RainyXeon
ceb2cf24a9 add: window onerror event check 2024-11-12 00:09:15 -03:00
RainyXeon
3c1af44edc add: clear all log button 2024-11-12 00:09:15 -03:00
RainyXeon
073a0673a0 add: realtime error log tracking modal 2024-11-12 00:09:14 -03:00
RainyXeon
32ea9344dd remove: translation for error log 2024-11-12 00:09:14 -03:00
ThePedroo
60cf5fb9e1 update: WebUI English translation of Arch to Architecture
This commit changes the word that references the architecture from the brief "Arch" to the full "Architecture" word.
2024-11-12 00:09:13 -03:00
ThePedroo
1fb0926ac6 add: functional daemon action buttons
This commit adds the function that allows functional daemon action buttons.
2024-11-12 00:09:12 -03:00
ThePedroo
dde0436fd9 fix: JS code indentation/syntax
This commit fixes the syntax and indentation of the JavaScript code to meet the organization standard.
2024-11-12 00:09:12 -03:00
ThePedroo
ce54123a7c add: errors to error log history
This commit allows the errors to be saved on error log history.
2024-11-12 00:09:11 -03:00
ThePedroo
6ec8b5e7bd fix: JS code indentation/syntax
This commit fixes the syntax and indentation of the JavaScript code to meet the organization standard.
2024-11-12 00:09:10 -03:00
ThePedroo
3ef48b1dc4 update: Brazilian portuguese translations
This commit updates the translations for Brazilian portuguese.
2024-11-12 00:09:09 -03:00
ThePedroo
32579a2ebc fix: translations by reverting some to English
This commit reverts the translations done by Google Translator to English, waiting for natives to translate them.
2024-11-12 00:09:08 -03:00
Pedro.js
8a666edae6 add: LICENSE for webroot
This commit adds proper licensing for webroot folder.

Signed-off-by: Pedro.js <pedroolimpioguerra@gmail.com>
2024-11-12 00:09:06 -03:00
RainyXeon
b60209a0cb fix: overflow-y cannot scroll 2024-11-12 00:09:04 -03:00
RainyXeon
b15b33ddac fix: cannot enable light theme
Co-authored-by: CaptainThrowback <captainthrowback@hotmail.com>
2024-11-12 00:09:02 -03:00
RainyXeon
5788a9b67e fix: empty screen bug (silly error) 2024-11-12 00:09:01 -03:00
RainyXeon
e2e57113c1 fix: empty screen bug 2024-11-12 00:09:00 -03:00
RainyXeon
36eaaac200 improve: module element style 2024-11-12 00:08:59 -03:00
RainyXeon
ea2c8a5388 fix: infinity loading 2024-11-12 00:08:58 -03:00
RainyXeon
5352d4f0e6 fix: flash file corrupted (silly error) 2024-11-12 00:08:57 -03:00
RainyXeon
814fc3fe1e fix: flash file corrupted 2024-11-12 00:08:56 -03:00
RainyXeon
4dac5409d8 add: new webui framework (using navbar and refactor lang file) 2024-11-12 00:08:55 -03:00
RainyXeon
0b7c939c9f remove: webui test code in js/main.js 2024-11-12 00:08:54 -03:00
RainyXeon
db45eaee02 add: action card sepreate with settings 2024-11-12 00:08:53 -03:00
RainyXeon
259e1f0268 remove: webuiError file to avoid inf loading 2024-11-12 00:08:52 -03:00
RainyXeon
ffd0e36118 add: track webui error and log directly into error history (may not working) 2024-11-12 00:08:51 -03:00
WinCS
0818f0ade6 fix: zh_CN and zh_TW translations contributor link; improve: complexity in customize.sh
This commit fixes the contributor link for Chinese translations and improves the complexity in customise.sh by reducing it.
2024-11-12 00:08:50 -03:00
RainyXeon
59ac30d3cc add: builtin ProductSans font and option to toggle 2024-11-12 00:08:49 -03:00
ThePedroo
341d4944b4 add: credit for Chinese translations
This commit adds the credits for Chinese translations in "TRANSLATOR.md" file.
2024-11-12 00:08:49 -03:00
WinCS
afcf302d90 add: zn_CN and zn_TW web UI languages (#21)
This commit adds Chinese translations to the web UI.

Signed-off-by: WinCS <94188592+Meltartica@users.noreply.github.com>
2024-11-12 00:08:48 -03:00
RainyXeon
a18215226f fix: corrupted zip file in webui 2024-11-12 00:08:48 -03:00
RainyXeon
7ef7cf24e9 add: error history modal for easier to view log and copy 2024-11-12 00:08:47 -03:00
RainyXeon
e059917f73 fix: rezygisk appears as demo ui 2024-11-12 00:08:47 -03:00
RainyXeon
0538428a00 fix: webui infinity loading 2024-11-12 00:08:46 -03:00
Fyphen
f4b7c3bd9b add: japanese translation 2024-11-12 00:08:46 -03:00
RainyXeon
6952bf1888 fix: language list on modal not synchronized 2024-11-12 00:08:45 -03:00
RainyXeon
eb22157a8f fix: cannot load webui 2024-11-12 00:08:45 -03:00
RainyXeon
5778870963 fix: corrupted zip file in webui 2024-11-12 00:08:44 -03:00
RainyXeon
d1e86029ce fix: corrupted zip file in webui (not confirmed) 2024-11-12 00:08:44 -03:00
RainyXeon
d1d69ae553 fix: wrong locate of translate 2024-11-12 00:08:43 -03:00
RainyXeon
c92ad7c748 improve: language system based on json file
This commit will introduce new language system based on json file for easier to translate using crowdin in the future, also fix webui cannot load
2024-11-12 00:08:43 -03:00
RainyXeon
610683dfa2 improve: modal animation on webui by slow it down 2024-11-12 00:08:42 -03:00
RainyXeon
1bdaeaf0ac add: bottom slide animation for modal
This commit will add animation for modal that commit from the bottom (quite goofy) and click animation for theme-switch language-switch and close-modal icon
2024-11-12 00:08:42 -03:00
RainyXeon /
cbcb236255 fix: translation for webui for 95% translated 2024-11-12 00:08:42 -03:00
ThePedroo
41a15e87b7 fix: infinite loading; add: translate on set
This commit fixes the infinite loading area and adds the feature that it will already change all phrases on set, without the need of restart.
2024-11-12 00:08:41 -03:00
Emulond Argent
567cf1a8b9 add: ru_RU language to web UI (#18)
This commit adds Russian to the web UI language list.

Signed-off-by: Emulond Argent <108662981+Emulond@users.noreply.github.com>
2024-11-12 00:08:41 -03:00
ExtremeXT
d4d2c9d663 add: ro_RO language to web UI (#17)
This commit adds Romanian to the web UI language list.
2024-11-12 00:08:40 -03:00
RainyXeon /
a337b55efd add: base functional for lang system; fix: weird issue related to js 2024-11-12 00:08:40 -03:00
ThePedroo
ce080dff8f improve: Web UI by ignoring hw unsupported 64/32-bit
This commit improves Web UI Javascript code by allowing it to be aware of unsupported 64 or 32 bit, thus removing zygoteXX and daemonXX info.
2024-11-12 00:08:40 -03:00
ThePedroo
9fcf433b66 add: translation for errors; fix: pt_BR not exported
This commit adds translation for errors for both en_US and pt_BR. Also fixes the issue where brazilian portuguese translation wouldn't be exported.
2024-11-12 00:08:39 -03:00
ThePedroo
d9edb7c063 add: pt_BR translation; improve: code syntax
This commit both adds brazilian portuguese translation and improves the code syntax to match the standard.
2024-11-12 00:08:39 -03:00
RainyXeon /
c707c151fd add: lang list for lang modal 2024-11-12 00:08:38 -03:00
RainyXeon /
c3ddaa0bfe improve: warn color of bright card 2024-11-12 00:08:38 -03:00
RainyXeon /
ad3624b945 add: base code for modal/lang support [W.I.P] 2024-11-12 00:08:38 -03:00
RainyXeon /
ebdba3ba0f add: expand-able menu on settings card; fix: modules list not showing 2024-11-12 00:08:37 -03:00
ThePedroo
a6a268d2c1 improve: JS code by matching with the standard
This commit improves the JS code by making compliant to the standard of PerformanC.
2024-11-12 00:08:37 -03:00
ThePedroo
686342ced6 fix: missing module list
This commit fixes the missing module list due to mismatch in ID names.
2024-11-12 00:08:37 -03:00
RainyXeon /
3831547e6e fix: button in light theme 2024-11-12 00:08:36 -03:00
RainyXeon /
235117f52a add: start/stop/restart daemon button 2024-11-12 00:08:36 -03:00
RainyXeon /
e6c770fca2 improve: loading screen based in setting up time 2024-11-12 00:08:36 -03:00
RainyXeon /
daf9c78eed fix: module list field now showing on production 2024-11-12 00:08:35 -03:00
RainyXeon /
e0cb8da6dd add: loading screen, expandable list and card header icons
This commit will add new loading screen, expandable list and card header icons for improving UX/UI
2024-11-12 00:08:35 -03:00
RainyXeon /
292f75a81e add: pre-fix for module list 2024-11-12 00:08:35 -03:00
RainyXeon /
c909e21ebc add: new module list interface 2024-11-12 00:08:34 -03:00
RainyXeon /
37fc9a44b1 fix: svg sometimes not showing on webui 2024-11-12 00:08:34 -03:00
RainyXeon /
7b6b3cb9a0 improve: dim card color in light theme 2024-11-12 00:08:33 -03:00
RainyXeon /
6e8809b116 remove: unused code from index.html 2024-11-12 00:08:33 -03:00
RainyXeon /
1aa0e7e148 fix: light theme on dim card 2024-11-12 00:08:33 -03:00
RainyXeon /
1f011eefc3 add: light theme with button based 2024-11-12 00:08:32 -03:00
RainyXeon /
79d9e4c531 add: light theme base
This commit will add the base of light theme support in ReZygisk WebUI
2024-11-12 00:08:32 -03:00
ThePedroo
cf59aed3f9 add: webroot files to get sign
This commit simply adds the webroot files to be also verified the autencity.
2024-11-12 00:08:32 -03:00
ThePedroo
94905fb175 improve: web UI JS code
This commit improves the web UI Javascript code.
2024-11-12 00:08:31 -03:00
RainyXeon /
e5a7dfb862 remove: useless div card
This commit will remove useless div card in webui
2024-11-12 00:08:31 -03:00
RainyXeon /
f79eaf1185 improve: ReZygisk webui state
This commit will improve ReZygisk webui state by adding new red color and hide settings/modules card if it's error or not exist
2024-11-12 00:08:31 -03:00
RainyXeon /
9655c89ccc improve: description font
This commit will improve description font by adding more margin to make it more clear
2024-11-12 00:08:30 -03:00
RainyXeon /
2acda90379 add: mark icon for rezygisk state; improve: global fonts
This commit will add new icon for ReZygisk is mark. This icon will replect the state of ReZygisk. This commit also improve font by adding new local font named ProductSans for material you feeling
2024-11-12 00:08:30 -03:00
ThePedroo
bdf12dcf44 fix: building process; add: web UI JavaScript code
This commit both fixes the building process to include the webroot folder and adds the web UI JS code to allow it to fetch the values.
2024-11-12 00:08:29 -03:00
RainyXeon /
10bdf6f080 move: webui -> webroot; improve: design for webui
This commit will move webui dir to webroot dir and redesign the webui base on KernelSU UI
2024-11-12 00:08:29 -03:00
RainyXeon /
a3accd7a94 add: base for webui support in rezygisk
This commit will add the base for webui in rezygisk
2024-11-12 00:08:28 -03:00
36 changed files with 303 additions and 846 deletions

View File

@@ -59,7 +59,7 @@ body:
id: code_of_conduct id: code_of_conduct
attributes: attributes:
label: Code of Conduct 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: options:
- label: I agree to follow this project's Code of Conduct - label: I agree to follow this project's Code of Conduct
required: true required: true

View File

@@ -35,7 +35,7 @@ body:
id: code_of_conduct id: code_of_conduct
attributes: attributes:
label: Code of Conduct 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: options:
- label: I agree to follow this project's Code of Conduct - label: I agree to follow this project's Code of Conduct
required: true required: true

View File

@@ -1,6 +1,9 @@
name: Untrusted CI name: CI
on: on:
push:
branches: [ main ]
pull_request: pull_request:
merge_group: merge_group:
workflow_dispatch: workflow_dispatch:
@@ -22,7 +25,7 @@ jobs:
java-version: "17" java-version: "17"
- name: Setup Gradle - name: Setup Gradle
uses: gradle/actions/setup-gradle@v4 uses: gradle/actions/setup-gradle@v4.2.1
- name: Build with Gradle - name: Build with Gradle
run: | run: |

View File

@@ -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
View File

@@ -1,3 +1,3 @@
[submodule "LSPlt"] [submodule "loader/src/external/lsplt"]
path = loader/src/external/lsplt path = loader/src/external/lsplt
url = https://github.com/PerformanC/LSPlt url = https://github.com/JingMatrix/LSPlt

View File

@@ -6,13 +6,13 @@
- **es_ES** by [@LuchoModzzz](https://github.com/Lxchoooo) - **es_ES** by [@LuchoModzzz](https://github.com/Lxchoooo)
- **es_MX** by [@LuchoModzzz](https://github.com/Lxchoooo) - **es_MX** by [@LuchoModzzz](https://github.com/Lxchoooo)
- **fr_FR** by [@GhostFRR](https://github.com/GhostFRR) - **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) - **id_ID** by [@bpanca05](https://github.com/bpanca05) & [@LuckyKiddos](https://github.com/GuitarHeroStyles)
- **it_IT** by [@thasave14](https://github.com/thasave14) - **it_IT** by [@thasave14](https://github.com/thasave14)
- **pt_BR** by [@ThePedroo](https://github.com/ThePedroo) - **pt_BR** by [@ThePedroo](https://github.com/ThePedroo)
- **ro_RO** by [@ExtremeXT](https://github.com/ExtremeXT) - **ro_RO** by [@ExtremeXT](https://github.com/ExtremeXT)
- **ru_RU** by [@Emulond](https://github.com/Emulond) & [@AJleKcAHgP68](https://github.com/AJleKcAHgP68) - **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) - **uk_UA** by [@Kittyskj](https://github.com/Kittyskj)
- **vi_VN** by [@RainyXeon](https://github.com/RainyXeon) - **vi_VN** by [@RainyXeon](https://github.com/RainyXeon)
- **zh_CN** by [@Meltartica](https://github.com/Meltartica) & [@SheepChef](https://github.com/SheepChef) - **zh_CN** by [@Meltartica](https://github.com/Meltartica) & [@SheepChef](https://github.com/SheepChef)

View File

@@ -18,7 +18,7 @@ fun String.execute(currentWorkingDir: File = file("./")): String {
val gitCommitCount = "git rev-list HEAD --count".execute().toInt() val gitCommitCount = "git rev-list HEAD --count".execute().toInt()
val gitCommitHash = "git rev-parse --verify --short HEAD".execute() 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 moduleName by extra("ReZygisk")
val verName by extra("v1.0.0") val verName by extra("v1.0.0")
val verCode by extra(gitCommitCount) val verCode by extra(gitCommitCount)
@@ -38,18 +38,19 @@ val androidSourceCompatibility by extra(JavaVersion.VERSION_11)
val androidTargetCompatibility by extra(JavaVersion.VERSION_11) val androidTargetCompatibility by extra(JavaVersion.VERSION_11)
tasks.register("Delete", Delete::class) { tasks.register("Delete", Delete::class) {
delete(layout.buildDirectory.get()) delete(rootProject.buildDir)
} }
fun Project.configureBaseExtension() { fun Project.configureBaseExtension() {
extensions.findByType(LibraryExtension::class)?.run { extensions.findByType(LibraryExtension::class)?.run {
namespace = "com.performanc.org.rezygisk" namespace = "icu.nullptr.zygisk.next"
compileSdk = androidCompileSdkVersion compileSdk = androidCompileSdkVersion
ndkVersion = androidCompileNdkVersion ndkVersion = androidCompileNdkVersion
buildToolsVersion = androidBuildToolsVersion buildToolsVersion = androidBuildToolsVersion
defaultConfig { defaultConfig {
minSdk = androidMinSdkVersion minSdk = androidMinSdkVersion
targetSdk = androidTargetSdkVersion
} }
lint { lint {

View File

@@ -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)); ((uintptr_t)1 << ((hash >> img->gnu_shift2_) % bloom_mask_bits));
if ((mask & bloom_word) != mask) { if ((mask & bloom_word) != mask) {
/* INFO: Very loggy -- generates too much noise. GNU is rarely used for Zygisk context. */ LOGE("Symbol '%s' (hash %u) filtered out by GNU Bloom Filter (idx %zu, mask 0x%lx, word 0x%lx)",
/* 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);
name, hash, bloom_idx, (unsigned long)mask, (unsigned long)bloom_word);
*/
return 0; return 0;
} }

View File

@@ -4,9 +4,6 @@
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
#define IS_ISOLATED_SERVICE(uid) \
((uid) >= 90000 && (uid) < 1000000)
/* /*
* Bionic's atoi runs through strtol(). * Bionic's atoi runs through strtol().
* Use our own implementation for faster conversion. * Use our own implementation for faster conversion.

View File

@@ -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]);
}

View File

@@ -22,8 +22,5 @@ void entry(void* addr, size_t size, const char* path) {
LOGD("start plt hooking"); LOGD("start plt hooking");
hook_functions(); hook_functions();
clean_trace(path, 1, 0, false);
void *module_addrs[1] = { addr };
clean_trace(path, module_addrs, 1, 1, 0, false);
send_seccomp_event();
} }

View File

@@ -98,7 +98,6 @@ struct ZygiskContext {
~ZygiskContext(); ~ZygiskContext();
/* Zygisksu changed: Load module fds */ /* Zygisksu changed: Load module fds */
bool load_modules_only();
void run_modules_pre(); void run_modules_pre();
void run_modules_post(); void run_modules_post();
DCL_PRE_POST(fork) DCL_PRE_POST(fork)
@@ -125,8 +124,6 @@ struct ZygiskContext {
vector<tuple<dev_t, ino_t, const char *, void **>> *plt_hook_list; vector<tuple<dev_t, ino_t, const char *, void **>> *plt_hook_list;
map<string, vector<JNINativeMethod>> *jni_hook_list; map<string, vector<JNINativeMethod>> *jni_hook_list;
bool should_unmap_zygisk = false; bool should_unmap_zygisk = false;
bool enable_unloader = false;
bool hooked_unloader = false;
std::vector<lsplt::MapInfo> cached_map_infos = {}; std::vector<lsplt::MapInfo> cached_map_infos = {};
} // namespace } // 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); int res = old_pthread_attr_setstacksize((pthread_attr_t *)target, size);
LOGV("Call pthread_attr_setstacksize in [tid, pid]: %d, %d", gettid(), getpid()); LOGV("Call pthread_attr_setstacksize in [tid, pid]: %d, %d", gettid(), getpid());
if (!enable_unloader)
return res;
// Only perform unloading on the main thread // Only perform unloading on the main thread
if (gettid() != getpid()) if (gettid() != getpid())
return res; return res;
@@ -255,27 +249,6 @@ DCL_HOOK_FUNC(char *, strdup, const char *s) {
return old_strdup(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 #undef DCL_HOOK_FUNC
// ----------------------------------------------------------------- // -----------------------------------------------------------------
@@ -628,11 +601,9 @@ void ZygiskContext::sanitize_fds() {
struct dirent *entry; struct dirent *entry;
while ((entry = readdir(dir))) { while ((entry = readdir(dir))) {
int fd = parse_int(entry->d_name); 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); close(fd);
LOGW("Closed leaked fd: %d", fd);
} }
closedir(dir); closedir(dir);
@@ -644,12 +615,13 @@ void ZygiskContext::fork_post() {
g_ctx = nullptr; g_ctx = nullptr;
} }
bool ZygiskContext::load_modules_only() { /* Zygisksu changed: Load module fds */
void ZygiskContext::run_modules_pre() {
struct zygisk_modules ms; struct zygisk_modules ms;
if (rezygiskd_read_modules(&ms) == false) { if (rezygiskd_read_modules(&ms) == false) {
LOGE("Failed to read modules from zygiskd"); LOGE("Failed to read modules from zygiskd");
return false; return;
} }
for (size_t i = 0; i < ms.modules_count; i++) { for (size_t i = 0; i < ms.modules_count; i++) {
@@ -676,11 +648,6 @@ bool ZygiskContext::load_modules_only() {
free_modules(&ms); free_modules(&ms);
return true;
}
/* Zygisksu changed: Load module fds */
void ZygiskContext::run_modules_pre() {
for (auto &m : modules) { for (auto &m : modules) {
m.onLoad(env); m.onLoad(env);
@@ -702,19 +669,7 @@ void ZygiskContext::run_modules_post() {
if (modules.size() > 0) { if (modules.size() > 0) {
LOGD("modules unloaded: %zu/%zu", modules_unloaded, modules.size()); LOGD("modules unloaded: %zu/%zu", modules_unloaded, modules.size());
clean_trace("/data/adb", modules.size(), modules_unloaded, true);
/* 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);
} }
} }
@@ -722,48 +677,7 @@ void ZygiskContext::run_modules_post() {
void ZygiskContext::app_specialize_pre() { void ZygiskContext::app_specialize_pre() {
flags[APP_SPECIALIZE] = true; flags[APP_SPECIALIZE] = true;
/* INFO: Isolated services have different UIDs than the main apps. Because info_flags = rezygiskd_get_process_flags(g_ctx->args.app->uid, (const char *const)process);
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);
if (info_flags & PROCESS_IS_FIRST_STARTED) { if (info_flags & PROCESS_IS_FIRST_STARTED) {
/* INFO: To ensure we are really using a clean mount namespace, we use /* INFO: To ensure we are really using a clean mount namespace, we use
the first process it as reference for clean mount namespace, the first process it as reference for clean mount namespace,
@@ -773,64 +687,33 @@ void ZygiskContext::app_specialize_pre() {
update_mnt_ns(Clean, true); 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."); LOGD("Manager process detected. Notifying that Zygisk has been enabled.");
/* INFO: This environment variable is related to Magisk Zygisk/Manager. It /* INFO: This environment variable is related to Magisk Zygisk/Manager. It
it used by Magisk's Zygisk to communicate to Magisk Manager whether it used by Magisk's Zygisk to communicate to Magisk Manager whether
Zygisk is working or not, allowing Zygisk modules to both work properly Zygisk is working or not.
and for the manager to mark Zygisk as enabled.
However, to enhance capabilities of root managers, it is also set for To allow Zygisk modules to both work properly and for the manager to
any other supported manager, so that, if they wish, they can recognize identify Zygisk, being it not built-in, as working, we also set it. */
if Zygisk is enabled.
*/
setenv("ZYGISK_ENABLED", "1", 1); setenv("ZYGISK_ENABLED", "1", 1);
} else { } 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 /* INFO: Modules only have two "start off" points from Zygisk, preSpecialize and
postSpecialize. In preSpecialize, the process still has privileged postSpecialize. While preSpecialie in fact runs with Zygote (not superuser)
permissions, and therefore can execute mount/umount/setns functions. privileges, in postSpecialize it will now be with lower permission, in
If we update the mount namespace AFTER executing them, any mounts made the app's sandbox and therefore can move to a clean mount namespace after
will be lost, and the process will not have access to them anymore. executing the modules preSpecialize.
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.
*/ */
bool in_denylist = (info_flags & PROCESS_ON_DENYLIST) == PROCESS_ON_DENYLIST; if ((info_flags & PROCESS_ON_DENYLIST) == PROCESS_ON_DENYLIST) {
if (in_denylist) { flags[DO_REVERT_UNMOUNT] = true;
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 /* INFO: Executed after setns to ensure a module can update the mounts of an
application without worrying about it being overwritten by setns. application without worrying about it being overwritten by setns.
*/ */
run_modules_pre(); 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()) if (!is_child())
return; return;
load_modules_only();
run_modules_pre(); run_modules_pre();
rezygiskd_system_server_started(); rezygiskd_system_server_started();
@@ -939,7 +821,7 @@ ZygiskContext::~ZygiskContext() {
m.clearApi(); m.clearApi();
} }
enable_unloader = true; hook_unloader();
} }
} // namespace } // 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) \ #define PLT_HOOK_REGISTER(DEV, INODE, NAME) \
PLT_HOOK_REGISTER_SYM(DEV, INODE, #NAME, 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, size_t load, size_t unload, bool spoof_maps) {
void clean_trace(const char *path, void **module_addrs, size_t module_addrs_length, size_t load, size_t unload, bool spoof_maps) {
LOGD("cleaning trace for path %s", path); LOGD("cleaning trace for path %s", path);
if (load > 0 || unload > 0) solist_reset_counters(load, unload); if (load > 0 || unload > 0) solist_reset_counters(load, unload);
LOGD("Dropping solist record for %s", path); LOGD("Dropping solist record for %s", path);
bool any_dropped = false; bool path_found = solist_drop_so_path(path);
for (size_t i = 0; i < module_addrs_length; i++) { if (!path_found || !spoof_maps) return;
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;
LOGD("spoofing virtual maps for %s", path); LOGD("spoofing virtual maps for %s", path);
// spoofing map names is futile in Android, we do it simply
/* INFO: Spoofing maps names is futile, after all it will // to avoid Zygisk detections based on string comparison
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 */
for (auto &map : lsplt::MapInfo::Scan()) { for (auto &map : lsplt::MapInfo::Scan()) {
if (strstr(map.path.c_str(), path) && strstr(map.path.c_str(), "libzygisk") == 0) 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); mprotect(addr, size, PROT_READ);
} }
memcpy(copy, addr, size); memcpy(copy, addr, size);
mprotect(copy, size, map.perms);
mremap(copy, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, addr); 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, fork);
PLT_HOOK_REGISTER(android_runtime_dev, android_runtime_inode, unshare); 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, strdup);
PLT_HOOK_REGISTER(android_runtime_dev, android_runtime_inode, property_get);
hook_commit(); hook_commit();
// Remove unhooked methods // Remove unhooked methods
@@ -1048,13 +913,9 @@ void hook_functions() {
} }
static void hook_unloader() { static void hook_unloader() {
if (hooked_unloader) return;
hooked_unloader = true;
ino_t art_inode = 0; ino_t art_inode = 0;
dev_t art_dev = 0; dev_t art_dev = 0;
cached_map_infos = lsplt::MapInfo::Scan();
for (auto &map : cached_map_infos) { for (auto &map : cached_map_infos) {
if (map.path.ends_with("/libart.so")) { if (map.path.ends_with("/libart.so")) {
art_inode = map.inode; art_inode = map.inode;
@@ -1064,16 +925,7 @@ static void hook_unloader() {
} }
if (art_dev == 0 || art_inode == 0) { 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"); LOGE("virtual map for libart.so is not cached");
hooked_unloader = false;
return; return;
} else { } else {
LOGD("hook_unloader called with libart.so [%zu:%lu]", art_dev, art_inode); LOGD("hook_unloader called with libart.so [%zu:%lu]", art_dev, art_inode);

View File

@@ -213,7 +213,6 @@ case 5: \
bool tryUnload() const { return unload && dlclose(handle) == 0; }; bool tryUnload() const { return unload && dlclose(handle) == 0; };
void clearApi() { memset(&api, 0, sizeof(api)); } void clearApi() { memset(&api, 0, sizeof(api)); }
int getId() const { return id; } int getId() const { return id; }
void *getEntry() const { return entry.ptr; }
ZygiskModule(int id, void *handle, void *entry); ZygiskModule(int id, void *handle, void *entry);

View File

@@ -2,28 +2,27 @@
#include <stdbool.h> #include <stdbool.h>
#include <string.h> #include <string.h>
#include <android/dlext.h>
#include <linux/limits.h>
#include "elf_util.h" #include "elf_util.h"
#include "logging.h" #include "logging.h"
#include "solist.h" #include "solist.h"
/* TODO: Is offset for realpath necessary? It seems to have the function
available anywhere. */
#ifdef __LP64__ #ifdef __LP64__
size_t solist_size_offset = 0x18; size_t solist_size_offset = 0x18;
size_t solist_next_offset = 0x30;
size_t solist_realpath_offset = 0x1a8; size_t solist_realpath_offset = 0x1a8;
#else #else
size_t solist_size_offset = 0x90; size_t solist_size_offset = 0x90;
size_t solist_next_offset = 0xa4;
size_t solist_realpath_offset = 0x174; size_t solist_realpath_offset = 0x174;
#endif #endif
static const char *(*get_realpath_sym)(SoInfo *) = NULL; static const char *(*get_realpath_sym)(SoInfo *) = NULL;
static void (*soinfo_free)(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) { static inline const char *get_path(SoInfo *self) {
if (get_realpath_sym) 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; *(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) { static bool pdg_setup(ElfImg *img) {
ppdg.ctor = (void *(*)())getSymbAddress(img, "__dl__ZN18ProtectedDataGuardC2Ev"); ppdg.ctor = (void *(*)())getSymbAddress(img, "__dl__ZN18ProtectedDataGuardC2Ev");
@@ -45,20 +48,22 @@ static bool pdg_setup(ElfImg *img) {
return ppdg.ctor != NULL && ppdg.dtor != NULL; 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() { 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 SoInfo *solist = NULL;
static size_t *g_module_unload_counter = 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() { static bool solist_init() {
#ifdef __LP64__ #ifdef __LP64__
@@ -72,6 +77,10 @@ static bool solist_init() {
return false; return false;
} }
ppdg = (struct pdg) {
.ctor = NULL,
.dtor = NULL
};
if (!pdg_setup(linker)) { if (!pdg_setup(linker)) {
LOGE("Failed to setup pdg"); LOGE("Failed to setup pdg");
@@ -87,6 +96,17 @@ static bool solist_init() {
See #63 for more information. 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"); somain = (SoInfo *)getSymbValueByPrefix(linker, "__dl__ZL6somain");
if (somain == NULL) { if (somain == NULL) {
LOGE("Failed to find somain __dl__ZL6somain*"); LOGE("Failed to find somain __dl__ZL6somain*");
@@ -98,6 +118,20 @@ static bool solist_init() {
LOGD("%p is somain", (void *)somain); 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"); get_realpath_sym = (const char *(*)(SoInfo *))getSymbAddress(linker, "__dl__ZNK6soinfo12get_realpathEv");
if (get_realpath_sym == NULL) { if (get_realpath_sym == NULL) {
LOGE("Failed to find get_realpath __dl__ZNK6soinfo12get_realpathEv"); 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); LOGD("%p is soinfo_free", (void *)soinfo_free);
find_containing_library = (SoInfo *(*)(const void *))getSymbAddress(linker, "__dl__Z23find_containing_libraryPKv"); g_module_load_counter = (uint64_t *)getSymbAddress(linker, "__dl__ZL21g_module_load_counter");
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");
if (g_module_load_counter != NULL) LOGD("found symbol g_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"); if (g_module_unload_counter != NULL) LOGD("found symbol g_module_unload_counter");
for (size_t i = 0; i < 1024 / sizeof(void *); i++) { 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 *)); 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) { if (possible_size_of_somain < 0x100000 && possible_size_of_somain > 0x100) {
solist_size_offset = i * sizeof(void *); solist_size_offset = i * sizeof(void *);
LOGD("solist_size_offset is %zu * %zu = %p", i, sizeof(void *), (void *)solist_size_offset); 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; break;
} }
@@ -152,49 +183,36 @@ static bool solist_init() {
return true; return true;
} }
/* INFO: find_containing_library returns the SoInfo for the library that contains bool solist_drop_so_path(const char *target_path) {
that memory inside its limits, hence why named "lib_memory" in ReZygisk. */ if (solist == NULL && !solist_init()) {
bool solist_drop_so_path(void *lib_memory) {
if (somain == NULL && !solist_init()) {
LOGE("Failed to initialize solist"); LOGE("Failed to initialize solist");
return false; return false;
} }
SoInfo *found = (*find_containing_library)(lib_memory); for (SoInfo *iter = solist; iter; iter = get_next(iter)) {
if (found == NULL) { if (get_path(iter) && strstr(get_path(iter), target_path)) {
LOGD("Could not find containing library for %p", lib_memory); 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)); return false;
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;
} }
void solist_reset_counters(size_t load, size_t unload) { 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"); LOGE("Failed to initialize solist");
return; return;
@@ -206,18 +224,18 @@ void solist_reset_counters(size_t load, size_t unload) {
return; return;
} }
size_t loaded_modules = *g_module_load_counter; uint64_t loaded_modules = *g_module_load_counter;
size_t unloaded_modules = *g_module_unload_counter; uint64_t unloaded_modules = *g_module_unload_counter;
if (loaded_modules >= load) { 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) { 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);
} }
} }

View File

@@ -35,7 +35,7 @@ struct pdg {
SOURCES: SOURCES:
- https://android.googlesource.com/platform/bionic/+/refs/heads/android15-release/linker/linker.cpp#1712 - 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 INFO: When dlopen'ing a library, the system will increment 1 to a global

View File

@@ -7,6 +7,4 @@ extern size_t block_size;
void hook_functions(); 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); void clean_trace(const char* path, size_t load = 1, size_t unload = 0, bool spoof_maps = false);
extern "C" void send_seccomp_event();

View File

@@ -355,7 +355,7 @@ void rezygiskd_listener_callback() {
case SYSTEM_SERVER_STARTED: { case SYSTEM_SERVER_STARTED: {
LOGD("system server started, mounting prop"); 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"); PLOGE("failed to mount prop");
} }
@@ -405,7 +405,7 @@ static bool ensure_daemon_created(bool is_64bit) {
if (is_64bit || (!is_64bit && !status64.supported)) { if (is_64bit || (!is_64bit && !status64.supported)) {
LOGD("new zygote started."); 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) { 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 */ /* INFO: We need to create the file first, otherwise the mount will fail */
close(open(PROP_PATH, O_WRONLY | O_CREAT | O_TRUNC, 0644)); 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) { if (orig_prop == NULL) {
PLOGE("failed to open orig prop"); PLOGE("failed to open orig prop");

View File

@@ -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"); void *libc_return_addr = find_module_return_addr(map, "libc.so");
LOGD("libc return addr %p", libc_return_addr); 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 */ /* call dlopen */
void *dlopen_addr = NULL; #ifdef __LP64__
if (!libdl_path || (dlopen_addr = find_func_addr(local_map, map, libdl_path, "dlopen")) == NULL) { 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 */ /* 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"); LOGW("Failed to find dlopen from libdl.so, will load from linker");
#ifdef __LP64__ dlopen_addr = find_func_addr(local_map, map, "/system/bin/linker", "__dl_dlopen");
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
if (dlopen_addr == NULL) { if (dlopen_addr == NULL) {
PLOGE("Find __dl_dlopen"); PLOGE("Find __dl_dlopen");
@@ -224,16 +198,16 @@ bool inject_on_main(int pid, const char *lib_path) {
LOGE("handle is null"); LOGE("handle is null");
/* call dlerror */ /* call dlerror */
void *dlerror_addr = NULL; #ifdef __LP64__
if (!libdl_path || (dlerror_addr = find_func_addr(local_map, map, libdl_path, "dlerror")) == NULL) { 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 */ /* 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"); LOGW("Failed to find dlerror from libdl.so, will load from linker");
#ifdef __LP64__ dlerror_addr = find_func_addr(local_map, map, "/system/bin/linker", "__dl_dlerror");
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
if (dlerror_addr == NULL) { if (dlerror_addr == NULL) {
LOGE("Find __dl_dlerror"); LOGE("Find __dl_dlerror");
@@ -251,19 +225,19 @@ bool inject_on_main(int pid, const char *lib_path) {
LOGE("dlerror str is null"); LOGE("dlerror str is null");
free(args); free(args);
free_maps(local_map);
free_maps(map);
return false; 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) { if (strlen_addr == NULL) {
LOGE("find strlen"); LOGE("find strlen");
free(args); free(args);
free_maps(local_map);
free_maps(map);
return false; return false;
} }
@@ -275,8 +249,6 @@ bool inject_on_main(int pid, const char *lib_path) {
LOGE("dlerror len <= 0"); LOGE("dlerror len <= 0");
free(args); free(args);
free_maps(local_map);
free_maps(map);
return false; return false;
} }
@@ -286,8 +258,6 @@ bool inject_on_main(int pid, const char *lib_path) {
LOGE("malloc err"); LOGE("malloc err");
free(args); free(args);
free_maps(local_map);
free_maps(map);
return false; return false;
} }
@@ -299,23 +269,20 @@ bool inject_on_main(int pid, const char *lib_path) {
free(err); free(err);
free(args); free(args);
free_maps(local_map);
free_maps(map);
return false; return false;
} }
/* call dlsym(handle, "entry") */ /* call dlsym(handle, "entry") */
void *dlsym_addr = NULL; #ifdef __LP64__
if (!libdl_path || (dlsym_addr = find_func_addr(local_map, map, libdl_path, "dlsym")) == NULL) { 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 */ /* 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"); LOGW("Failed to find dlsym from libdl.so, will load from linker");
#ifdef __LP64__ dlsym_addr = find_func_addr(local_map, map, "/system/bin/linker", "__dl_dlsym");
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
if (dlsym_addr == NULL) { if (dlsym_addr == NULL) {
LOGE("find __dl_dlsym"); LOGE("find __dl_dlsym");
@@ -403,7 +370,7 @@ bool trace_zygote(int pid) {
int status; 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"); PLOGE("seize");
return false; return false;
@@ -438,16 +405,6 @@ bool trace_zygote(int pid) {
if (STOPPED_WITH(SIGCONT, 0)) { if (STOPPED_WITH(SIGCONT, 0)) {
LOGD("received SIGCONT"); 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); ptrace(PTRACE_DETACH, pid, 0, SIGCONT);
} }
} else { } else {

View File

@@ -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) { 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++) { for (size_t i = 0; i < map->size; i++) {
if (map->maps[i].path == NULL) continue; 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; return (void *)map->maps[i].start;
} }
@@ -522,32 +530,6 @@ int fork_dont_care() {
return pid; return pid;
} }
void tracee_skip_syscall(int pid) {
struct user_regs_struct regs;
if (!get_regs(pid, &regs)) {
LOGE("failed to get seccomp regs");
exit(1);
}
regs.REG_SYSNR = -1;
if (!set_regs(pid, &regs)) {
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) { void wait_for_trace(int pid, int *status, int flags) {
while (1) { while (1) {
pid_t result = waitpid(pid, status, flags); pid_t result = waitpid(pid, status, flags);
@@ -558,13 +540,7 @@ void wait_for_trace(int pid, int *status, int flags) {
exit(1); exit(1);
} }
if (*status >> 8 == (SIGTRAP | (PTRACE_EVENT_SECCOMP << 8))) { if (!WIFSTOPPED(*status)) {
tracee_skip_syscall(pid);
ptrace(PTRACE_CONT, pid, 0, 0);
continue;
} else if (!WIFSTOPPED(*status)) {
char status_str[64]; char status_str[64];
parse_status(*status, status_str, sizeof(status_str)); parse_status(*status, status_str, sizeof(status_str));

View File

@@ -37,22 +37,18 @@ void free_maps(struct maps *maps);
#define REG_SP rsp #define REG_SP rsp
#define REG_IP rip #define REG_IP rip
#define REG_RET rax #define REG_RET rax
#define REG_SYSNR orig_rax
#elif defined(__i386__) #elif defined(__i386__)
#define REG_SP esp #define REG_SP esp
#define REG_IP eip #define REG_IP eip
#define REG_RET eax #define REG_RET eax
#define REG_SYSNR orig_eax
#elif defined(__aarch64__) #elif defined(__aarch64__)
#define REG_SP sp #define REG_SP sp
#define REG_IP pc #define REG_IP pc
#define REG_RET regs[0] #define REG_RET regs[0]
#define REG_SYSNR regs[8]
#elif defined(__arm__) #elif defined(__arm__)
#define REG_SP uregs[13] #define REG_SP uregs[13]
#define REG_IP uregs[15] #define REG_IP uregs[15]
#define REG_RET uregs[0] #define REG_RET uregs[0]
#define REG_SYSNR uregs[7]
#define user_regs_struct user_regs #define user_regs_struct user_regs
#endif #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); 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_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); void *find_func_addr(struct maps *local_info, struct maps *remote_info, const char *module, const char *func);

View File

@@ -93,6 +93,7 @@ androidComponents.onVariants { variant ->
doLast { doLast {
if (file("private_key").exists()) { if (file("private_key").exists()) {
println("=== Guards the peace of Machikado ===")
val privateKey = file("private_key").readBytes() val privateKey = file("private_key").readBytes()
val publicKey = file("public_key").readBytes() val publicKey = file("public_key").readBytes()
val namedSpec = NamedParameterSpec("ed25519") 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) { fun getSign(name: String, abi: String, is64Bit: Boolean) {
val set = TreeSet<Pair<File, File?>> { o1, o2 -> val set = TreeSet<Pair<File, File?>> { o1, o2 ->
o1.first.path.replace("\\", "/") o1.first.path.replace("\\", "/")
@@ -182,32 +154,11 @@ androidComponents.onVariants { variant ->
signFile.appendBytes(publicKey) 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.arm64", "arm64-v8a", true)
getSign("machikado.arm", "armeabi-v7a", false) getSign("machikado.arm", "armeabi-v7a", false)
getSign("machikado.x86_64", "x86_64", true) getSign("machikado.x86_64", "x86_64", true)
getSign("machikado.x86", "x86", false) 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 { } else {
println("no private_key found, this build will not be signed") 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_64").asFile.createNewFile()
root.file("machikado.x86").asFile.createNewFile() root.file("machikado.x86").asFile.createNewFile()
}
fileTree(moduleDir).visit { fileTree(moduleDir).visit {
if (isDirectory) return@visit if (isDirectory) return@visit
val md = MessageDigest.getInstance("SHA-256")
val md = MessageDigest.getInstance("SHA-256") file.forEachBlock(4096) { bytes, size ->
file.forEachBlock(4096) { bytes, size -> md.update(bytes, 0, size)
md.update(bytes, 0, size)
}
file(file.path + ".sha256").writeText(Hex.encodeHexString(md.digest()))
} }
file(file.path + ".sha256").writeText(Hex.encodeHexString(md.digest()))
root.file("misaki.sig").asFile.createNewFile()
} }
} }
} }

View File

@@ -49,7 +49,7 @@ export async function getTranslations(locate) {
} }
export async function getAvailableLanguages() { 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) if (lsCmd.errno !== 0) return setError('WebUI', lsCmd.stderr)

View File

@@ -18,13 +18,13 @@ const monitor_status = document.getElementById('monitor_status');
monitor_status.innerHTML = translations.page.actions.status.tracing 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_stop.addEventListener('click', () => {
monitor_status.innerHTML = translations.page.actions.status.exiting 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', () => { monitor_pause.addEventListener('click', () => {
@@ -32,7 +32,7 @@ const monitor_status = document.getElementById('monitor_status');
monitor_status.innerHTML = translations.page.actions.status.stopped 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')
}) })
} }
})() })()

View File

@@ -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 のライセンス"
}
}
}
}

View File

@@ -121,7 +121,11 @@ void companion_entry(int fd) {
ASSURE_SIZE_WRITE("ZygiskdCompanion", "module_entry", ret, sizeof(uint8_t)); 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); sigaction(SIGPIPE, &sa, NULL);
while (1) { while (1) {

View File

@@ -62,7 +62,6 @@ void apatch_get_existence(struct root_impl_state *state) {
} }
struct package_config { struct package_config {
char *process;
uid_t uid; uid_t uid;
bool root_granted; bool root_granted;
bool umount_needed; bool umount_needed;
@@ -105,7 +104,7 @@ bool _apatch_get_package_config(struct packages_config *restrict config) {
return false; return false;
} }
config->configs[config->size].process = strdup(strtok(line, ",")); strtok(line, ",");
char *exclude_str = strtok(NULL, ","); char *exclude_str = strtok(NULL, ",");
if (exclude_str == NULL) continue; 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) { 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); free(config->configs);
} }
@@ -160,7 +155,7 @@ bool apatch_uid_granted_root(uid_t uid) {
return false; 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; struct packages_config config;
if (!_apatch_get_package_config(&config)) { if (!_apatch_get_package_config(&config)) {
_apatch_free_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; 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); _apatch_free_package_config(&config);
return false; return false;

View File

@@ -7,7 +7,7 @@ void apatch_get_existence(struct root_impl_state *state);
bool apatch_uid_granted_root(uid_t uid); 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); bool apatch_uid_is_manager(uid_t uid);

View File

@@ -30,7 +30,6 @@ void root_impls_setup(void) {
impl.impl = Multiple; impl.impl = Multiple;
} else if (state_ksu.state == Supported) { } else if (state_ksu.state == Supported) {
impl.impl = KernelSU; impl.impl = KernelSU;
impl.variant = state_ksu.variant;
} else if (state_apatch.state == Supported) { } else if (state_apatch.state == Supported) {
impl.impl = APatch; impl.impl = APatch;
} else if (state_magisk.state == Supported) { } 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); return ksu_uid_should_umount(uid);
} }
case APatch: { case APatch: {
return apatch_uid_should_umount(uid, process); return apatch_uid_should_umount(uid);
} }
case Magisk: { case Magisk: {
return magisk_uid_should_umount(process); return magisk_uid_should_umount(process);

View File

@@ -19,12 +19,6 @@
#define CMD_GET_VERSION 2 #define CMD_GET_VERSION 2
#define CMD_UID_GRANTED_ROOT 12 #define CMD_UID_GRANTED_ROOT 12
#define CMD_UID_SHOULD_UMOUNT 13 #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) { void ksu_get_existence(struct root_impl_state *state) {
int version = 0; int version = 0;
@@ -48,26 +42,6 @@ void ksu_get_existence(struct root_impl_state *state) {
} }
state->state = Supported; 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 if (version >= 1 && version <= MIN_KSU_VERSION - 1) state->state = TooOld;
else state->state = Abnormal; else state->state = Abnormal;
@@ -94,24 +68,8 @@ bool ksu_uid_should_umount(uid_t uid) {
} }
bool ksu_uid_is_manager(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; struct stat s;
if (stat(manager_path, &s) == -1) { if (stat("/data/user_de/0/me.weishu.kernelsu", &s) == -1) {
if (errno != ENOENT) { if (errno != ENOENT) {
LOGE("Failed to stat KSU manager data directory: %s\n", strerror(errno)); LOGE("Failed to stat KSU manager data directory: %s\n", strerror(errno));
} }

View File

@@ -3,11 +3,6 @@
#include "../constants.h" #include "../constants.h"
enum kernelsu_variants {
KOfficial,
KNext
};
void ksu_get_existence(struct root_impl_state *state); void ksu_get_existence(struct root_impl_state *state);
bool ksu_uid_granted_root(uid_t uid); bool ksu_uid_granted_root(uid_t uid);

View File

@@ -28,7 +28,7 @@ char *magisk_managers[] = {
#define DEBUG_RAMDISK_MAGISK lp_select("/debug_ramdisk/magisk32", "/debug_ramdisk/magisk64") #define DEBUG_RAMDISK_MAGISK lp_select("/debug_ramdisk/magisk32", "/debug_ramdisk/magisk64")
#define BITLESS_DEBUG_RAMDISK_MAGISK "/debug_ramdisk/magisk" #define BITLESS_DEBUG_RAMDISK_MAGISK "/debug_ramdisk/magisk"
static enum magisk_variants variant = MOfficial; enum magisk_variants variant = Official;
/* INFO: Longest path */ /* INFO: Longest path */
static char path_to_magisk[sizeof(DEBUG_RAMDISK_MAGISK)] = { 0 }; static char path_to_magisk[sizeof(DEBUG_RAMDISK_MAGISK)] = { 0 };
bool is_using_sulist = false; bool is_using_sulist = false;
@@ -74,7 +74,7 @@ void magisk_get_existence(struct root_impl_state *state) {
return; 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++) { for (unsigned long i = 0; i < sizeof(supported_variants) / sizeof(supported_variants[0]); i++) {
if (strstr(magisk_info, supported_variants[i])) { if (strstr(magisk_info, supported_variants[i])) {

View File

@@ -4,8 +4,8 @@
#include "../constants.h" #include "../constants.h"
enum magisk_variants { enum magisk_variants {
MOfficial, Official,
MKitsune Kitsune
}; };
void magisk_get_existence(struct root_impl_state *state); void magisk_get_existence(struct root_impl_state *state);

View File

@@ -20,7 +20,6 @@
#include "utils.h" #include "utils.h"
#include "root_impl/common.h" #include "root_impl/common.h"
#include "root_impl/kernelsu.h"
#include "root_impl/magisk.h" #include "root_impl/magisk.h"
int clean_namespace_fd = 0; int clean_namespace_fd = 0;
@@ -437,8 +436,7 @@ void stringify_root_impl_name(struct root_impl impl, char *restrict output) {
break; break;
} }
case KernelSU: { case KernelSU: {
if (impl.variant == KOfficial) strcpy(output, "KernelSU"); strcpy(output, "KernelSU");
else strcpy(output, "KernelSU Next");
break; break;
} }
@@ -448,8 +446,11 @@ void stringify_root_impl_name(struct root_impl impl, char *restrict output) {
break; break;
} }
case Magisk: { case Magisk: {
if (impl.variant == MOfficial) strcpy(output, "Magisk Official"); if (impl.variant == 0) {
else strcpy(output, "Magisk Kitsune"); strcpy(output, "Magisk Official");
} else {
strcpy(output, "Magisk Kitsune");
}
break; break;
} }
@@ -602,57 +603,115 @@ bool umount_root(struct root_impl impl) {
return false; return false;
} }
/* INFO: "Magisk" is the longest word that will ever be put in source_name */ switch (impl.impl) {
char source_name[sizeof("magisk")]; case None: { break; }
if (impl.impl == KernelSU) strcpy(source_name, "KSU"); case Multiple: { break; }
else if (impl.impl == APatch) strcpy(source_name, "APatch");
else strcpy(source_name, "magisk");
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; LOGI("[%s] Unmounting root", source_name);
size_t num_targets = 0;
for (size_t i = 0; i < mounts.length; i++) { const char **targets_to_unmount = NULL;
struct mountinfo mount = mounts.mounts[i]; size_t num_targets = 0;
bool should_unmount = false; for (size_t i = 0; i < mounts.length; i++) {
/* INFO: The root implementations have their own /system mounts, so we struct mountinfo mount = mounts.mounts[i];
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;
if (strcmp(mount.source, source_name) == 0) should_unmount = true; bool should_unmount = false;
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; /* 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++; if (strcmp(mount.source, source_name) == 0) should_unmount = true;
targets_to_unmount = realloc(targets_to_unmount, num_targets * sizeof(char*)); if (strncmp(mount.root, "/adb/modules", strlen("/adb/modules")) == 0) should_unmount = true;
if (targets_to_unmount == NULL) { if (strncmp(mount.target, "/data/adb/modules", strlen("/data/adb/modules")) == 0) should_unmount = true;
LOGE("[%s] Failed to allocate memory for targets_to_unmount\n", source_name);
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(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--) { for (size_t i = 0; i < mounts.length; i++) {
const char *target = targets_to_unmount[i - 1]; struct mountinfo mount = mounts.mounts[i];
if (umount2(target, MNT_DETACH) == -1) {
LOGE("[%s] Failed to unmount %s: %s\n", source_name, target, strerror(errno)); bool should_unmount = false;
} else { /* INFO: Magisk has its own /system mounts, so we only skip the mount
LOGI("[%s] Unmounted %s\n", source_name, target); 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); free_mounts(&mounts);
@@ -785,7 +844,7 @@ int save_mns_fd(int pid, enum MountNamespaceState mns_state, struct root_impl im
return -1; 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."); LOGI("[Magisk] Magisk Kitsune detected, will skip cache first.");
/* INFO: MagiskSU of Kitsune has a special behavior: It is only mounted /* INFO: MagiskSU of Kitsune has a special behavior: It is only mounted

View File

@@ -65,9 +65,6 @@
return -1; \ return -1; \
} }
#define IS_ISOLATED_SERVICE(uid) \
((uid) >= 90000 && (uid) < 1000000)
#define write_func_def(type) \ #define write_func_def(type) \
ssize_t write_## type(int fd, type val) ssize_t write_## type(int fd, type val)

View File

@@ -44,18 +44,15 @@ enum Architecture {
#define TMP_PATH "/data/adb/rezygisk" #define TMP_PATH "/data/adb/rezygisk"
#define CONTROLLER_SOCKET TMP_PATH "/init_monitor" #define CONTROLLER_SOCKET TMP_PATH "/init_monitor"
#define PATH_CP_NAME TMP_PATH "/" lp_select("cp32.sock", "cp64.sock") #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_FILE PATH_MODULES_DIR "/zygisksu/bin/zygiskd" lp_select("32", "64")
#define ZYGISKD_PATH "/data/adb/modules/rezygisk/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) { static enum Architecture get_arch(void) {
char system_arch[64]; char system_arch[32];
get_property("ro.product.cpu.abilist", system_arch); 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, "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); LOGE("Unsupported system architecture: %s\n", system_arch);
exit(1); exit(1);
@@ -86,7 +83,7 @@ static void load_modules(enum Architecture arch, struct Context *restrict contex
struct dirent *entry; struct dirent *entry;
while ((entry = readdir(dir)) != NULL) { while ((entry = readdir(dir)) != NULL) {
if (entry->d_type != DT_DIR) continue; /* INFO: Only directories */ 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 *name = entry->d_name;
char so_path[PATH_MAX]; 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->modules[context->len].companion = -1;
context->len++; context->len++;
} }
closedir(dir);
} }
static void free_modules(struct Context *restrict context) { static void free_modules(struct Context *restrict context) {
@@ -360,9 +355,6 @@ void zygiskd_start(char *restrict argv[]) {
return; return;
} }
struct sigaction sa = { .sa_handler = SIG_IGN };
sigaction(SIGPIPE, &sa, NULL);
bool first_process = true; bool first_process = true;
while (1) { while (1) {
int client_fd = accept(socket_fd, NULL, NULL); int client_fd = accept(socket_fd, NULL, NULL);