Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/bash
- set -euo pipefail
- base_dir="$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" && pwd -P)"
- cd "$base_dir"
- #region functions
- #region init
- function add_user_local_bin_to_path() {
- local expected="$HOME/.local/bin"
- local path
- path=$(echo "$PATH" | tr ':' $'\n' | sed -E 's#/+$##g')
- if ! echo "$path" | grep -q "$expected"; then
- PATH="$expected:$(echo "$path" | tr $'\n' ':')"
- fi
- }
- function install_bootstrap_ubuntu() {
- local packages=()
- curl --version >/dev/null 2>&1 || packages+=( curl )
- git --version >/dev/null 2>&1 || packages+=( git )
- if [[ ${#packages[@]} -gt 0 ]]; then
- echo "installing packages: ${packages[*]} .."
- sudo apt install "${packages[@]}"
- fi
- }
- function is_python_min_version_found() {
- local pythonVersion
- pythonVersion=$(python3 --version 2>/dev/null | awk '{ print $2 }' || echo "0.0.0")
- minVer=$(printf "$pythonVersion\n3.7.0" | sort --version-sort | head -n1)
- if [[ "$minVer" == "3.7.0" ]]; then
- return 0
- fi
- return 1
- }
- function install_python_macos() {
- if ! is_python_min_version_found; then
- if ! which brew >/dev/null 2>&1; then
- echo "error: brew not found - download from https://brew.sh/" >&2
- exit 1
- fi
- echo "installing python3 .." >&2
- HOMEBREW_NO_AUTO_UPDATE=1 brew install --quiet python3
- fi
- }
- function install_python_ubuntu() {
- local packages=()
- is_python_min_version_found || packages+=( python3.10 )
- dpkg -l | awk '$2=="python3.10-venv"&&$1=="ii"' | grep -q . \
- || packages+=( python3.10-venv )
- pip3 --version >/dev/null 2>&1 || packages+=( python3-pip )
- if [[ ${#packages[@]} -gt 0 ]]; then
- echo "installing python3 packages: ${packages[*]} .."
- sudo apt install "${packages[@]}"
- fi
- }
- #endregion
- #region sdk
- function get_platform_os() {
- case "$(uname -s | tr '[:upper:]' '[:lower:]')" in
- darwin )
- echo "mac"
- ;;
- linux )
- echo "linux"
- ;;
- * )
- echo "error: unsupported platform os '$(uname -s)' expected 'Darwin' or 'Linux'" >&2
- exit 1
- esac
- }
- function get_sdk_home() {
- local android_home=${ANDROID_HOME:-${ANDROID_SDK_ROOT:-}}
- if [[ "$android_home" == "" ]]; then
- case $(get_platform_os) in
- mac )
- echo "$HOME/Library/Android/sdk"
- ;;
- linux )
- echo "$HOME/Android/Sdk"
- ;;
- * )
- echo "error: unsupported platform" >&2
- exit 1
- esac
- fi
- echo "$android_home"
- }
- function ensure_android_home_exists() {
- if [[ ! -d "$android_home" ]]; then
- echo "creating android home directory: $android_home" >&2
- mkdir -p "$android_home"
- fi
- }
- function get_cmdline_tools_filename() {
- local platform=$(get_platform_os)
- local filename=$( \
- curl -fsSL https://developer.android.com/studio \
- | sed -nE "s/.*(commandlinetools-$platform-[A-Za-z0-9._-]*_latest\.zip).*/\1/p" \
- | head -n1 \
- )
- if [[ "$filename" == "" ]]; then
- echo "error: could not detect android commandlinetools filename" >&2
- exit 1
- fi
- echo "$filename"
- }
- function get_cmdline_tools_url() {
- local filename=$(get_cmdline_tools_filename)
- echo "https://dl.google.com/android/repository/$filename"
- }
- function ensure_cmdline_tools_exists() {
- local sdkmanager_path="$cmdline_tools_path/latest/bin/sdkmanager"
- if [[ ! -f "$sdkmanager_path" ]]; then
- echo "fetching cmdline-tools .." >&2
- local url=$(get_cmdline_tools_url)
- curl -fsSL "$url" -o cmdline-tools.zip
- unzip cmdline-tools.zip -d cmdline-tools
- rm cmdline-tools.zip
- cd cmdline-tools
- mv cmdline-tools latest
- cd - >/dev/null
- fi
- if ! which sdkmanager >/dev/null 2>&1; then
- PATH="$cmdline_tools_path/latest/bin:$PATH"
- fi
- }
- function ensure_emulator_exists() {
- local emulator_version=$(sdkmanager --list_installed | awk '$1 == "emulator" { print $2 }')
- if [[ "$emulator_version" == "" ]]; then
- echo "fetching emulator .." >&2
- echo y | sdkmanager --install emulator
- fi
- if ! which emulator >/dev/null 2>&1; then
- PATH="$emulator_path:$PATH"
- fi
- }
- function ensure_platform_tools_exists() {
- local platform_tools_version=$(sdkmanager --list_installed | awk '$1 == "platform-tools" { print $2 }')
- if [[ "$platform_tools_version" == "" ]]; then
- echo "fetching platform-tools .." >&2
- echo y | sdkmanager --install platform-tools
- fi
- if ! which adb >/dev/null 2>&1; then
- PATH="$platform_tools_path:$PATH"
- fi
- }
- function ensure_platforms_exists() {
- if [[ ! -d platforms ]]; then
- echo "creating directory platforms .." >&2
- mkdir platforms
- fi
- }
- function get_platform_arch() {
- case "$(uname -m)" in
- x86_64 )
- echo "x86_64"
- ;;
- arm64 )
- echo "arm64-v8a"
- ;;
- * )
- echo "error: unsupported platform arch '$(uname -m)' expected 'x86_64' or 'arm64'" >&2
- exit 1
- esac
- }
- function setup_android_sdk() {
- android_home=$(get_sdk_home)
- cmdline_tools_path="$android_home/cmdline-tools"
- emulator_path="$android_home/emulator"
- platform_tools_path="$android_home/platform-tools"
- if [[ "${ANDROID_HOME:-}" == "" ]]; then
- export ANDROID_HOME=$android_home
- fi
- if [[ "${ANDROID_SDK_ROOT:-}" == "" ]]; then
- export ANDROID_SDK_ROOT=$android_home
- fi
- ensure_android_home_exists
- cd "$android_home"
- ensure_cmdline_tools_exists
- ensure_emulator_exists
- ensure_platform_tools_exists
- ensure_platforms_exists
- cd - >/dev/null
- }
- #endregion
- #region submodules
- function setup_pywidevine() {
- cd lib
- if [[ ! -f pywidevine/.git/config ]]; then
- echo "cloning pywidevine .."
- git clone --quiet https://github.com/rlaphoenix/pywidevine.git
- fi
- cd pywidevine
- poetry --version >/dev/null 2>&1 || pip3 install poetry
- poetry config virtualenvs.in-project true
- poetry install -E serve
- cd "$base_dir"
- }
- function setup_dumper() {
- cd lib
- if [[ ! -f dumper/.git/config ]]; then
- echo "cloning dumper .."
- git clone --quiet https://github.com/Diazole/dumper.git
- fi
- cd dumper
- echo "installing dumper dependencies .."
- python3 -m venv venv
- . venv/bin/activate
- pip3 install -r requirements.txt
- deactivate
- cd "$base_dir"
- }
- function install_submodules() {
- if [[ ! -d "$base_dir/lib" ]]; then
- mkdir "$base_dir/lib"
- fi
- setup_pywidevine
- setup_dumper
- }
- #endregion
- #region dumper
- function ensure_frida_server_exists() {
- case "$(uname -m)" in
- x86_64 | arm64 )
- frida_bin="frida-server-16.0.8-android-$(uname -m)"
- ;;
- * )
- echo "error: unsupported platform arch '$(uname -m)' expected 'x86_64' or 'arm64'" >&2
- exit 1
- esac
- local frida_url="https://github.com/frida/frida/releases/download/16.0.8/$frida_bin.xz"
- if [[ ! -f "lib/$frida_bin" ]]; then
- echo "fetching $frida_bin .."
- curl -fsSL -o- "$frida_url" | xz -d >"lib/$frida_bin"
- chmod +x "lib/$frida_bin"
- fi
- }
- function set_android_versions() {
- case "${1:-9}" in
- 9 )
- api_version="28"
- cdm_version="14.0.0"
- ;;
- 10 )
- api_version="29"
- cdm_version="15.0.0"
- ;;
- * )
- echo "error: android version must be 9 or 10" >&2
- exit 1
- esac
- }
- function set_avd_vars() {
- avd_package="system-images;android-$api_version;default;$(get_platform_arch)"
- avd_name="Pixel_6_API_$api_version"
- avd_device="pixel_6"
- }
- function ensure_default_package_exists() {
- local package_version=$(sdkmanager --list_installed | awk '$1 == "'"$avd_package"'" { print $2 }')
- if [[ "$package_version" == "" ]]; then
- echo "fetching $avd_package .." >&2
- echo y | sdkmanager --install "$avd_package"
- fi
- }
- function dumper_exit_handler() {
- if [[ ${dump_keys_pid:-} != "" ]]; then
- echo "exiting dumper .." >&2
- kill "$dump_keys_pid" >/dev/null 2>&1 || true
- fi
- if [[ ${emulator_pid:-} != "" ]]; then
- echo "exiting emulator .." >&2
- kill "$emulator_pid" >/dev/null 2>&1 || true
- sleep 2
- fi
- echo "removing avd $avd_name .." >&2
- avdmanager delete avd --name "$avd_name" >/dev/null 2>&1 || true
- }
- function create_avd() {
- echo "creating device $avd_name .." >&2
- avdmanager create avd --device "$avd_device" --name "$avd_name" --package "$avd_package" --sdcard 512M
- ANDROID_EMULATOR_WAIT_TIME_BEFORE_KILL=0 \
- emulator -no-audio -no-boot-anim -no-snapshot-save -no-window -avd "$avd_name" >/dev/null &
- emulator_pid=$!
- }
- function copy_frida_server() {
- echo "copying $frida_bin .." >&2
- while true; do
- if adb push "lib/$frida_bin" /sdcard >/dev/null 2>&1; then
- break
- fi
- sleep 1
- done
- }
- function start_frida_server() {
- echo "starting frida server .." >&2
- sleep 2
- adb shell su 0 sh "-c 'mv /sdcard/$frida_bin /data/local/tmp/ && cd /data/local/tmp && chmod +x $frida_bin && ./$frida_bin'" &
- sleep 2
- }
- function start_dumper() {
- echo "starting dumper .." >&2
- cd lib/dumper
- . venv/bin/activate
- python3 dump_keys.py --cdm-version "$cdm_version" &
- dump_keys_pid=$!
- deactivate || true
- sleep 2
- cd - >/dev/null
- }
- function launch_drm_url() {
- echo "launching bitmovin .." >&2
- adb shell am start -a android.intent.action.VIEW -d https://bitmovin.com/demos/drm
- }
- function wait_for_dumper() {
- echo "waiting for key dump .." >&2
- if [[ ! -d lib/dumper/key_dumps ]]; then
- mkdir -p lib/dumper/key_dumps
- fi
- while true; do
- key=$(find lib/dumper/key_dumps -type f -name private_key.pem -newermt '-10 seconds' | head -n1)
- if [[ "$key" != "" ]]; then
- echo "success! found key at file://$PWD/$key" >&2
- break
- fi
- sleep 2
- done
- }
- function create_wvd() {
- echo "creating wvd file .." >&2
- local key_dir="$base_dir/$(dirname "$key")"
- local tmp_dir=$(mktemp -d)
- cd lib/pywidevine
- poetry run pywidevine create-device \
- --type ANDROID --level 3 \
- --key "$key_dir/private_key.pem" \
- --client_id "$key_dir/client_id.bin" \
- --output "$tmp_dir"
- cd - >/dev/null
- local wvd_file=$(ls -1 "$tmp_dir"/*.wvd)
- if [[ "$wvd_file" == "" ]]; then
- echo "error: could not create wvd" >&2
- exit 1
- fi
- local new_wvd_name="$(basename "$wvd_file" | sed 's/unknown_//' | sed 's/sdk_built_for_//')"
- if [[ ! -d "$base_dir/devices" ]]; then
- mkdir "$base_dir/devices"
- fi
- mv "$wvd_file" "$base_dir/devices/$new_wvd_name"
- echo "success: created device $new_wvd_name"
- }
- function dump_keys() {
- ensure_frida_server_exists
- set_android_versions "$@"
- set_avd_vars
- ensure_default_package_exists
- trap dumper_exit_handler exit
- create_avd
- copy_frida_server
- start_frida_server
- start_dumper
- launch_drm_url
- wait_for_dumper
- create_wvd
- }
- #endregion
- function error_reporter() {
- echo -e "\n\033[91merror: setup failed with status $? at line $1:\033[0m" >&2
- echo "" >&2
- awk 'NR>L-3 && NR<L+2 { printf "%s%-5d %s%s\n",(NR==L?"\033[91m> ":"\033[90m "),NR,$0,"\033[0m" }' "L=$1" "$0" >&2
- }
- #endregion
- trap 'error_reporter $LINENO' ERR
- case "$(uname -s)" in
- Darwin )
- echo "running setup for macOS .."
- add_user_local_bin_to_path
- install_python_macos
- install_submodules
- ;;
- Linux )
- [[ ! -f /etc/os-release ]] || . /etc/os-release
- if [[ "${ID:-}" != "ubuntu" ]]; then
- echo "error: unsupported distro" >&2
- exit 1
- fi
- echo "running setup for Ubuntu .."
- export PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring
- add_user_local_bin_to_path
- install_bootstrap_ubuntu
- install_python_ubuntu
- install_submodules
- unset PYTHON_KEYRING_BACKEND
- ;;
- * )
- echo "error: unsupported OS $(uname -s)" >&2
- exit 1
- esac
- echo "configuring the environment .." >&2
- setup_android_sdk
- echo "starting dumper .." >&2
- dump_keys "$@"
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement