#!/bin/bash

# =============================================
# 判官APK弹窗式注册机 (用户交互版)
# 使用apktool进行反编译/回编，支持自定义签名
# 注意：此脚本需在/Alitc/zcj目录运行
# =============================================

# 颜色定义
COLOR_TITLE="\033[1;36m"      # 标题 - 青色加粗
COLOR_STEP="\033[1;35m"       # 步骤 - 紫色加粗
COLOR_SUCCESS="\033[1;32m"    # 成功 - 绿色加粗
COLOR_ERROR="\033[1;31m"      # 错误 - 红色加粗
COLOR_WARNING="\033[1;33m"    # 警告 - 黄色加粗
COLOR_INFO="\033[1;34m"       # 信息 - 蓝色加粗
COLOR_MENU="\033[1;36m"       # 菜单 - 青色加粗
COLOR_INPUT="\033[1;37m"      # 输入提示 - 白色加粗
COLOR_RESET="\033[0m"         # 重置颜色

# 目录定义
APK_DIR="/Alitc/zcj/APK"
LIB_DIR="/Alitc/zcj/libs"
WORK_DIR="/Alitc/zcj"
OUTPUT_DIR="/Alitc/zcj/out"
ALI_SMALI_ZIP="/Alitc/zcj/smali/tcszcj.zip"

# 显示彩色标题
show_header() {
    echo -e "\n${COLOR_TITLE}=================================="
    echo " 判官APK弹窗式注册机-用户交互式版"
    echo -e "==================================${COLOR_RESET}"
}

# 显示使用帮助
show_help() {
    echo -e "\n${COLOR_TITLE}判官APK弹窗式注册机使用说明${COLOR_RESET}"
    echo "此脚本提供两种签名模式："
    echo -e "${COLOR_SUCCESS}1. 默认签名模式：${COLOR_RESET}"
    echo "  自动扫描$APK_DIR目录下的APK文件"
    echo "  使用默认签名配置: 别名=androiddebugkey, 密码=android"
    echo "  注入后的APK将输出到$OUTPUT_DIR目录"
    echo ""
    echo -e "${COLOR_SUCCESS}2. 自定义签名模式：${COLOR_RESET}"
    echo "  手动指定签名文件注入"
    echo "  注入后的APK将输出到$OUTPUT_DIR目录"
    echo ""
    echo -e "${COLOR_WARNING}使用前准备：${COLOR_RESET}"
    echo "1. 将待处理APK放入$APK_DIR目录"
    echo "2. 确保ali_smali.zip文件在$WORK_DIR目录"
    echo "3. 确保以下工具在$LIB_DIR目录:"
    echo "   - apktool.jar"
    echo "   - apksigner.jar"
}

# 扫描APK目录并选择文件
select_apk() {
    # 确保APK目录存在
    mkdir -p "$APK_DIR"
    
    # 查找APK文件
    apk_files=("$APK_DIR"/*.apk)
    if [ ${#apk_files[@]} -eq 0 ]; then
        echo -e "${COLOR_ERROR}错误：$APK_DIR 目录下未找到APK文件！${COLOR_RESET}"
        echo -e "${COLOR_WARNING}请将待处理的APK文件放入 $APK_DIR/ 目录${COLOR_RESET}"
        return 1
    fi
    
    echo -e "\n${COLOR_INFO}检测到以下APK文件：${COLOR_RESET}"
    local i=1
    for apk in "${apk_files[@]}"; do
        echo "$i) $(basename "$apk")"
        ((i++))
    done
    
    echo -en "${COLOR_INPUT}请选择要处理的APK文件 [1-${#apk_files[@]}]: ${COLOR_RESET}"
    read choice
    
    # 验证选择
    if [[ ! $choice =~ ^[0-9]+$ ]] || ((choice < 1 || choice > ${#apk_files[@]})); then
        echo -e "${COLOR_ERROR}错误：无效的选择！${COLOR_RESET}"
        return 1
    fi
    
    # 设置选择的APK路径
    APK_PATH="${apk_files[$choice-1]}"
    APK_NAME=$(basename "$APK_PATH" .apk)
    OUTPUT_APK="$OUTPUT_DIR/${APK_NAME}_ali.apk"
    UNPACK_DIR="$WORK_DIR/temp/$APK_NAME"
    
    echo -e "${COLOR_SUCCESS}已选择: $APK_PATH${COLOR_RESET}"
    return 0
}

# 默认签名模式处理
simple_mode() {
    echo -e "\n${COLOR_TITLE}===== 默认签名模式 =====${COLOR_RESET}"
    
    # 设置默认签名配置
    KEYSTORE_PATH="$WORK_DIR/debug.keystore"
    ALIAS="androiddebugkey"
    KEYSTORE_PASS="android"
    KEY_PASS="android"
    
    # 检查默认密钥库是否存在
    if [ ! -f "$KEYSTORE_PATH" ]; then
        echo -e "${COLOR_WARNING}提示：未找到默认密钥库，将创建新的密钥库...${COLOR_RESET}"
        keytool -genkey -v -keystore "$KEYSTORE_PATH" -alias "$ALIAS" \
            -storepass "$KEYSTORE_PASS" -keypass "$KEY_PASS" \
            -keyalg RSA -keysize 2048 -validity 10000 \
            -dname "CN=Android Debug,O=Android,C=US"
    fi
    
    echo -e "${COLOR_SUCCESS}使用默认签名配置:${COLOR_RESET}"
    echo "密钥库: $(basename "$KEYSTORE_PATH")"
    echo "别名: $ALIAS"
    echo "密钥库密码: $KEYSTORE_PASS"
    echo "密钥密码: $KEY_PASS"
    
    return 0
}

# 自定义签名模式处理
advanced_mode() {
    echo -e "\n${COLOR_TITLE}===== 自定义签名模式 =====${COLOR_RESET}"
    
    # 获取用户输入的签名信息
    echo -en "${COLOR_INPUT}请输入密钥库路径 [默认: $WORK_DIR/debug.keystore]: ${COLOR_RESET}"
    read input_ks
    KEYSTORE_PATH=${input_ks:-"$WORK_DIR/debug.keystore"}
    
    echo -en "${COLOR_INPUT}请输入密钥别名 [默认: androiddebugkey]: ${COLOR_RESET}"
    read input_alias
    ALIAS=${input_alias:-"androiddebugkey"}
    
    echo -en "${COLOR_INPUT}请输入密钥库密码 [默认: android]: ${COLOR_RESET}"
    read -s ks_pass
    KEYSTORE_PASS=${ks_pass:-"android"}
    echo
    
    echo -en "${COLOR_INPUT}请输入密钥密码 [默认: android]: ${COLOR_RESET}"
    read -s key_pass
    KEY_PASS=${key_pass:-"android"}
    echo
    
    echo -e "${COLOR_SUCCESS}使用以下配置:${COLOR_RESET}"
    echo "密钥库: $KEYSTORE_PATH"
    echo "别名: $ALIAS"
    echo "密钥库密码: $KEYSTORE_PASS"
    echo "密钥密码: $KEY_PASS"
    
    return 0
}

# 检查必要工具
check_tools() {
    local required_tools=(
        "$LIB_DIR/apktool.jar"
        "$LIB_DIR/apksigner.jar"
        "$ALI_SMALI_ZIP"
    )
    
    local missing=0
    for tool in "${required_tools[@]}"; do
        if [ ! -f "$tool" ]; then
            echo -e "${COLOR_ERROR}错误：未找到工具 $tool${COLOR_RESET}"
            ((missing++))
        fi
    done
    
    if [ $missing -gt 0 ]; then
        echo -e "${COLOR_WARNING}请确保所有必要工具都存在:${COLOR_RESET}"
        echo "1. apktool.jar"
        echo "2. apksigner.jar"
        echo "3. ali_smali.zip"
        echo -e "这些工具应该放在: $LIB_DIR 或 $WORK_DIR"
        return 1
    fi
    
    return 0
}

# 清理残留文件
cleanup() {
    echo -e "${COLOR_STEP}[清理] 删除临时文件...${COLOR_RESET}"
    [ -d "$UNPACK_DIR" ] && rm -rf "$UNPACK_DIR"
    [ -f "$WORK_DIR/temp.apk" ] && rm -f "$WORK_DIR/temp.apk"
}

# 加固处理流程
perform_reinforcement() {
    # 确保输出目录存在
    mkdir -p "$OUTPUT_DIR"
    
    # 检查必要工具
    if ! check_tools; then
        cleanup
        return 1
    fi
    
    # 步骤1: 反编译APK
    echo -e "\n${COLOR_STEP}[1/6] 反编译APK...${COLOR_RESET}"
    java -jar "$LIB_DIR/apktool.jar" d -f "$APK_PATH" -o "$UNPACK_DIR" || {
        echo -e "${COLOR_ERROR}错误：反编译失败！${COLOR_RESET}"
        echo -e "${COLOR_WARNING}可能原因:${COLOR_RESET}"
        echo "1. APK文件损坏"
        echo "2. 缺少依赖库"
        echo "3. apktool版本不兼容"
        cleanup
        return 1
    }
    
    # 步骤2: 添加ali_smali内容
    echo -e "${COLOR_STEP}[2/6] 添加弹窗代码...${COLOR_RESET}"
    unzip -qo "$ALI_SMALI_ZIP" -d "$UNPACK_DIR/smali" || {
        echo -e "${COLOR_ERROR}错误：解压ali_smali.zip失败！${COLOR_RESET}"
        cleanup
        return 1
    }
    
    # 步骤3: 修改AndroidManifest.xml
    echo -e "${COLOR_STEP}[3/6] 修改应用入口...${COLOR_RESET}"
    MANIFEST="$UNPACK_DIR/AndroidManifest.xml"
    
    # 检查XML文件是否存在
    if [ ! -f "$MANIFEST" ]; then
        echo -e "${COLOR_ERROR}错误：未找到AndroidManifest.xml文件！${COLOR_RESET}"
        cleanup
        return 1
    fi
    
    # 精确提取application主入口
    APP_CLASS=$(grep -a -oP '<application[^>]*android:name="\K[^"]+' "$MANIFEST" | head -1)
    
    if [ -z "$APP_CLASS" ]; then
        # 如果没有显式声明的application类，使用默认值
        echo -e "${COLOR_WARNING}警告: 未找到显式application类名，使用默认值${COLOR_RESET}"
        APP_CLASS="android.app.Application"
    else
        echo -e "${COLOR_SUCCESS}找到主入口: $APP_CLASS${COLOR_RESET}"
    fi
    
    # 精确替换application主入口（仅替换application标签内的name属性）
    sed -i ':a;N;$!ba; s/\(<application[^>]* android:name=\)"[^"]*"/\1"阿力.NB"/' "$MANIFEST"
    
 # 步骤4: 修改smali类继承关系
    echo -e "${COLOR_STEP}[4/6] 修改类继承关系...${COLOR_RESET}"
    # 转换类名为smali格式
    SMALI_APP_CLASS="L${APP_CLASS//./\/};"
    TARGET_SMALI="$UNPACK_DIR/smali/阿力/NB.smali"
    
    if [ ! -f "$TARGET_SMALI" ]; then
        echo -e "${COLOR_ERROR}错误：未找到NB.smali文件！${COLOR_RESET}"
        echo -e "${COLOR_WARNING}请检查ali_smali.zip是否包含正确的smali结构${COLOR_RESET}"
        cleanup
        return 1
    fi
    
    # 备份原始smali文件
    cp "$TARGET_SMALI" "${TARGET_SMALI}.bak"
    
    # 精确替换三处父类继承关系
    echo -e "${COLOR_INFO}修改.super指令...${COLOR_RESET}"
    sed -i "s#^\.super Landroid/app/Application;\$#.super $SMALI_APP_CLASS#" "$TARGET_SMALI"
    
    echo -e "${COLOR_INFO}修改<init>方法中的父类引用...${COLOR_RESET}"
    sed -i "s#Landroid/app/Application;#$SMALI_APP_CLASS#g" "$TARGET_SMALI"
    
    echo -e "${COLOR_INFO}修改onCreate方法中的父类引用...${COLOR_RESET}"
    sed -i "s#Landroid/app/Application;#$SMALI_APP_CLASS#g" "$TARGET_SMALI"
    
    echo -e "${COLOR_SUCCESS}已修改父类为: $SMALI_APP_CLASS${COLOR_RESET}"    
    
    # 步骤5: 回编APK
    echo -e "${COLOR_STEP}[5/6] 回编APK...${COLOR_RESET}"
    java -jar "$LIB_DIR/apktool.jar" b "$UNPACK_DIR" -o "$WORK_DIR/temp.apk" || {
        echo -e "${COLOR_ERROR}错误：回编APK失败！${COLOR_RESET}"
        echo -e "${COLOR_WARNING}可能原因:${COLOR_RESET}"
        echo "1. smali语法错误"
        echo "2. 资源冲突"
        echo "3. apktool版本问题"
        cleanup
        return 1
    }
    
    # 步骤6: 签名APK
    echo -e "${COLOR_STEP}[6/6] 签名APK...${COLOR_RESET}"
    
    # 检查签名文件是否存在
    if [ ! -f "$KEYSTORE_PATH" ]; then
        echo -e "${COLOR_ERROR}错误：未找到密钥库文件 $KEYSTORE_PATH${COLOR_RESET}"
        cleanup
        return 1
    fi
    
    java -jar "$LIB_DIR/apksigner.jar" sign \
        --ks "$KEYSTORE_PATH" \
        --ks-pass "pass:$KEYSTORE_PASS" \
        --key-pass "pass:$KEY_PASS" \
        --out "$OUTPUT_APK" \
        "$WORK_DIR/temp.apk" || {
        echo -e "${COLOR_ERROR}错误：签名失败！${COLOR_RESET}"
        cleanup
        return 1
    }
    
    # 清理临时文件
    cleanup
    
    echo -e "\n${COLOR_SUCCESS}注入完成！文件已保存到: $OUTPUT_APK${COLOR_RESET}"
    
    # 显示APK信息
    echo -e "\n${COLOR_INFO}APK信息:${COLOR_RESET}"
    echo "原始大小: $(du -h "$APK_PATH" | cut -f1)"
    echo "注入后大小: $(du -h "$OUTPUT_APK" | cut -f1)"
    
    return 0
}

# 显示菜单选项
show_menu() {
    echo -e "\n${COLOR_MENU}请选择签名模式：${COLOR_RESET}"
    echo "1) 默认签名模式 (使用debug.keystore)"
    echo "2) 自定义签名模式 (手动指定签名)"
    echo "3) 检查工具状态"
    echo "4) 脚本使用说明"
    echo "5) 退出"
    echo -en "${COLOR_INPUT}请输入选项 [1-5]: ${COLOR_RESET}"
}

# 主程序
main() {
    # 显示标题
    show_header
    
    # 确保所需目录存在
    mkdir -p "$APK_DIR" "$OUTPUT_DIR" "$WORK_DIR/temp"
    
    # 主循环
    while true; do
        # 选择APK
        if ! select_apk; then
            echo -en "\n${COLOR_INPUT}按回车键返回菜单... ${COLOR_RESET}"
            read
            continue
        fi
        
        # 选择模式
        show_menu
        read choice
        
        case $choice in
            1)
                if simple_mode; then
                    perform_reinforcement
                fi
                ;;
            2)
                if advanced_mode; then
                    perform_reinforcement
                fi
                ;;
            3)
                echo -e "\n${COLOR_TITLE}===== 工具状态检查 =====${COLOR_RESET}"
                check_tools
                if [ $? -eq 0 ]; then
                    echo -e "${COLOR_SUCCESS}所有必要工具都存在${COLOR_RESET}"
                fi
                continue
                ;;
            4)
                show_help
                echo -en "\n${COLOR_INPUT}按回车键返回菜单... ${COLOR_RESET}"
                read
                continue
                ;;
            5)
                echo -e "${COLOR_WARNING}已退出注入工具${COLOR_RESET}"
                exit 0
                ;;
            *)
                echo -e "${COLOR_ERROR}错误：无效选项，请重新选择！${COLOR_RESET}"
                continue
                ;;
        esac
        
        # 询问是否继续
        echo -en "\n${COLOR_INPUT}是否继续操作？[y/n]: ${COLOR_RESET}"
        read continue_choice
        if [[ ! "$continue_choice" =~ ^[Yy]$ ]]; then
            echo -e "${COLOR_WARNING}已退出注入工具${COLOR_RESET}"
            exit 0
        fi
    done
}

# 启动主程序
main