Compare commits

...
56 Commits
Author SHA1 Message Date
wbruno b20483dd9a Merge pull request 'Update SmartDock to new version' (#218) from rduttshukla/feat/smartdock-update-and-permission-fix into main
Reviewed-on: #218
2026-10-12 14:01:14 -04:00
wbruno 8020dbd8fc Merge pull request 'Fix forgotten commas in microg.py' (#270) from MarSoft/patch-1 into main
Reviewed-on: #270
2026-10-12 14:00:52 -04:00
wbruno b7e1c37e14 Merge pull request 'Fix /data/adb/magisk permissions so Zygisk can initialise' (#284) from MisterWizzard/fix/magisk-data-adb-permissions into main
Reviewed-on: #284
2026-10-12 14:00:19 -04:00
wbruno 2f6547f873 Merge pull request 'feat: add device spoof to fix Play Store device compatibility' (#275) from EsymDnB/main into main
Reviewed-on: #275
2026-10-12 13:59:31 -04:00
Suggon 48dbfaf34a Update houdini library with extended expiry date (July 1, 2028)
Intel's libhoudini library includes a built-in "expiry date" that
prevents execution after a certain date. The previous versions expired
on January 1, 2026 (#256) and September 1, 2026 respectively.

This update refreshes the library to a newer build per
https://github.com/supremegamers/vendor_intel_proprietary_houdini/issues/6
and has an extended expiry date of July 1, 2028.
2026-09-11 14:56:36 +02:00
MisterWizzardandClaude Opus 5 b09e018894 Fix /data/adb/magisk permissions so Zygisk can initialise
General.install() runs copy() -> extra1() -> set_perm(). set_perm() only walks
self.files, which are paths under copy_dir (the overlay), so the copy that
Magisk.setup() makes into <data_dir>/adb/magisk keeps the 0644 the binaries
inherit from the apk extraction.

A non-executable /data/adb/magisk/magisk64 makes magisk_env() abort at
post-fs-data. Root still works, because that runs from the overlay copy, but
Zygisk never initialises: the Magisk app reports "Zygisk: No" no matter what the
zygisk setting says, and no error is surfaced to explain why. This breaks every
Zygisk module (LSPosed, Shamiko, PlayIntegrityFix, ...).

Fix setup() to apply the same 0755 to its own destination that
Magisk.set_path_perm() already applies to magisk paths.

Adds a regression test that passes with the fix and fails without it. It needs no
Waydroid install, no root and no extra dependencies:

    python3 tests/test_magisk_setup_perms.py

Fixes #283

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-30 09:49:05 +10:00
mcheesemanandClaude Sonnet 4.6 3bc2b310a3 feat: add device spoof to fix Play Store device compatibility
Adds a device_spoof module that writes Android device identity
properties into waydroid.cfg, enabling games like Destiny Rising
that reject Waydroid's generic device profile. Includes Pixel 6
and Samsung Galaxy S21 profiles.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 20:03:41 +08:00
Семён Марьясин 963e3511fe Fix forgotten commas in microg.py
Choosing Minimal variants resulted in this without my fix:

  File "/nix/store/2a3cl1fvl0418qmkrvndx4si29w9yvv5-waydroid-script-0-unstable-2026-01-05/lib/python3.13/site-packages/stuff/microg.py", line 109, in __init__
    self.act_md5 = self.dl_links[variant][1]
                   ~~~~~~~~~~~~~~~~~~~~~~^^^
IndexError: list index out of range
2026-04-14 19:04:01 +03:00
ayasa520 d5289cfd89 Update libhoudini (#256)
* Update download link for Houdini version 13
2026-01-05 09:56:03 +01:00
NullBite ddaa6b190f Add Nix flake and improve derivation
This adds a Nix flake to the repo as well as updates the derivation so
that it includes `lzip` as a dependency
2025-11-17 10:08:53 +01:00
Gerry Bagaskoro Putro 15020ec20a fix(nodataperm): prevent crash when uninstalling on Android 13 2025-11-11 19:37:38 +01:00
Alessandro Astone fcb15624db Fix A13 widevine
Closes: https://github.com/casualsnek/waydroid_script/issues/236
2025-08-31 22:56:59 +02:00
Alessandro Astone db43c7c9cf main: Default to A13
Following Waydroid which now defaults to A13
2025-08-18 12:41:31 +02:00
Mio 3e344b360f fix https://github.com/casualsnek/waydroid_script/issues/229 2025-07-13 09:11:10 +02:00
金雄镕 5527d390eb Reorder ro.product.cpu.abilist to prioritize 64-bit ABIs 2025-07-11 19:43:32 +02:00
MasterKia 6f44d95070 Fix microg installation guide
The previous command returns an error ("ModuleNotFoundError: No module named 'InquirerPy'") even after installing the InquirerPy module using pip.
2025-07-04 10:43:21 +02:00
Alessandro Astone 32d21c8074 Change ndk_translation for A13 2025-05-30 18:36:04 +02:00
Alessandro Astone eb337a1351 Change houdini for A13
Even though this is extracted from an Android 14 image, it works better
including on AMD CPUs

Closes: #224
2025-05-21 21:40:38 +02:00
Alessandro Astone 48186df8af A13 ndk_translation 2025-05-20 00:02:29 +02:00
Alessandro Astone c14650010e A13 houdini 2025-05-20 00:02:29 +02:00
Rishi 2d3bd9432f Update SmartDock to new version and add WRITE_SECURE_SETTINGS to fix bootloop 2025-03-22 17:09:09 +05:30
Casu Al Snek 1a2d3ad643 Merge pull request #143 from mistrmochov/patch-2
Update to Magisk Delta 26.3
2024-01-20 19:29:28 +05:45
mistrmochov 7cccf2b56d Maintainer of Magisk Delta, just deleted the repo for older Magisk Delta, so I put it on my repo 2024-01-10 19:16:24 +01:00
mistrmochov d31988a829 Update to Magisk Delta 26.3
Your script works fine with last Magisk Delta (before Kitsune Mask update).

Also with modified setup for bootanim
2024-01-09 16:44:57 +01:00
Casu Al Snek b12c06568c Merge pull request #132 from mkg20001/nix
Add nixos derivation
2024-01-09 09:12:53 +05:45
Casu Al Snek e0de64c047 Merge pull request #133 from mkg20001/fdroidpriv
Add fdroidpriv for installing f-droid privleged extension
2024-01-09 09:12:10 +05:45
Casu Al Snek bc3efd48c2 Merge pull request #131 from linyinfeng/fix-houdini
Fix binfmt_misc mounting for libhoudini
2024-01-09 09:11:33 +05:45
Casu Al Snek cd6239737a Downgrade magisk to Magisk_Delta_25210_canary_fdac22ba 2024-01-09 09:09:14 +05:45
Casu Al Snek 97293f3cc1 Merge pull request #140 from s1204IT/main
Update MindTheGapps package
2024-01-03 18:24:03 +05:45
Syuugo 76caf7e1d7 Fix filename 2023-12-22 12:49:35 +09:00
Syuugo 3527282950 Redirect user 2023-12-22 08:39:07 +09:00
Syuugo d2502086ed Update MTG package 2023-12-22 08:37:26 +09:00
Maciej Krüger c5110830f7 Add fdroidpriv for installing f-droid privleged extension 2023-11-20 03:35:08 +01:00
Maciej Krüger d81b72fed7 Add nixos derivation 2023-11-20 03:34:03 +01:00
Lin Yinfeng bd8d53906a Fix binfmt_misc mounting for libhoudini 2023-10-23 20:17:25 +08:00
Casu Al Snek acbb764ac5 Merge pull request #94 from mak448a/patch-1
Various grammar fixes
2023-09-26 19:06:34 +05:45
Casu Al Snek 45602d27c8 Merge pull request #122 from claui/mitm
Install self-signed CA cert into trust store
2023-09-25 19:47:04 +05:45
mak448a 6706f4b9d7 Merge branch 'main' into patch-1 2023-09-24 20:50:18 -05:00
Claudia b1c88db1ce Feature: install self-signed cacert to trust store
For analysis and reverse engineering, it can be helpful to insert a
custom CA certificate into Waydroid’s system-wide trust store.
Users used to be able to do that via Android’s settings but not anymore.

The `install mitm` command accepts a path to a file that contains a
– typically self-signed – CA certificate in PEM format.
It then renames [1] and copies the file into the overlay file system,
placing it into Waydroid’s trust store.

As a usage example, the following command lines enable your host to use
mitmproxy [2] to act as a proxy and to intercept [3] HTTP(S) connections
that come from the Waydroid container:

```sh
$ timeout --preserve-status 2 mitmdump -n                           # creates a CA cert in ~/.mitmproxy
$ sudo venv/bin/python3 main.py install mitm --ca-cert ~/.mitmproxy/mitmproxy-ca-cert.pem
INFO: Creating directory: /system/etc/security/cacerts
INFO: Copying /home/yourname/.mitmproxy/mitmproxy-ca-cert.pem to system trust store
INFO: Target file: /system/etc/security/cacerts/6320a7db.0
INFO: mitm installation finished
$ sudo waydroid shell -- ls -l /system/etc/security/cacerts         # double-check that it worked
[…]
-rw-r--r-- 1 root root 1191 2024-01-01 00:00 6320a7db.0
[…]
$ adb shell settings put global http_proxy ${YOUR_IP_HERE?}:3128    # tell Waydroid to use the proxy
                                                                    #     for all connections
$ mitmproxy -p 3128                                                 # start proxy and display a TUI
                                                                    #     with HTTP(S) connections
                                                                    #     coming from Waydroid
```

[1]: https://docs.mitmproxy.org/stable/howto-install-system-trusted-ca-android/#2-rename-certificate

[2]: https://mitmproxy.org/

[3]: https://docs.mitmproxy.org/stable/mitmproxytutorial-interceptrequests/
2023-09-23 18:34:14 +02:00
Casu Al Snek 688c84fd58 Merge pull request #124 from Benjamin-Loison/main
Add `bash` syntax highlighting to `README.md`
2023-09-23 20:54:44 +05:45
Benjamin Loison 367697d59e Add bash syntax highlighting to README.md 2023-09-17 02:26:48 +02:00
Casu Al Snek 77e222fb16 Merge pull request #118 from ayasa520/main
Fix some issues that prevented scripts from working properly
2023-08-25 14:47:59 +05:45
Rikka 821c7c0bc2 Update prompt 2023-08-24 23:33:10 +08:00
Rikka 854b4b0a6c Use venv to avoid breaking Python installation or OS 2023-08-24 23:33:04 +08:00
Rikka 6d5af57ebc fix: Fix simlink path issue
https://github.com/casualsnek/waydroid_script/issues/101
Relative path fails when using symlink. Replace it with absolute path.
2023-08-24 23:22:20 +08:00
Rikka a80ff8e855 update hidestatusbar link 2023-08-24 23:22:16 +08:00
Rikka 3e51f7f56e update smartdock link 2023-08-24 23:22:05 +08:00
Rikka e1ee7f0b0c Fix capitalization of MicroG and update nodataperm 2023-08-24 23:21:53 +08:00
ayasa520 337d066eeb fix(microg): typos 2023-08-24 23:17:14 +08:00
Casu Al Snek 4db9bb3cba Merge pull request #110 from axolotlek/main
fix cli commands mistakes in readme
2023-08-19 00:13:01 +05:45
Casu Al Snek 489159c5f9 Merge pull request #111 from SUFandom/patch-1
[URGENT] Update nodataperm.py by changing MD5SUM hash to updated state
2023-07-25 23:48:31 +05:45
SUFandom 9c2d8fcd83 [URGENT] Update nodataperm.py
Change the MD5Sum Because trying it spams error because its invalid

Suggestion: Just add the main.zip to the Releases tag and let The script grab the 'stable' version there an just change it alongside with the python script library for update to not add issues
2023-07-25 20:09:05 +08:00
axolotlek 098036cca9 fixed mistakes in readme 2023-07-25 14:46:43 +03:00
axolotlek 212135d3c8 fixed mistakes in readme 2023-07-25 13:59:51 +03:00
mak448a 7b5c7f64c0 Update README.md 2023-06-15 13:53:47 -05:00
mak448a b80dcf171f Update README.md 2023-06-15 13:38:56 -05:00
23 changed files with 643 additions and 97 deletions
+3
View File
@@ -105,4 +105,7 @@ venv.bak/
# mypy # mypy
.mypy_cache/ .mypy_cache/
# nix
result*
test.py test.py
+36 -24
View File
@@ -1,5 +1,6 @@
# Waydroid Extras Script # Waydroid Extras Script
Script to add gapps and other stuff to waydroid !
Script to add GApps and other stuff to Waydroid!
# Installation/Usage # Installation/Usage
@@ -8,8 +9,9 @@ Script to add gapps and other stuff to waydroid !
``` ```
git clone https://github.com/casualsnek/waydroid_script git clone https://github.com/casualsnek/waydroid_script
cd waydroid_script cd waydroid_script
sudo python3 -m pip install -r python3 -m venv venv
sudo python main.py venv/bin/pip install -r requirements.txt
sudo venv/bin/python3 main.py
``` ```
![image-20230430013103883](assets/img/README/image-20230430013103883.png) ![image-20230430013103883](assets/img/README/image-20230430013103883.png)
@@ -22,17 +24,20 @@ sudo python main.py
## Command Line ## Command Line
```bash
git clone https://github.com/casualsnek/waydroid_script git clone https://github.com/casualsnek/waydroid_script
cd waydroid_script cd waydroid_script
sudo python3 -m pip install -r requirements.txt python3 -m venv venv
venv/bin/pip install -r requirements.txt
# install something # install something
sudo python3 main.py install {gapps, magisk, libndk, libhoudini, nodataperm, smartdock, microg} sudo venv/bin/python3 main.py install {gapps, magisk, libndk, libhoudini, nodataperm, smartdock, microg, mitm}
# uninstall something # uninstall something
sudo python3 main.py uninstall {gapps, magisk, libndk, libhoudini, nodataperm, smartdock, microg} sudo venv/bin/python3 main.py uninstall {gapps, magisk, libndk, libhoudini, nodataperm, smartdock, microg}
# get Android device ID # get Android device ID
sudo python main.py certified sudo venv/bin/python3 main.py certified
# some hacks # some hacks
sudo python3 hack {nodataperm, hidestatusbar} sudo venv/bin/python3 main.py hack {nodataperm, hidestatusbar}
```
## Dependencies ## Dependencies
@@ -50,18 +55,19 @@ sudo python main.py
![](assets/1.png) ![](assets/1.png)
Open terminal and switch to directory where "main.py" is located then run: Open terminal and switch to the directory where "main.py" is located then run:
sudo python3 main.py install gapps sudo venv/bin/python3 main.py install gapps
Then launch waydroid with: Then launch waydroid with:
waydroid show-full-ui waydroid show-full-ui
After waydroid has finished booting open terminal and switch to directory where "main.py" is located then run: After waydroid has finished booting, open terminal and switch to directory where "main.py" is located then run:
sudo python3 main.py google sudo python3 main.py google
Copy the returned numeric ID open ["https://google.com/android/uncertified/?pli=1"](https://google.com/android/uncertified/?pli=1) enter the id and register it, you may need to wait upto 10-20 minutes for device to get registered, then clear Google Play Service's cache and try logging in ! Copy the returned numeric ID, then open ["https://google.com/android/uncertified/?pli=1"](https://google.com/android/uncertified/?pli=1). Enter the ID and register it. Wait 10-20 minutes for device to get registered. Then clear Google Play Service's cache and try logging in!
## Install Magisk ## Install Magisk
@@ -69,7 +75,7 @@ Copy the returned numeric ID open ["https://google.com/android/uncertified/?pli=
Open terminal and switch to directory where "main.py" is located then run: Open terminal and switch to directory where "main.py" is located then run:
sudo python3 main.py install magisk sudo venv/bin/python3 main.py install magisk
Magisk will be installed on next boot! Magisk will be installed on next boot!
@@ -87,7 +93,7 @@ libndk seems to have better performance than libhoudini on AMD.
Open terminal and switch to directory where "main.py" is located then run: Open terminal and switch to directory where "main.py" is located then run:
sudo python3 main.py install libndk sudo venv/bin/python3 main.py install libndk
## Install libhoudini arm translation ## Install libhoudini arm translation
@@ -99,7 +105,7 @@ houdini64 version: 11.0.1b_z.38765.m
Open terminal and switch to directory where "main.py" is located then run: Open terminal and switch to directory where "main.py" is located then run:
sudo python3 main.py install libhoudini sudo venv/bin/python3 main.py install libhoudini
## Integrate Widevine DRM (L3) ## Integrate Widevine DRM (L3)
@@ -107,7 +113,7 @@ Open terminal and switch to directory where "main.py" is located then run:
Open terminal and switch to directory where "main.py" is located then run: Open terminal and switch to directory where "main.py" is located then run:
sudo python3 main.py install widevine sudo venv/bin/python3 main.py install widevine
## Install Smart Dock ## Install Smart Dock
@@ -116,7 +122,13 @@ Open terminal and switch to directory where "main.py" is located then run:
Open terminal and switch to directory where "main.py" is located then run: Open terminal and switch to directory where "main.py" is located then run:
sudo python3 main.py install smartdock sudo venv/bin/python3 main.py install smartdock
## Install a self-signed CA certificate
Open terminal and switch to directory where "main.py" is located then run:
sudo venv/bin/python3 main.py install mitm --ca-cert mycert.pem
## Granting full permission for apps data (HACK) ## Granting full permission for apps data (HACK)
@@ -130,9 +142,9 @@ Arknights, PUNISHING: GRAY RAVEN and other games won't freeze on the black scree
Open terminal and switch to directory where "main.py" is located then run: Open terminal and switch to directory where "main.py" is located then run:
``` ```
sudo python3 main.py hack nodataperm sudo venv/bin/python3 main.py hack nodataperm
``` ```
**WARNING**: Tested on `lineage-18.1-20230128-VANILLA-waydroid_x86_64.img`. This script will replace `/system/framework/service.jar`, which may prevent WayDroid from booting. If so, run `sudo python3 main.py uninstall nodataperm` to remove it. **WARNING**: Tested on `lineage-18.1-20230128-VANILLA-waydroid_x86_64.img`. This script will replace `/system/framework/service.jar`, which may prevent WayDroid from booting. If so, run `sudo venv/bin/python3 main.py uninstall nodataperm` to remove it.
Or you can run the following commands directly in `sudo waydroid shell`. In this way, every time a new game is installed, you need to run it again, but it's much less risky. Or you can run the following commands directly in `sudo waydroid shell`. In this way, every time a new game is installed, you need to run it again, but it's much less risky.
@@ -154,7 +166,7 @@ chmod 777 -R /mnt/*/*/*/*/Android/obb
![](assets/7.png) ![](assets/7.png)
``` ```
sudo python main.py install microg sudo venv/bin/python3 main.py install microg
``` ```
## Hide Status Bar ## Hide Status Bar
@@ -165,18 +177,18 @@ After
![After](assets/9.png) ![After](assets/9.png)
``` ```
sudo python3 main.py hack hidestatusbar sudo venv/bin/python3 main.py hack hidestatusbar
``` ```
## Get Android ID for device registration ## Get Android ID for device registration
You need to register you device with its it before being able to use gapps, this will print out your Android ID which you can use for device registration required for google apps: You need to register you device with its it before being able to use gapps, this will print out your Android ID which you can use for device registration required for Google apps:
Open terminal and switch to directory where "main.py" is located then run: Open terminal and switch to directory where "main.py" is located then run:
sudo python3 main.py google sudo venv/bin/python3 main.py certified
Star this repository if you find this useful, if you encounter problem create a issue on github ! Star this repository if you find this useful, if you encounter problem create an issue on GitHub!
## Error handling ## Error handling
+4
View File
@@ -0,0 +1,4 @@
let
pkgs = import <nixpkgs> {};
in
pkgs.callPackage ./package.nix { }
Generated
+41
View File
@@ -0,0 +1,41 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1707650010,
"narHash": "sha256-dOhphIA4MGrH4ElNCy/OlwmN24MsnEqFjRR6+RY7jZw=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "809cca784b9f72a5ad4b991e0e7bcf8890f9c3a6",
"type": "github"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs",
"systems": "systems"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}
+21
View File
@@ -0,0 +1,21 @@
{
description = "Waydroid Extras Script";
inputs = {
systems.url = "github:nix-systems/default";
};
outputs = { self, nixpkgs, systems }:
let
inherit (nixpkgs) lib;
eachSystem = lib.genAttrs (import systems);
mkApp = program: { type = "app"; inherit program; };
in {
packages = eachSystem (system: rec {
waydroid_script = nixpkgs.legacyPackages."${system}".callPackage ./package.nix { };
default = waydroid_script;
});
apps = eachSystem (system: rec {
waydroid_script = mkApp "${self.outputs.packages.${system}.waydroid_script}/bin/waydroid_script";
default = waydroid_script;
});
};
}
+39 -8
View File
@@ -12,10 +12,13 @@ from stuff.hidestatusbar import HideStatusBar
from stuff.houdini import Houdini from stuff.houdini import Houdini
from stuff.magisk import Magisk from stuff.magisk import Magisk
from stuff.microg import MicroG from stuff.microg import MicroG
from stuff.mitm import Mitm
from stuff.ndk import Ndk from stuff.ndk import Ndk
from stuff.nodataperm import Nodataperm from stuff.nodataperm import Nodataperm
from stuff.smartdock import Smartdock from stuff.smartdock import Smartdock
from stuff.widevine import Widevine from stuff.widevine import Widevine
from stuff.fdroidpriv import FDroidPriv
from stuff.device_spoof import DeviceSpoof, PROFILES
import tools.helper as helper import tools.helper as helper
from tools import container from tools import container
from tools import images from tools import images
@@ -82,7 +85,13 @@ def install_app(args):
if "smartdock" in app: if "smartdock" in app:
install_list.append(Smartdock()) install_list.append(Smartdock())
if "microg" in app: if "microg" in app:
install_list.append(MicroG(args.android_version)) install_list.append(MicroG(args.android_version, args.microg_variant))
if "mitm" in app:
install_list.append(Mitm(args.ca_cert_file))
if "fdroidpriv" in app:
install_list.append(FDroidPriv(args.android_version))
if "device_spoof" in app:
DeviceSpoof(getattr(args, "spoof_profile", "pixel6")).install()
if not container.use_overlayfs(): if not container.use_overlayfs():
copy_dir = "/tmp/waydroid" copy_dir = "/tmp/waydroid"
@@ -130,6 +139,12 @@ def remove_app(args):
remove_list.append(Smartdock()) remove_list.append(Smartdock())
if "microg" in app: if "microg" in app:
remove_list.append(MicroG(args.android_version, args.microg_variant)) remove_list.append(MicroG(args.android_version, args.microg_variant))
if "mitm" in app:
remove_list.append(Mitm())
if "fdroidpriv" in app:
remove_list.append(FDroidPriv(args.android_version))
if "device_spoof" in app:
DeviceSpoof().uninstall()
if "nodataperm" in app: if "nodataperm" in app:
remove_list.append(Nodataperm(args.android_version)) remove_list.append(Nodataperm(args.android_version))
if "hidestatusbar" in app: if "hidestatusbar" in app:
@@ -200,7 +215,7 @@ def interact():
Choice(name="Android 13", value="13"), Choice(name="Android 13", value="13"),
Choice(name="Exit", value=None) Choice(name="Exit", value=None)
], ],
default="11", default="13",
).execute() ).execute()
if not android_version: if not android_version:
exit() exit()
@@ -219,10 +234,9 @@ def interact():
if not action: if not action:
exit() exit()
install_choices = ["gapps", "microg", "libndk", "magisk", "smartdock",] install_choices = ["gapps", "microg", "libndk", "libhoudini", "magisk", "smartdock", "fdroidpriv", "widevine", "device_spoof"]
hack_choices = [] hack_choices = []
if android_version=="11": if android_version=="11":
install_choices.extend(["libhoudini", "widevine"])
hack_choices.extend(["nodataperm", "hidestatusbar"]) hack_choices.extend(["nodataperm", "hidestatusbar"])
if action == "Install": if action == "Install":
@@ -235,13 +249,20 @@ def interact():
).execute() ).execute()
microg_variants = ["Standard", "NoGoolag", microg_variants = ["Standard", "NoGoolag",
"UNLP", "Minimal", "MinimalIAP"] "UNLP", "Minimal", "MinimalIAP"]
if "MicroG" in apps: if "microg" in apps:
microg_variant = inquirer.select( microg_variant = inquirer.select(
message="Select MicroG variant", message="Select MicroG variant",
choices=microg_variants, choices=microg_variants,
default="Standard", default="Standard",
).execute() ).execute()
args.microg_variant = microg_variant args.microg_variant = microg_variant
if "device_spoof" in apps:
spoof_profile = inquirer.select(
message="Select device profile to spoof",
choices=list(PROFILES.keys()),
default="pixel6",
).execute()
args.spoof_profile = spoof_profile
args.app = apps args.app = apps
install_app(args) install_app(args)
elif action == "Remove": elif action == "Remove":
@@ -278,7 +299,7 @@ def main():
parser.add_argument('-a', '--android-version', parser.add_argument('-a', '--android-version',
dest='android_version', dest='android_version',
help='Specify the Android version', help='Specify the Android version',
default="11", default="13",
choices=["11", "13"]) choices=["11", "13"])
# android command # android command
@@ -286,8 +307,8 @@ def main():
'certified', help='Get device ID to obtain Play Store certification') 'certified', help='Get device ID to obtain Play Store certification')
certified.set_defaults(func=get_certified) certified.set_defaults(func=get_certified)
install_choices = ["gapps", "microg", "libndk", install_choices = ["gapps", "microg", "libndk", "libhoudini",
"libhoudini", "magisk", "smartdock", "widevine"] "magisk", "mitm", "smartdock", "widevine", "device_spoof"]
hack_choices = ["nodataperm", "hidestatusbar"] hack_choices = ["nodataperm", "hidestatusbar"]
micrg_variants = ["Standard", "NoGoolag", "UNLP", "Minimal", "MinimalIAP"] micrg_variants = ["Standard", "NoGoolag", "UNLP", "Minimal", "MinimalIAP"]
remove_choices = install_choices remove_choices = install_choices
@@ -305,6 +326,7 @@ microg: Add microG, Aurora Store and Aurora Droid to WayDriod
libndk: Add libndk arm translation, better for AMD CPUs libndk: Add libndk arm translation, better for AMD CPUs
libhoudini: Add libhoudini arm translation, better for Intel CPUs libhoudini: Add libhoudini arm translation, better for Intel CPUs
magisk: Install Magisk Delta to WayDroid magisk: Install Magisk Delta to WayDroid
mitm -c CA_CERT_FILE: Install root CA cert into system trust store
smartdock: A desktop mode launcher for Android smartdock: A desktop mode launcher for Android
widevine: Add support for widevine DRM L3 widevine: Add support for widevine DRM L3
""" """
@@ -313,6 +335,15 @@ widevine: Add support for widevine DRM L3
'install', formatter_class=argparse.RawTextHelpFormatter, help='Install an app') 'install', formatter_class=argparse.RawTextHelpFormatter, help='Install an app')
install_parser.add_argument( install_parser.add_argument(
**arg_template, choices=install_choices, help=install_help) **arg_template, choices=install_choices, help=install_help)
install_parser.add_argument('-c', '--ca-cert',
dest='ca_cert_file',
help='[for mitm only] The CA certificate file (*.pem) to install',
default=None)
install_parser.add_argument('-p', '--spoof-profile',
dest='spoof_profile',
help='[for device_spoof only] Device profile to spoof',
choices=list(PROFILES.keys()),
default="pixel6")
install_parser.set_defaults(func=install_app) install_parser.set_defaults(func=install_app)
# remove and its aliases # remove and its aliases
+32
View File
@@ -0,0 +1,32 @@
{ lib,
stdenvNoCC,
lzip,
python3,
makeWrapper }:
let
wrappedPath = lib.makeBinPath [ lzip ];
in stdenvNoCC.mkDerivation {
name = "waydroid_script";
buildInputs = [
(python3.withPackages(ps: with ps; [ tqdm requests inquirerpy ]))
];
nativeBuildInputs = [
makeWrapper
];
src = ./.;
postPatch = ''
patchShebangs main.py
'';
installPhase = ''
mkdir -p $out/libexec
cp -r . $out/libexec/waydroid_script
mkdir -p $out/bin
makeShellWrapper $out/libexec/waydroid_script/main.py $out/bin/waydroid_script \
--prefix PATH : "${wrappedPath}"
'';
}
+1 -1
View File
@@ -14,7 +14,7 @@ class AndroidId:
except: except:
return return
else: else:
Logger.error("WayDroid isn't running !") Logger.error("Please make sure Waydroid is running and Gapps has been installed!")
return return
print(queryout.replace("android_id|", "").strip()) print(queryout.replace("android_id|", "").strip())
print(" ^----- Open https://google.com/android/uncertified/?pli=1") print(" ^----- Open https://google.com/android/uncertified/?pli=1")
+71
View File
@@ -0,0 +1,71 @@
import configparser
from tools.logger import Logger
PROFILES = {
"pixel6": {
"ro.product.brand": "google",
"ro.product.manufacturer": "Google",
"ro.product.model": "Pixel 6",
"ro.product.name": "oriole",
"ro.product.device": "oriole",
"ro.product.board": "oriole",
"ro.build.product": "oriole",
"ro.build.fingerprint": "google/oriole/oriole:13/TQ3A.230901.001/10750268:user/release-keys",
"ro.build.description": "oriole-user 13 TQ3A.230901.001 10750268 release-keys",
"ro.build.version.release": "13",
"ro.build.version.sdk": "33",
"ro.build.type": "user",
"ro.build.tags": "release-keys",
},
"samsung_s21": {
"ro.product.brand": "samsung",
"ro.product.manufacturer": "samsung",
"ro.product.model": "SM-G991B",
"ro.product.name": "o1sxeea",
"ro.product.device": "o1s",
"ro.product.board": "lahaina",
"ro.build.product": "o1s",
"ro.build.fingerprint": "samsung/o1sxeea/o1s:13/TP1A.220624.014/G991BXXU5EWCA:user/release-keys",
"ro.build.description": "o1sxeea-user 13 TP1A.220624.014 G991BXXU5EWCA release-keys",
"ro.build.version.release": "13",
"ro.build.version.sdk": "33",
"ro.build.type": "user",
"ro.build.tags": "release-keys",
},
}
PROP_KEYS = list(next(iter(PROFILES.values())).keys())
class DeviceSpoof:
id = "device_spoof"
def __init__(self, profile_name="pixel6") -> None:
if profile_name not in PROFILES:
raise ValueError(f"Unknown profile '{profile_name}'. Choose from: {list(PROFILES.keys())}")
self.profile_name = profile_name
self.apply_props = PROFILES[profile_name]
def _read_cfg(self):
cfg = configparser.ConfigParser()
cfg.read("/var/lib/waydroid/waydroid.cfg")
if not cfg.has_section("properties"):
cfg.add_section("properties")
return cfg
def install(self):
cfg = self._read_cfg()
for key, value in self.apply_props.items():
cfg.set("properties", key, value)
with open("/var/lib/waydroid/waydroid.cfg", "w") as f:
cfg.write(f)
Logger.info(f"Device spoofed as '{self.profile_name}'. Restart Waydroid to apply.")
def uninstall(self):
cfg = self._read_cfg()
for key in PROP_KEYS:
cfg.remove_option("properties", key)
with open("/var/lib/waydroid/waydroid.cfg", "w") as f:
cfg.write(f)
Logger.info("Device spoof properties removed. Restart Waydroid to apply.")
+42
View File
@@ -0,0 +1,42 @@
import os
import shutil
from stuff.general import General
class FDroidPriv(General):
id = "fdroid priv"
dl_links = {"11": ["https://f-droid.org/repo/org.fdroid.fdroid.privileged.ota_2130.zip",
"6242cab56d197d80c598593a46da62e4"],
"13": ["https://f-droid.org/repo/org.fdroid.fdroid.privileged.ota_2130.zip",
"6242cab56d197d80c598593a46da62e4"]}
partition = "system"
dl_file_name = "org.fdroid.fdroid.privileged.ota_2130.zip"
dl_link = ...
act_md5 = ...
extract_to = "/tmp/fdroid_ota_2130"
files = [
"app/F-Droid.apk"
"app/F-Droid/F-Droid.apk"
"etc/permissions/permissions_org.fdroid.fdroid.privileged.xml"
"priv-app/F-DroidPrivilegedExtension.apk"
"priv-app/F-DroidPrivilegedExtension/F-DroidPrivilegedExtension.apk"
]
file_map = {
"permissions_org.fdroid.fdroid.privileged.xml": "etc/permissions/permissions_org.fdroid.fdroid.privileged.xml",
"F-Droid.apk": "app/F-Droid/F-Droid.apk",
"F-DroidPrivilegedExtension.apk": "priv-app/F-DroidPrivilegedExtension/F-DroidPrivilegedExtension.apk",
}
def __init__(self, android_version="11") -> None:
super().__init__()
self.dl_link = self.dl_links[android_version][0]
self.act_md5 = self.dl_links[android_version][1]
def copy(self):
for f, d in self.file_map.items():
rro_file = os.path.join(
self.copy_dir, self.partition, d)
rro_dir = os.path.dirname(rro_file)
if not os.path.exists(rro_dir):
os.makedirs(rro_dir)
shutil.copyfile(os.path.join(self.extract_to, f), rro_file)
+4 -4
View File
@@ -15,10 +15,10 @@ class Gapps(General):
"armeabi-v7a": ["https://sourceforge.net/projects/opengapps/files/arm/20220215/open_gapps-arm-11.0-pico-20220215.zip", "8719519fa32ae83a62621c6056d32814"] "armeabi-v7a": ["https://sourceforge.net/projects/opengapps/files/arm/20220215/open_gapps-arm-11.0-pico-20220215.zip", "8719519fa32ae83a62621c6056d32814"]
}, },
"13": { "13": {
"x86_64": ["https://github.com/Howard20181/MindTheGappsBuilder/releases/download/20230323/MindTheGapps-13.0.0-x86_64-20230323.zip", "aba427be1ddd0963121c87a4eda80299"], "x86_64": ["https://github.com/s1204IT/MindTheGappsBuilder/releases/download/20231028/MindTheGapps-13.0.0-x86_64-20231028.zip", "63ccebbf93d45c384f58d7c40049d398"],
"x86": ["https://github.com/Howard20181/MindTheGappsBuilder/releases/download/20230323/MindTheGapps-13.0.0-x86-20230323.zip", "f02d2f1a3f0a084f13ab4c1b58ad7554"], "x86": ["https://github.com/s1204IT/MindTheGappsBuilder/releases/download/20231028/MindTheGapps-13.0.0-x86-20231028.zip", "f12b6a8ed14eedbb4b5b3c932a865956"],
"arm64-v8a": ["https://github.com/Howard20181/MindTheGappsBuilder/releases/download/20230323/MindTheGapps-13.0.0-arm64-20230323.zip", "18484a5622eeccffcea2b43205655d8a"], "arm64-v8a": ["https://github.com/s1204IT/MindTheGappsBuilder/releases/download/20231028/MindTheGapps-13.0.0-arm64-20231028.zip", "11180da0a5d9f2ed2863882c30a8d556"],
"armeabi-v7a": ["https://github.com/Howard20181/MindTheGappsBuilder/releases/download/20230323/MindTheGapps-13.0.0-arm-20230323.zip", "e4c00a7eb1e4dfca0fc6a3e447710264"] "armeabi-v7a": ["https://github.com/s1204IT/MindTheGappsBuilder/releases/download/20231028/MindTheGapps-13.0.0-arm-20231028.zip", "d525c980bac427844aa4cb01628f8a8f"]
} }
} }
android_version = ... android_version = ...
+2 -2
View File
@@ -73,8 +73,8 @@ class General:
if not os.path.isfile(os.path.join(bin_dir, "resetprop")): if not os.path.isfile(os.path.join(bin_dir, "resetprop")):
if not os.path.exists(bin_dir): if not os.path.exists(bin_dir):
os.makedirs(bin_dir) os.makedirs(bin_dir)
shutil.copy(os.path.join( shutil.copy(os.path.join(os.path.join(os.path.dirname(__file__), "..", "bin",
"./bin", self.arch[0], "resetprop"), bin_dir) self.arch[0], "resetprop")), bin_dir)
os.chmod(os.path.join(bin_dir, "resetprop"), 0o755) os.chmod(os.path.join(bin_dir, "resetprop"), 0o755)
if not os.path.isfile(os.path.join(bin_dir, "resetprop.sh")): if not os.path.isfile(os.path.join(bin_dir, "resetprop.sh")):
with open(os.path.join(bin_dir, "resetprop.sh"), "w") as f: with open(os.path.join(bin_dir, "resetprop.sh"), "w") as f:
+2 -2
View File
@@ -5,8 +5,8 @@ from stuff.general import General
class HideStatusBar(General): class HideStatusBar(General):
id = "hide status bar" id = "hide status bar"
dl_links = {"11": ["https://github.com/ayasa520/hide-status-bar/releases/download/v0.0.1/app-release.apk", dl_links = {"11": ["https://github.com/ayasa520/hide-status-bar/releases/download/v0.0.2/app-release.apk",
"ae6c4cc567d6f3de77068e54e43818e2"]} "ff2fe63ddfb4b035e6720a1b195b2355"]}
partition = "system" partition = "system"
dl_file_name = "hidestatusbar.apk" dl_file_name = "hidestatusbar.apk"
dl_link = ... dl_link = ...
+2 -2
View File
@@ -10,7 +10,7 @@ class Houdini(General):
partition = "system" partition = "system"
dl_links = { dl_links = {
"11": ["https://github.com/supremegamers/vendor_intel_proprietary_houdini/archive/81f2a51ef539a35aead396ab7fce2adf89f46e88.zip", "fbff756612b4144797fbc99eadcb6653"], "11": ["https://github.com/supremegamers/vendor_intel_proprietary_houdini/archive/81f2a51ef539a35aead396ab7fce2adf89f46e88.zip", "fbff756612b4144797fbc99eadcb6653"],
# "13": ["https://github.com/supremegamers/vendor_intel_proprietary_houdini/archive/978d8cba061a08837b7e520cd03b635af643ba08.zip", "1e139054c05034648fae58a1810573b4"] "13": ["https://github.com/supremegamers/vendor_intel_proprietary_houdini/archive/2f8f088671182e17e67321e098e8411a3972a628.zip", "37fe0899f1e4da7f9a724cca1c1ab1ea"]
} }
act_md5 = ... act_md5 = ...
dl_link = ... dl_link = ...
@@ -18,7 +18,7 @@ class Houdini(General):
extract_to = "/tmp/houdiniunpack" extract_to = "/tmp/houdiniunpack"
init_rc_component = """ init_rc_component = """
on early-init on early-init
mount -t binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc mount binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc
on property:ro.enable.native.bridge.exec=1 on property:ro.enable.native.bridge.exec=1
exec -- /system/bin/sh -c "echo ':arm_exe:M::\\\\x7f\\\\x45\\\\x4c\\\\x46\\\\x01\\\\x01\\\\x01\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x02\\\\x00\\\\x28::/system/bin/houdini:P' > /proc/sys/fs/binfmt_misc/register" exec -- /system/bin/sh -c "echo ':arm_exe:M::\\\\x7f\\\\x45\\\\x4c\\\\x46\\\\x01\\\\x01\\\\x01\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x02\\\\x00\\\\x28::/system/bin/houdini:P' > /proc/sys/fs/binfmt_misc/register"
+37 -18
View File
@@ -10,7 +10,7 @@ from tools import container
class Magisk(General): class Magisk(General):
id = "magisk delta" id = "magisk delta"
partition = "system" partition = "system"
dl_link = "https://huskydg.github.io/magisk-files/app-debug.apk" dl_link = "https://github.com/mistrmochov/magiskdeltaorig/raw/main/app-release.apk"
dl_file_name = "magisk.apk" dl_file_name = "magisk.apk"
extract_to = "/tmp/magisk_unpack" extract_to = "/tmp/magisk_unpack"
magisk_dir = os.path.join(partition, "etc", "init", "magisk") magisk_dir = os.path.join(partition, "etc", "init", "magisk")
@@ -29,30 +29,28 @@ service bootanim /system/bin/bootanimation
bootanim_component = f""" bootanim_component = f"""
on post-fs-data on post-fs-data
start logd start logd
exec u:r:su:s0 root root -- /system/etc/init/magisk/magisk{host()[1]} --auto-selinux --setup-sbin /system/etc/init/magisk exec u:r:su:s0 root root -- /system/etc/init/magisk/magiskpolicy --live --magisk
exec u:r:su:s0 root root -- /system/etc/init/magisk/magiskpolicy --live --magisk "allow * magisk_file lnk_file *" exec u:r:magisk:s0 root root -- /system/etc/init/magisk/magiskpolicy --live --magisk
mkdir /sbin/.magisk 700 exec u:r:update_engine:s0 root root -- /system/etc/init/magisk/magiskpolicy --live --magisk
mkdir /sbin/.magisk/mirror 700 mkdir /dev/magisk_iqeoVo2mDrO 700
mkdir /sbin/.magisk/block 700 exec u:r:su:s0 root root -- /system/etc/init/magisk/magisk64 --auto-selinux --setup-sbin /system/etc/init/magisk /dev/magisk_iqeoVo2mDrO
copy /system/etc/init/magisk/config /sbin/.magisk/config exec u:r:su:s0 root root -- /dev/magisk_iqeoVo2mDrO/magisk --auto-selinux --post-fs-data
rm /dev/.magisk_unblock
exec u:r:su:s0 root root -- /sbin/magisk --auto-selinux --post-fs-data
wait /dev/.magisk_unblock 40
rm /dev/.magisk_unblock
on zygote-start on nonencrypted
exec u:r:su:s0 root root -- /sbin/magisk --auto-selinux --service exec u:r:su:s0 root root -- /dev/magisk_iqeoVo2mDrO/magisk --auto-selinux --service
on property:vold.decrypt=trigger_restart_framework
exec u:r:su:s0 root root -- /dev/magisk_iqeoVo2mDrO/magisk --auto-selinux --service
on property:sys.boot_completed=1 on property:sys.boot_completed=1
mkdir /data/adb/magisk 755 mkdir /data/adb/magisk 755
exec u:r:su:s0 root root -- /sbin/magisk --auto-selinux --boot-complete exec u:r:su:s0 root root -- /dev/magisk_iqeoVo2mDrO/magisk --auto-selinux --boot-complete
exec -- /system/bin/sh -c "if [ ! -e /data/data/io.github.huskydg.magisk ] ; then pm install /system/etc/init/magisk/magisk.apk ; fi"
on property:init.svc.zygote=restarting on property:init.svc.zygote=restarting
exec u:r:su:s0 root root -- /sbin/magisk --auto-selinux --zygote-restart exec u:r:su:s0 root root -- /dev/magisk_iqeoVo2mDrO/magisk --auto-selinux --zygote-restart
on property:init.svc.zygote=stopped on property:init.svc.zygote=stopped
exec u:r:su:s0 root root -- /sbin/magisk --auto-selinux --zygote-restart exec u:r:su:s0 root root -- /dev/magisk_iqeoVo2mDrO/magisk --auto-selinux --zygote-restart
""" """
def download(self): def download(self):
@@ -66,7 +64,28 @@ on property:init.svc.zygote=stopped
Logger.info("Additional setup") Logger.info("Additional setup")
magisk_absolute_dir = os.path.join(self.copy_dir, self.magisk_dir) magisk_absolute_dir = os.path.join(self.copy_dir, self.magisk_dir)
data_dir = get_data_dir() data_dir = get_data_dir()
shutil.copytree(magisk_absolute_dir, os.path.join(data_dir, "adb", "magisk"), dirs_exist_ok=True) data_magisk_dir = os.path.join(data_dir, "adb", "magisk")
shutil.copytree(magisk_absolute_dir, data_magisk_dir, dirs_exist_ok=True)
# General.install() calls set_perm() only over self.files, which are paths
# under copy_dir (the overlay). This /data/adb copy is made here, before
# that runs, so it keeps the 0644 the binaries inherited from the apk
# extraction. A non-executable /data/adb/magisk/magisk64 makes magisk_env()
# abort at post-fs-data: root still works from the overlay copy, but Zygisk
# silently never initialises (Magisk reports "Zygisk: No" no matter what
# the zygisk setting says). Apply the same perms set_path_perm() gives
# magisk paths, to this copy too.
self.set_data_magisk_perm(data_magisk_dir)
def set_data_magisk_perm(self, data_magisk_dir):
if not os.path.isdir(data_magisk_dir):
return
os.chmod(data_magisk_dir, 0o755)
for root, dirnames, filenames in os.walk(data_magisk_dir):
for dirname in dirnames:
os.chmod(os.path.join(root, dirname), 0o755)
for filename in filenames:
os.chmod(os.path.join(root, filename), 0o755)
def copy(self): def copy(self):
magisk_absolute_dir = os.path.join(self.copy_dir, self.magisk_dir) magisk_absolute_dir = os.path.join(self.copy_dir, self.magisk_dir)
+2 -2
View File
@@ -36,11 +36,11 @@ class MicroG(General):
"6136b383153c2a6797d14fb4d7ca3f97" "6136b383153c2a6797d14fb4d7ca3f97"
], ],
"Minimal": [ "Minimal": [
"https://github.com/ayasa520/MinMicroG/releases/download/latest/MinMicroG-Minimal-2.11.1-20230429100521.zip" "https://github.com/ayasa520/MinMicroG/releases/download/latest/MinMicroG-Minimal-2.11.1-20230429100521.zip",
"afb87eb64e7749cfd72c4760d85849da" "afb87eb64e7749cfd72c4760d85849da"
], ],
"MinimalIAP": [ "MinimalIAP": [
"https://github.com/ayasa520/MinMicroG/releases/download/latest/MinMicroG-MinimalIAP-2.11.1-20230429100556.zip" "https://github.com/ayasa520/MinMicroG/releases/download/latest/MinMicroG-MinimalIAP-2.11.1-20230429100556.zip",
"cc071f4f776cbc16c4c1f707aff1f7fa" "cc071f4f776cbc16c4c1f707aff1f7fa"
] ]
} }
+40
View File
@@ -0,0 +1,40 @@
import os
import shutil
from stuff.general import General
from tools.helper import run
from tools.logger import Logger
class Mitm(General):
id = "mitm"
partition = "system"
def __init__(self, ca_cert_file: str=None) -> None:
super().__init__()
self.ca_cert_file = ca_cert_file
def download(self):
pass
def skip_extract(self):
return True
def copy(self):
file_hash = run([
'openssl', 'x509', '-noout', '-subject_hash_old', '-in',
self.ca_cert_file,
]).stdout.decode("ascii").strip()
target_dir = os.path.join(
self.copy_dir, self.partition, "etc", "security", "cacerts")
Logger.info(f"Creating directory: {target_dir}")
os.makedirs(target_dir, exist_ok=True)
target_path = os.path.join(target_dir, f'{file_hash}.0')
Logger.info(f"Copying {self.ca_cert_file} to system trust store")
Logger.info(f"Target file: {target_path}")
shutil.copyfile(self.ca_cert_file, target_path)
os.chmod(target_path, 0o644)
def install(self):
if not self.ca_cert_file:
raise ValueError(
"This command requires the --ca-cert switch and a *.pem file")
super().install()
+2 -2
View File
@@ -9,12 +9,12 @@ class Ndk(General):
partition = "system" partition = "system"
dl_links = { dl_links = {
"11": ["https://github.com/supremegamers/vendor_google_proprietary_ndk_translation-prebuilt/archive/9324a8914b649b885dad6f2bfd14a67e5d1520bf.zip", "c9572672d1045594448068079b34c350"], "11": ["https://github.com/supremegamers/vendor_google_proprietary_ndk_translation-prebuilt/archive/9324a8914b649b885dad6f2bfd14a67e5d1520bf.zip", "c9572672d1045594448068079b34c350"],
"13": ["https://github.com/supremegamers/vendor_google_proprietary_ndk_translation-prebuilt/archive/a090003c60df53a9eadb2df09bd4fd2fa86ea629.zip", "e6f0d9fc28ebc427b59a3942a9a4ffc0"] "13": ["https://github.com/supremegamers/vendor_google_proprietary_ndk_translation-prebuilt/archive/68734c52556d3d7a6db34c603dd9276915c29f2f.zip", "0b2207c490fcb400aa5c87fcf0d52d38"]
} }
dl_file_name = "libndktranslation.zip" dl_file_name = "libndktranslation.zip"
extract_to = "/tmp/libndkunpack" extract_to = "/tmp/libndkunpack"
apply_props = { apply_props = {
"ro.product.cpu.abilist": "x86_64,x86,armeabi-v7a,armeabi,arm64-v8a", "ro.product.cpu.abilist": "x86_64,x86,arm64-v8a,armeabi-v7a,armeabi",
"ro.product.cpu.abilist32": "x86,armeabi-v7a,armeabi", "ro.product.cpu.abilist32": "x86,armeabi-v7a,armeabi",
"ro.product.cpu.abilist64": "x86_64,arm64-v8a", "ro.product.cpu.abilist64": "x86_64,arm64-v8a",
"ro.dalvik.vm.native.bridge": "libndk_translation.so", "ro.dalvik.vm.native.bridge": "libndk_translation.so",
+45 -19
View File
@@ -1,7 +1,8 @@
import gzip
import os import os
import re
import shutil import shutil
from stuff.general import General from stuff.general import General
from tools.helper import backup, restore
from tools.logger import Logger from tools.logger import Logger
from tools import container from tools import container
@@ -9,37 +10,59 @@ from tools import container
class Nodataperm(General): class Nodataperm(General):
id = "nodataperm" id = "nodataperm"
dl_links = { dl_links = {
"11": ["https://github.com/ayasa520/hack_full_data_permission/archive/refs/heads/main.zip", "11": {
"eafd7b0986f3edaebaf1dd89f19d49bf"], "x86_64": [
"13": ["", ""] "https://github.com/ayasa520/hack_full_data_permission/archive/d4beab7780eb792059d33e77d865579c9ee41546.zip",
"b0e3908ffcf5df8ea62f4929aa680f1a"
],
},
"13": {
"x86_64": [
"https://github.com/ayasa520/hack_full_data_permission/archive/d4beab7780eb792059d33e77d865579c9ee41546.zip",
"b0e3908ffcf5df8ea62f4929aa680f1a"
],
},
} }
dl_file_name = "nodataperm.zip" dl_file_name = "nodataperm.zip"
extract_to = "/tmp/nodataperm" extract_to = "/tmp/nodataperm"
dl_link = ... dl_link = None
act_md5 = ... act_md5 = None
partition = "system" partition = "system"
files = [ files = [
"etc/nodataperm.sh", "etc/nodataperm.sh",
"etc/init/nodataperm.rc", "etc/init/nodataperm.rc",
"framework/services.jar" "framework/services.jar",
"framework/services.jar.prof",
"framework/services.jar.bprof",
] ]
def __init__(self, android_version="11") -> None: def __init__(self, android_version="11") -> None:
super().__init__() super().__init__()
self.dl_link = self.dl_links[android_version][0] print("ok")
self.act_md5 = self.dl_links[android_version][1] arch = self.arch[0]
if android_version not in self.dl_links:
raise KeyError(f"No download links for Android version '{android_version}'")
if arch not in self.dl_links[android_version]:
raise KeyError(f"No download links for architecture '{arch}' in Android version '{android_version}'")
self.dl_link = self.dl_links[android_version][arch][0]
self.act_md5 = self.dl_links[android_version][arch][1]
def copy(self): def copy(self):
name = re.findall(r"([a-zA-Z0-9]+)\.zip", self.dl_link)[0]
extract_path = os.path.join( extract_path = os.path.join(
self.extract_to, "hack_full_data_permission-main") self.extract_to, f"hack_full_data_permission-{name}")
if not container.use_overlayfs(): if not container.use_overlayfs():
services_jar = os.path.join( services_jar = os.path.join(
self.copy_dir, self.partition, "framework", "services.jar") self.copy_dir, self.partition, "framework", "services.jar")
gz_filename = services_jar+".gz" services_jar_prof = os.path.join(
with gzip.open(gz_filename, 'wb') as f_gz: self.copy_dir, self.partition, "framework", "services.jar.prof")
with open(services_jar, "rb") as f: services_jar_bprof = os.path.join(
f_gz.write(f.read()) self.copy_dir, self.partition, "framework", "services.jar.bprof")
Logger.info("Copying widevine library files ...") backup(services_jar)
backup(services_jar_prof)
backup(services_jar_bprof)
Logger.info(f"Copying {self.id} library files ...")
shutil.copytree(extract_path, os.path.join( shutil.copytree(extract_path, os.path.join(
self.copy_dir, self.partition), dirs_exist_ok=True) self.copy_dir, self.partition), dirs_exist_ok=True)
@@ -47,7 +70,10 @@ class Nodataperm(General):
if not container.use_overlayfs(): if not container.use_overlayfs():
services_jar = os.path.join( services_jar = os.path.join(
self.copy_dir, self.partition, "framework", "services.jar") self.copy_dir, self.partition, "framework", "services.jar")
gz_filename = services_jar+".gz" services_jar_prof = os.path.join(
with gzip.GzipFile(gz_filename) as f_gz: self.copy_dir, self.partition, "framework", "services.jar.prof")
with open(services_jar, "wb") as f: services_jar_bprof = os.path.join(
f.writelines(f_gz) self.copy_dir, self.partition, "framework", "services.jar.bprof")
restore(services_jar)
restore(services_jar_prof)
restore(services_jar_bprof)
+3 -2
View File
@@ -4,10 +4,10 @@ from stuff.general import General
class Smartdock(General): class Smartdock(General):
id = "smartdock" id = "smartdock"
dl_link = "https://f-droid.org/repo/cu.axel.smartdock_198.apk" dl_link = "https://f-droid.org/repo/cu.axel.smartdock_1130.apk"
partition = "system" partition = "system"
dl_file_name = "smartdock.apk" dl_file_name = "smartdock.apk"
act_md5 = "a8ce0bca5e1772796404602e0fa250a4" act_md5 = "6bfedb959ef5855c3782e8001cb67f86"
apply_props = { "qemu.hw.mainkeys" : "1" } apply_props = { "qemu.hw.mainkeys" : "1" }
skip_extract = True skip_extract = True
permissions = """<?xml version="1.0" encoding="utf-8"?> permissions = """<?xml version="1.0" encoding="utf-8"?>
@@ -30,6 +30,7 @@ class Smartdock(General):
<permission name="android.permission.ACCESS_SUPERUSER"/> <permission name="android.permission.ACCESS_SUPERUSER"/>
<permission name="android.permission.PACKAGE_USAGE_STATS" /> <permission name="android.permission.PACKAGE_USAGE_STATS" />
<permission name="android.permission.QUERY_ALL_PACKAGES" /> <permission name="android.permission.QUERY_ALL_PACKAGES" />
<permission name="android.permission.WRITE_SECURE_SETTINGS" />
</privapp-permissions> </privapp-permissions>
</permissions> </permissions>
""" """
+13 -2
View File
@@ -13,8 +13,8 @@ class Widevine(General):
"x86_64": { "x86_64": {
"11": ["https://github.com/supremegamers/vendor_google_proprietary_widevine-prebuilt/archive/48d1076a570837be6cdce8252d5d143363e37cc1.zip", "11": ["https://github.com/supremegamers/vendor_google_proprietary_widevine-prebuilt/archive/48d1076a570837be6cdce8252d5d143363e37cc1.zip",
"f587b8859f9071da4bca6cea1b9bed6a"], "f587b8859f9071da4bca6cea1b9bed6a"],
"13": ["https://github.com/supremegamers/vendor_google_proprietary_widevine-prebuilt/archive/a8524d608431573ef1c9313822d271f78728f9a6.zip", "13": ["https://github.com/WayDroid-ATV/vendor_google_proprietary_widevine-prebuilt/archive/679552343d8b2e8d7a19b6df61c7a03963d0c75b.zip",
"5c55df61da5c012b4e43746547ab730f"] "80ab79ea85c7b2556baedb371a54e01c"]
}, },
# "armeabi-v7a": ["https://github.com/supremegamers/vendor_google_proprietary_widevine-prebuilt/archive/a1a19361d36311bee042da8cf4ced798d2c76d98.zip", "fed6898b5cfd2a908cb134df97802554"], # "armeabi-v7a": ["https://github.com/supremegamers/vendor_google_proprietary_widevine-prebuilt/archive/a1a19361d36311bee042da8cf4ced798d2c76d98.zip", "fed6898b5cfd2a908cb134df97802554"],
"arm64-v8a": { "arm64-v8a": {
@@ -30,7 +30,10 @@ class Widevine(General):
"etc/init/*widevine.rc", "etc/init/*widevine.rc",
"etc/vintf/manifest/*widevine.xml", "etc/vintf/manifest/*widevine.xml",
"lib/libwvhidl.so", "lib/libwvhidl.so",
"lib/libwvaidl.so",
"lib/mediadrm", "lib/mediadrm",
"lib64/libwvhidl.so",
"lib64/libwvaidl.so",
"lib64/mediadrm" "lib64/mediadrm"
] ]
@@ -38,9 +41,17 @@ class Widevine(General):
super().__init__() super().__init__()
self.dl_link = self.dl_links[self.arch[0]][android_version][0] self.dl_link = self.dl_links[self.arch[0]][android_version][0]
self.act_md5 = self.dl_links[self.arch[0]][android_version][1] self.act_md5 = self.dl_links[self.arch[0]][android_version][1]
self.android_version = android_version
self.libdir = "lib64" if self.arch[1] == 64 else "lib"
def copy(self): def copy(self):
name = re.findall("([a-zA-Z0-9]+)\.zip", self.dl_link)[0] name = re.findall("([a-zA-Z0-9]+)\.zip", self.dl_link)[0]
Logger.info("Copying widevine library files ...") Logger.info("Copying widevine library files ...")
shutil.copytree(os.path.join(self.extract_to, "vendor_google_proprietary_widevine-prebuilt-"+name, shutil.copytree(os.path.join(self.extract_to, "vendor_google_proprietary_widevine-prebuilt-"+name,
"prebuilts"), os.path.join(self.copy_dir, self.partition), dirs_exist_ok=True) "prebuilts"), os.path.join(self.copy_dir, self.partition), dirs_exist_ok=True)
if self.android_version == "13":
try:
os.symlink("libprotobuf-cpp-lite-3.9.1.so",
os.path.join(self.copy_dir, self.partition, self.libdir, "libprotobuf-cpp-lite.so"))
except FileExistsError:
pass
+179
View File
@@ -0,0 +1,179 @@
#!/usr/bin/env python3
"""Regression test for Magisk.setup() permissions on the /data/adb/magisk copy.
install() runs copy() -> extra1() -> set_perm(). set_perm() only walks self.files,
which are paths under copy_dir (the overlay), so the copy that setup() makes into
<data>/adb/magisk keeps the 0644 the binaries inherit from the apk extraction.
A non-executable /data/adb/magisk/magisk64 makes magisk_env() abort at post-fs-data.
Root still works (it runs from the overlay copy), but Zygisk never initialises and
the Magisk app reports "Zygisk: No" with no error explaining why.
Runs as an ordinary user, needs no Waydroid install and no extra dependencies:
python3 tests/test_magisk_setup_perms.py
"""
import os
import shutil
import stat
import sys
import tempfile
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import stuff.magisk as magisk_module
from stuff.magisk import Magisk
MAGISK_BINARIES = [
"magisk64",
"magiskinit",
"magiskboot",
"magiskpolicy",
"busybox",
"util_functions.sh",
]
def make_overlay(base):
"""Mimic the tree copy() leaves behind: binaries written 0644 by shutil.copyfile."""
magisk_dir = os.path.join(base, "system", "etc", "init", "magisk")
os.makedirs(os.path.join(magisk_dir, "chromeos"), exist_ok=True)
for name in MAGISK_BINARIES:
path = os.path.join(magisk_dir, name)
with open(path, "wb") as f:
f.write(b"\x7fELF placeholder")
os.chmod(path, 0o644)
nested = os.path.join(magisk_dir, "chromeos", "futility")
with open(nested, "wb") as f:
f.write(b"placeholder")
os.chmod(nested, 0o644)
return magisk_dir
def file_modes(root):
modes = {}
for dirpath, _dirnames, filenames in os.walk(root):
for name in filenames:
path = os.path.join(dirpath, name)
modes[os.path.relpath(path, root)] = stat.S_IMODE(os.stat(path).st_mode)
return modes
def test_plain_copytree_loses_exec_bit():
"""Document the original behaviour: a bare copytree leaves the binaries 0644."""
base = tempfile.mkdtemp()
try:
src = make_overlay(base)
dst = os.path.join(base, "data", "adb", "magisk")
os.makedirs(os.path.dirname(dst), exist_ok=True)
shutil.copytree(src, dst, dirs_exist_ok=True)
modes = file_modes(dst)
assert modes["magisk64"] == 0o644, (
"expected the pre-fix behaviour to reproduce, got %o" % modes["magisk64"]
)
finally:
shutil.rmtree(base, ignore_errors=True)
def test_setup_makes_data_copy_executable():
"""setup() must leave every file and dir in <data>/adb/magisk executable."""
base = tempfile.mkdtemp()
try:
make_overlay(base)
data_dir = os.path.join(base, "data")
os.makedirs(data_dir, exist_ok=True)
original_get_data_dir = magisk_module.get_data_dir
original_info = magisk_module.Logger.info
magisk_module.get_data_dir = lambda: data_dir
magisk_module.Logger.info = lambda *a, **k: None
class StubMagisk(Magisk):
@property
def copy_dir(self):
return base
try:
StubMagisk().setup()
finally:
magisk_module.get_data_dir = original_get_data_dir
magisk_module.Logger.info = original_info
dst = os.path.join(data_dir, "adb", "magisk")
modes = file_modes(dst)
assert modes, "setup() copied nothing"
not_executable = {n: oct(m) for n, m in modes.items() if m != 0o755}
assert not not_executable, "files left non-0755: %s" % not_executable
assert stat.S_IMODE(os.stat(dst).st_mode) == 0o755
nested = os.path.join(dst, "chromeos")
assert stat.S_IMODE(os.stat(nested).st_mode) == 0o755, "nested dir not fixed"
finally:
shutil.rmtree(base, ignore_errors=True)
def test_setup_is_idempotent():
base = tempfile.mkdtemp()
try:
make_overlay(base)
data_dir = os.path.join(base, "data")
os.makedirs(data_dir, exist_ok=True)
original_get_data_dir = magisk_module.get_data_dir
original_info = magisk_module.Logger.info
magisk_module.get_data_dir = lambda: data_dir
magisk_module.Logger.info = lambda *a, **k: None
class StubMagisk(Magisk):
@property
def copy_dir(self):
return base
try:
StubMagisk().setup()
StubMagisk().setup()
finally:
magisk_module.get_data_dir = original_get_data_dir
magisk_module.Logger.info = original_info
dst = os.path.join(data_dir, "adb", "magisk")
assert all(m == 0o755 for m in file_modes(dst).values())
finally:
shutil.rmtree(base, ignore_errors=True)
def test_perm_helper_tolerates_missing_dir():
Magisk().set_data_magisk_perm(os.path.join(tempfile.gettempdir(), "definitely-not-here"))
def main():
tests = [
test_plain_copytree_loses_exec_bit,
test_setup_makes_data_copy_executable,
test_setup_is_idempotent,
test_perm_helper_tolerates_missing_dir,
]
failed = 0
for test in tests:
try:
test()
except AssertionError as exc:
failed += 1
print("FAIL %s: %s" % (test.__name__, exc))
except Exception as exc: # noqa: BLE001 - surface anything unexpected
failed += 1
print("ERROR %s: %r" % (test.__name__, exc))
else:
print("ok %s" % test.__name__)
if failed:
print("\n%d test(s) failed" % failed)
return 1
print("\nall %d tests passed" % len(tests))
return 0
if __name__ == "__main__":
sys.exit(main())
+13
View File
@@ -1,3 +1,4 @@
import gzip
import os import os
import re import re
import platform import platform
@@ -131,3 +132,15 @@ def check_root():
if os.geteuid() != 0: if os.geteuid() != 0:
Logger.error("This script must be run as root. Aborting.") Logger.error("This script must be run as root. Aborting.")
sys.exit(1) sys.exit(1)
def backup(path):
gz_filename = path+".gz"
with gzip.open(gz_filename, 'wb') as f_gz:
with open(path, "rb") as f:
f_gz.write(f.read())
def restore(path):
gz_filename = path+".gz"
with gzip.GzipFile(gz_filename) as f_gz:
with open(path, "wb") as f:
f.writelines(f_gz)