Created
May 9, 2019 11:50
-
-
Save DayS/1c7bcf7ee943381f44138a7773af893f to your computer and use it in GitHub Desktop.
apk-debuggable
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
function usage(){ | |
printf "Make APK debuggable.\n" | |
printf "Usage: $0 [options]\n" | |
printf "\t-f,--file <path> : Direct path to an APK to make debuggable\n" | |
printf "\t-i,--id <package_name> : Identifier of an APK to pull from device\n" | |
} | |
if [ $# -eq 0 ]; then | |
usage | |
fi | |
# Declare alias for sed to make it compatible in both Mac and Unix OS | |
darwin=false; | |
case "`uname`" in | |
Darwin*) darwin=true ;; | |
esac | |
if "$darwin"; then | |
alias sed_regexp="sed -E" | |
else | |
alias sed_regexp="sed -r -e" | |
fi | |
# Retrieve zipalign binary from Android SDK | |
if [ -z "$ANDROID_HOME" ]; then | |
echo "You must set a ANDROID_HOME environment variable referencing Android SDK folder" | |
exit 1; | |
fi | |
ANDROID_BUILD_TOOLS_VERSION=`ls $ANDROID_HOME/build-tools | tail -1` | |
ZIPALING_PATH="$ANDROID_HOME/build-tools/$ANDROID_BUILD_TOOLS_VERSION/zipalign" | |
function pullFromDevice() { | |
APK_ID="$1" | |
echo ">> Search an APK on device matching id $APK_ID" | |
APK_MATCHES=`adb shell pm list packages -f | grep "$APK_ID"` | |
if [ `echo "$APK_MATCHES" | wc -l` -gt 1 ]; then | |
echo "Too many results:" | |
echo "$APK_MATCHES" | |
exit 1; | |
fi | |
APK_DEVICE_PATH=`echo "$APK_MATCHES" | sed_regexp 's/^package:(.+\.apk).*/\1/'` | |
APK_DEVICE_ID=`echo "$APK_MATCHES" | sed_regexp 's/.*=([^=]+)$/\1/'` | |
echo ">>> Found APK $APK_DEVICE_ID at $APK_DEVICE_PATH" | |
APK_LOCAL_PATH="$APK_DEVICE_ID.apk" | |
echo ">> Pulling APK to $APK_LOCAL_PATH" | |
adb pull "$APK_DEVICE_PATH" "$APK_LOCAL_PATH" | |
if [ $? -ne 0 ]; then | |
echo "ERROR while pulling APK" | |
exit 1 | |
fi | |
} | |
function makeDebuggable() { | |
APK_INPUT_PATH="$1" | |
APK_RECOMPILED_PATH=`echo "$APK_INPUT_PATH" | sed 's/\.apk/.debuggable.apk/'` | |
APK_ALIGNED_PATH=`echo "$APK_RECOMPILED_PATH" | sed 's/\.apk/.aligned.apk/'` | |
APK_DECOMPILE_PATH="$APK_INPUT_PATH.out" | |
echo ">> Decompiling APK from $APK_INPUT_PATH" | |
apktool d -f -o "$APK_DECOMPILE_PATH" "$APK_INPUT_PATH" | |
if [ $? -ne 0 ]; then | |
echo "ERROR while decompiling APK" | |
exit 1 | |
fi | |
allowUserCertificates "$APK_DECOMPILE_PATH" | |
echo ">> Recompiling APK to $APK_RECOMPILED_PATH" | |
apktool b --debug --no-crunch -o "$APK_RECOMPILED_PATH" "$APK_DECOMPILE_PATH" | |
if [ $? -ne 0 ]; then | |
echo "ERROR while recompiling APK" | |
echo "Try again after running : apktool empty-framework-dir --force" | |
exit 1 | |
fi | |
echo ">> Signing APK" | |
CERT_PATH="$APK_DECOMPILE_PATH/resign.keystore" | |
CERT_ALIAS="alias_name" | |
CERT_PASS="recompiled" | |
if [ ! -f "$CERT_PATH" ]; then | |
echo ">>> Generating certificate" | |
keytool -genkey -v -keystore "$CERT_PATH" -alias "$CERT_ALIAS" -keyalg RSA -keysize 2048 -validity 10000 -dname "CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown" -storepass "$CERT_PASS" -keypass "$CERT_PASS" | |
if [ $? -ne 0 ]; then | |
echo "ERROR while generating certificate" | |
exit 1 | |
fi | |
fi | |
echo ">>> Signing APK with certificate" | |
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore "$CERT_PATH" -storepass "$CERT_PASS" -keypass "$CERT_PASS" "$APK_RECOMPILED_PATH" "$CERT_ALIAS" | |
echo ">>> Aligning APK" | |
$ZIPALING_PATH -f -v 4 "$APK_RECOMPILED_PATH" "$APK_ALIGNED_PATH" | |
if [ $? -ne 0 ]; then | |
echo "ERROR while aligning APK" | |
exit 1 | |
fi | |
rm -f "$APK_RECOMPILED_PATH" | |
echo ">> Done. Install apk with : adb install -f $APK_ALIGNED_PATH" | |
} | |
function allowUserCertificates() { | |
APK_DECOMPILED_PATH="$1" | |
MANIFEST_FILE="$APK_DECOMPILED_PATH/AndroidManifest.xml" | |
echo ">> Allowing User's SSL certificates" | |
mkdir -p "$APK_DECOMPILED_PATH/res/xml" | |
EXISTING_NETWORK_SECURITY_CONFIG=`grep -E 'android:networkSecurityConfig="@xml/([a-zA-Z0-9_]+)"' -o "$MANIFEST_FILE" | sed -E 's#.*@xml/([a-zA-Z0-9_]+).*#\1#'` | |
if [ ! -z "$EXISTING_NETWORK_SECURITY_CONFIG" ]; then | |
NETWORK_SECURITY_CONFIG_FILE="$APK_DECOMPILED_PATH/res/xml/$EXISTING_NETWORK_SECURITY_CONFIG.xml" | |
echo ">>> Found existing and used network security file : $NETWORK_SECURITY_CONFIG_FILE" | |
EXISTING_DEBUG_NODE=`grep "<debug-overrides>" "$NETWORK_SECURITY_CONFIG_FILE"` | |
if [ ! -z "$EXISTING_DEBUG_NODE" ]; then | |
echo ">>> Found debug-overrides XML tag" | |
# Because we're making a replacement on multiline, we can't use 'sed' command | |
mv "$NETWORK_SECURITY_CONFIG_FILE" "$NETWORK_SECURITY_CONFIG_FILE.bck" | |
cat "$NETWORK_SECURITY_CONFIG_FILE.bck" | tr -d '\n' | sed_regexp -e $'s#(</trust-anchors>[\s\t]*</debug-overrides>)#<certificates src="user" />\\1#' > "$NETWORK_SECURITY_CONFIG_FILE" | |
rm "$NETWORK_SECURITY_CONFIG_FILE.bck" | |
else | |
sed_regexp -i '' -e 's#(</network-security-config>)#<debug-overrides><trust-anchors><certificates src=\"user\" /></trust-anchors></debug-overrides>\1#' "$NETWORK_SECURITY_CONFIG_FILE" | |
fi | |
else | |
NETWORK_SECURITY_CONFIG_FILE="$APK_DECOMPILED_PATH/res/xml/network_security_config.xml" | |
echo ">>> Creating network security file : $NETWORK_SECURITY_CONFIG_FILE" | |
echo "<network-security-config> | |
<debug-overrides><trust-anchors><certificates src=\"user\" /></trust-anchors></debug-overrides> | |
</network-security-config>" > "$NETWORK_SECURITY_CONFIG_FILE" | |
sed_regexp -i '' -e 's#(<application)#\1 android:networkSecurityConfig="@xml/network_security_config"#' "$MANIFEST_FILE" | |
fi | |
} | |
while [[ "$#" -gt 0 ]]; do case $1 in | |
-f|--file) | |
makeDebuggable $2 | |
shift;; | |
-i|--id) | |
pullFromDevice $2 | |
makeDebuggable $APK_LOCAL_PATH | |
shift;; | |
*) "Echo unknown parameter $1"; exit 1;; | |
esac; shift; done | |
exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment