From b1c88db1ce72e11ba44add0f481b6786c4ce17d2 Mon Sep 17 00:00:00 2001 From: Claudia Date: Mon, 4 Sep 2023 15:36:25 +0200 Subject: [PATCH] Feature: install self-signed cacert to trust store MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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/ --- README.md | 8 +++++++- main.py | 14 ++++++++++++-- stuff/mitm.py | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 stuff/mitm.py diff --git a/README.md b/README.md index 9d586de..7795c7f 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ cd waydroid_script python3 -m venv venv venv/bin/pip install -r requirements.txt # install something -sudo venv/bin/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 sudo venv/bin/python3 main.py uninstall {gapps, magisk, libndk, libhoudini, nodataperm, smartdock, microg} # get Android device ID @@ -122,6 +122,12 @@ Open terminal and switch to directory where "main.py" is located then run: 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) diff --git a/main.py b/main.py index 79889fe..af90935 100755 --- a/main.py +++ b/main.py @@ -12,6 +12,7 @@ from stuff.hidestatusbar import HideStatusBar from stuff.houdini import Houdini from stuff.magisk import Magisk from stuff.microg import MicroG +from stuff.mitm import Mitm from stuff.ndk import Ndk from stuff.nodataperm import Nodataperm from stuff.smartdock import Smartdock @@ -83,6 +84,8 @@ def install_app(args): install_list.append(Smartdock()) if "microg" in app: install_list.append(MicroG(args.android_version, args.microg_variant)) + if "mitm" in app: + install_list.append(Mitm(args.ca_cert_file)) if not container.use_overlayfs(): copy_dir = "/tmp/waydroid" @@ -130,6 +133,8 @@ def remove_app(args): remove_list.append(Smartdock()) if "microg" in app: remove_list.append(MicroG(args.android_version, args.microg_variant)) + if "mitm" in app: + remove_list.append(Mitm()) if "nodataperm" in app: remove_list.append(Nodataperm(args.android_version)) if "hidestatusbar" in app: @@ -286,8 +291,8 @@ def main(): 'certified', help='Get device ID to obtain Play Store certification') certified.set_defaults(func=get_certified) - install_choices = ["gapps", "microg", "libndk", - "libhoudini", "magisk", "smartdock", "widevine"] + install_choices = ["gapps", "microg", "libndk", "libhoudini", + "magisk", "mitm", "smartdock", "widevine"] hack_choices = ["nodataperm", "hidestatusbar"] micrg_variants = ["Standard", "NoGoolag", "UNLP", "Minimal", "MinimalIAP"] remove_choices = install_choices @@ -305,6 +310,7 @@ microg: Add microG, Aurora Store and Aurora Droid to WayDriod libndk: Add libndk arm translation, better for AMD CPUs libhoudini: Add libhoudini arm translation, better for Intel CPUs 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 widevine: Add support for widevine DRM L3 """ @@ -313,6 +319,10 @@ widevine: Add support for widevine DRM L3 'install', formatter_class=argparse.RawTextHelpFormatter, help='Install an app') install_parser.add_argument( **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.set_defaults(func=install_app) # remove and its aliases diff --git a/stuff/mitm.py b/stuff/mitm.py new file mode 100644 index 0000000..8468a9a --- /dev/null +++ b/stuff/mitm.py @@ -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()