Skip to content

Instantly share code, notes, and snippets.

@incogbyte
Last active August 25, 2025 14:44
Show Gist options
  • Select an option

  • Save incogbyte/a3b7e86f512fa438b5c288d0bad57c4c to your computer and use it in GitHub Desktop.

Select an option

Save incogbyte/a3b7e86f512fa438b5c288d0bad57c4c to your computer and use it in GitHub Desktop.
APK Dumper and Automation some
#!/bin/bash
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
WORK_DIR="./apk_extractor_temp"
OUTPUT_DIR="./ExtractedAPKs"
check_adb() {
if ! command -v adb &> /dev/null; then
echo -e "${RED}[ERROR] ADB not found. Please install ADB.${NC}"
exit 1
fi
if ! adb devices | grep -q "device$"; then
echo -e "${RED}[ERROR] No Android device connected.${NC}"
echo -e "${YELLOW}Connect a device and make sure USB debugging is enabled.${NC}"
exit 1
fi
echo -e "${GREEN}[OK] Device connected via ADB${NC}"
}
cleanup() {
echo -e "${YELLOW}[INFO] Cleaning temporary files...${NC}"
rm -rf "$WORK_DIR"
}
setup_directories() {
echo -e "${BLUE}[INFO] Setting up directories...${NC}"
mkdir -p "$WORK_DIR"
mkdir -p "$OUTPUT_DIR"
}
list_installed_apps() {
echo -e "${GREEN}=== INSTALLED APPS ON DEVICE ===${NC}"
echo ""
echo -e "${YELLOW}[INFO] Getting application list...${NC}"
packages=$(adb shell pm list packages -3 2>/dev/null | sed 's/package://g' | sort)
if [ -z "$packages" ]; then
packages=$(adb shell pm list packages 2>/dev/null | sed 's/package://g' | sort)
fi
i=1
echo ""
for package in $packages; do
printf "${GREEN}%3d.${NC} %s\n" "$i" "$package"
i=$((i+1))
done
total_apps=$((i-1))
echo ""
echo -e "${BLUE}Total apps: $total_apps${NC}"
echo "$packages" > "$WORK_DIR/packages.txt"
}
get_user_choice() {
echo ""
echo -e "${YELLOW}Enter the number of the app you want to extract (1-$total_apps):${NC}"
read -r choice
if ! [[ "$choice" =~ ^[0-9]+$ ]]; then
echo -e "${RED}[ERROR] Please enter a valid number${NC}"
exit 1
fi
if [ "$choice" -lt 1 ] || [ "$choice" -gt "$total_apps" ]; then
echo -e "${RED}[ERROR] Number out of range (1-$total_apps)${NC}"
exit 1
fi
SELECTED_PACKAGE=$(sed -n "${choice}p" "$WORK_DIR/packages.txt")
if [ -z "$SELECTED_PACKAGE" ]; then
echo -e "${RED}[ERROR] Could not identify the package${NC}"
exit 1
fi
echo -e "${GREEN}[INFO] Selected app: $SELECTED_PACKAGE${NC}"
}
get_app_info() {
echo -e "${BLUE}[INFO] Getting app information...${NC}"
APK_PATHS=$(adb shell pm path "$SELECTED_PACKAGE" 2>/dev/null | sed 's/package://g')
if [ -z "$APK_PATHS" ]; then
echo -e "${RED}[ERROR] Could not find the app's APKs${NC}"
exit 1
fi
BASE_APK=$(echo "$APK_PATHS" | grep -E "base\.apk|^[^:]*\.apk$" | head -1)
if [ -z "$BASE_APK" ]; then
BASE_APK=$(echo "$APK_PATHS" | head -1)
fi
echo -e "${GREEN}[OK] Base APK found${NC}"
VERSION=$(adb shell dumpsys package "$SELECTED_PACKAGE" | grep versionName | head -1 | sed 's/.*versionName=//' | awk '{print $1}')
if [ -z "$VERSION" ]; then
VERSION="unknown"
fi
echo -e "${BLUE}[INFO] Version: $VERSION${NC}"
SPLIT_COUNT=$(echo "$APK_PATHS" | wc -l)
echo -e "${BLUE}[INFO] Total APKs (base + splits): $SPLIT_COUNT${NC}"
echo "$APK_PATHS" > "$WORK_DIR/apk_paths.txt"
}
extract_apks_from_device() {
echo -e "${YELLOW}[INFO] Extracting APKs from device...${NC}"
APP_WORK_DIR="$(pwd)/$WORK_DIR/$SELECTED_PACKAGE"
mkdir -p "$APP_WORK_DIR"
i=1
while IFS= read -r apk_path; do
if [ -n "$apk_path" ]; then
if echo "$apk_path" | grep -q "base.apk"; then
output_name="base.apk"
elif echo "$apk_path" | grep -q "split_"; then
output_name=$(basename "$apk_path")
else
output_name="apk_$i.apk"
fi
echo -e "${BLUE}[INFO] Extracting: $output_name${NC}"
adb pull "$apk_path" "$APP_WORK_DIR/$output_name" 2>/dev/null
if [ -f "$APP_WORK_DIR/$output_name" ]; then
echo -e "${GREEN}[OK] Extracted: $output_name${NC}"
else
echo -e "${YELLOW}[WARNING] Failed to extract: $output_name${NC}"
fi
i=$((i+1))
fi
done < "$WORK_DIR/apk_paths.txt"
}
unpack_apks() {
echo -e "${YELLOW}[INFO] Unpacking APKs...${NC}"
cd "$APP_WORK_DIR" || {
echo -e "${RED}[ERROR] Failed to change to directory: $APP_WORK_DIR${NC}"
exit 1
}
if [ -f "base.apk" ]; then
echo -e "${BLUE}[INFO] Unpacking base.apk...${NC}"
unzip -q -o "base.apk" -d "base_extracted"
else
echo -e "${RED}[ERROR] base.apk not found${NC}"
exit 1
fi
for split_apk in split_*.apk; do
if [ -f "$split_apk" ]; then
split_name="${split_apk%.apk}"
echo -e "${BLUE}[INFO] Unpacking: $split_apk${NC}"
unzip -q -o "$split_apk" -d "$split_name"
if echo "$split_apk" | grep -q "arm64"; then
echo -e "${GREEN}[OK] ARM64 split detected${NC}"
elif echo "$split_apk" | grep -q "armeabi"; then
echo -e "${GREEN}[OK] ARM split detected${NC}"
elif echo "$split_apk" | grep -q "x86_64"; then
echo -e "${GREEN}[OK] x86_64 split detected${NC}"
elif echo "$split_apk" | grep -q "x86"; then
echo -e "${GREEN}[OK] x86 split detected${NC}"
elif echo "$split_apk" | grep -q "hdpi\|xhdpi\|xxhdpi\|xxxhdpi\|mdpi"; then
echo -e "${GREEN}[OK] Density split detected${NC}"
elif echo "$split_apk" | grep -q "config\."; then
echo -e "${GREEN}[OK] Configuration split detected${NC}"
fi
fi
done
}
merge_components() {
echo -e "${YELLOW}[INFO] Merging components into Fat APK...${NC}"
if [ ! -d "$APP_WORK_DIR" ]; then
echo -e "${RED}[ERROR] Working directory not found: $APP_WORK_DIR${NC}"
echo -e "${BLUE}[DEBUG] Current directory: $(pwd)${NC}"
echo -e "${BLUE}[DEBUG] Available directories in $WORK_DIR:${NC}"
ls -la "$WORK_DIR" 2>/dev/null || echo "Cannot list $WORK_DIR"
exit 1
fi
cd "$APP_WORK_DIR" || {
echo -e "${RED}[ERROR] Failed to change to directory: $APP_WORK_DIR${NC}"
exit 1
}
echo -e "${BLUE}[INFO] Merging native libraries...${NC}"
for split_dir in split_*/; do
if [ -d "$split_dir" ] && [ -d "$split_dir/lib" ]; then
echo -e "${BLUE}[INFO] Copying libs from $split_dir${NC}"
mkdir -p "base_extracted/lib"
cp -r "$split_dir/lib/"* "base_extracted/lib/" 2>/dev/null || true
fi
done
echo -e "${BLUE}[INFO] Merging assets...${NC}"
for split_dir in split_*/; do
if [ -d "$split_dir" ] && [ -d "$split_dir/assets" ]; then
echo -e "${BLUE}[INFO] Copying assets from $split_dir${NC}"
mkdir -p "base_extracted/assets"
cp -r "$split_dir/assets/"* "base_extracted/assets/" 2>/dev/null || true
fi
done
echo -e "${BLUE}[INFO] Merging resources...${NC}"
for split_dir in split_*/; do
if [ -d "$split_dir" ] && [ -d "$split_dir/res" ]; then
echo -e "${BLUE}[INFO] Merging resources from $split_dir${NC}"
cp -r "$split_dir/res/"* "base_extracted/res/" 2>/dev/null || true
fi
done
if [ -d "base_extracted/lib" ]; then
echo -e "${GREEN}[OK] Included architectures:${NC}"
ls "base_extracted/lib/"
fi
}
create_fat_apk() {
echo -e "${YELLOW}[INFO] Creating Fat APK...${NC}"
if [ ! -d "$APP_WORK_DIR/base_extracted" ]; then
echo -e "${RED}[ERROR] Base extracted directory not found: $APP_WORK_DIR/base_extracted${NC}"
echo -e "${BLUE}[DEBUG] Available in $APP_WORK_DIR:${NC}"
ls -la "$APP_WORK_DIR" 2>/dev/null || echo "Cannot list $APP_WORK_DIR"
exit 1
fi
cd "$APP_WORK_DIR/base_extracted" || {
echo -e "${RED}[ERROR] Failed to change to directory: $APP_WORK_DIR/base_extracted${NC}"
exit 1
}
echo -e "${BLUE}[INFO] Removing old signature...${NC}"
rm -rf META-INF/
mkdir -p "$(pwd)/../../$OUTPUT_DIR"
OUTPUT_APK="$(pwd)/../../$OUTPUT_DIR/${SELECTED_PACKAGE}_v${VERSION}_fat.apk"
echo -e "${BLUE}[INFO] Compressing Fat APK...${NC}"
zip -r -q "$OUTPUT_APK" .
cd ../../ || {
echo -e "${RED}[ERROR] Failed to return to original directory${NC}"
exit 1
}
if [ -f "$OUTPUT_DIR/${SELECTED_PACKAGE}_v${VERSION}_fat.apk" ]; then
if [[ "$OSTYPE" == "darwin"* ]]; then
SIZE=$(du -h "$OUTPUT_DIR/${SELECTED_PACKAGE}_v${VERSION}_fat.apk" | cut -f1)
else
SIZE=$(du -h "$OUTPUT_DIR/${SELECTED_PACKAGE}_v${VERSION}_fat.apk" | cut -f1)
fi
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}[SUCCESS] Fat APK created successfully!${NC}"
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}File: $OUTPUT_DIR/${SELECTED_PACKAGE}_v${VERSION}_fat.apk${NC}"
echo -e "${GREEN}Size: $SIZE${NC}"
if unzip -t "$OUTPUT_DIR/${SELECTED_PACKAGE}_v${VERSION}_fat.apk" >/dev/null 2>&1; then
echo -e "${GREEN}[OK] APK integrity verified${NC}"
else
echo -e "${YELLOW}[WARNING] APK may need adjustments${NC}"
fi
else
echo -e "${RED}[ERROR] Failed to create Fat APK${NC}"
exit 1
fi
}
show_instructions() {
echo ""
echo -e "${GREEN}=== NEXT STEPS ===${NC}"
echo ""
echo -e "${BLUE}1. Sign the APK:${NC}"
echo " Use one of the options below:"
echo " - apksigner (Android SDK)"
echo " - jarsigner (Java)"
echo " - uber-apk-signer"
echo ""
echo -e "${BLUE}2. Example signing with uber-apk-signer:${NC}"
echo " java -jar uber-apk-signer.jar --apks $OUTPUT_DIR/${SELECTED_PACKAGE}_v${VERSION}_fat.apk"
echo ""
echo -e "${BLUE}3. Install the signed APK:${NC}"
echo " adb install signed_file.apk"
echo ""
echo -e "${YELLOW}NOTE: The Fat APK contains all libraries and resources${NC}"
echo -e "${YELLOW} necessary to work on any device.${NC}"
}
main() {
clear
echo -e "${GREEN}=====================================${NC}"
echo -e "${GREEN} FAT APK GENERATOR VIA ADB ${NC}"
echo -e "${GREEN} Version 3.0 ${NC}"
echo -e "${GREEN}=====================================${NC}"
echo ""
check_adb
setup_directories
list_installed_apps
get_user_choice
get_app_info
extract_apks_from_device
unpack_apks
merge_components
create_fat_apk
cleanup
show_instructions
echo ""
echo -e "${GREEN}[COMPLETE] Process finished!${NC}"
}
trap cleanup EXIT INT TERM
main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment