Last active
August 25, 2025 14:44
-
-
Save incogbyte/a3b7e86f512fa438b5c288d0bad57c4c to your computer and use it in GitHub Desktop.
APK Dumper and Automation some
This file contains hidden or 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/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