#!/bin/bash

RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m'

log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }

echo "AES256 CBC 加密生成"
echo "系统库: /system/lib64/libcrypto.so"
echo ""

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"

# 威尔逊定理密钥生成
# 使用威尔逊定理: 如果 p 是质数，则 (p-1)! ≡ -1 (mod p)，即 (p-1)! + 1 ≡ 0 (mod p)
generate_wilson_key() {
    # 选择一个质数 p (32位范围内的质数，确保计算在合理时间内)
    local primes=(100003 100019 100043 100049 100057 100069 100103 100109 100129 100151)
    local p=${primes[$RANDOM % ${#primes[@]}]}
    
    # 计算 (p-1)! mod p 的简化版本
    # 使用威尔逊定理的性质来生成确定性的伪随机序列
    
    local seed=$p
    local key_hex=""
    
    # 生成32字节的密钥 (256位)
    for i in {1..32}; do
        # 使用威尔逊定理相关的计算来生成每个字节
        # (p-1)! mod p = p-1，所以 (p-1)! + 1 ≡ 0 (mod p)
        # 我们可以利用这个性质生成伪随机字节
        local byte=$(( (seed * i + p) % 256 ))
        
        # 进一步使用威尔逊定理的变形
        # 威尔逊定理: (p-1)! ≡ -1 (mod p) ⇒ (p-1)! + 1 = k*p
        # 使用这个关系来混淆
        local k=$(( (i * p) / 256 ))
        byte=$(( (byte ^ k) & 0xFF ))
        
        # 添加到密钥
        key_hex="${key_hex}$(printf "%02x" $byte)"
        
        # 更新种子
        seed=$(( (seed * 1103515245 + 12345) & 0x7FFFFFFF ))
    done
    
    echo "$key_hex"
}

# 威尔逊定理IV生成函数
generate_wilson_iv() {
    # 选择另一个质数 q (与密钥生成不同)
    local primes=(100267 100271 100279 100291 100297 100313 100333 100343 100357 100361)
    local q=${primes[$RANDOM % ${#primes[@]}]}
    
    local seed=$q
    local iv_hex=""
    
    # 生成16字节的IV (128位)
    for i in {1..16}; do
        # 使用威尔逊定理相关的计算
        # (q-1)! mod q = q-1
        local byte=$(( (seed * i * 7 + q) % 256 ))
        
        # 应用威尔逊定理的变形
        local k=$(( (i * q) / 128 ))
        byte=$(( (byte ^ k) & 0xFF ))
        
        # 添加到IV
        iv_hex="${iv_hex}$(printf "%02x" $byte)"
        
        # 更新种子
        seed=$(( (seed * 1664525 + 1013904223) & 0x7FFFFFFF ))
    done
    
    echo "$iv_hex"
}

# 增强版密钥生成：威尔逊定理 + 随机混合
generate_enhanced_key() {
    # 1. 生成随机密钥
    local true_random_key=$(dd if=/dev/urandom bs=32 count=1 2>/dev/null | xxd -p -c 64 | tr -d '\n' 2>/dev/null)
    
    # 2. 生成威尔逊定理密钥
    local wilson_key=$(generate_wilson_key)
    
    # 3. 混合两者（XOR运算）
    local mixed_key=""
    for i in $(seq 0 2 62); do
        true_byte=0x${true_random_key:$i:2}
        wilson_byte=0x${wilson_key:$i:2}
        mixed_byte=$(( (true_byte ^ wilson_byte) & 0xFF ))
        mixed_key="${mixed_key}$(printf "%02x" $mixed_byte)"
    done
    
    echo "$mixed_key"
}

# IV生成：威尔逊定理 + 随机混合
generate_enhanced_iv() {
    # 1. 生成随机IV
    local true_random_iv=$(dd if=/dev/urandom bs=16 count=1 2>/dev/null | xxd -p -c 32 | tr -d '\n' 2>/dev/null)
    
    # 2. 生成威尔逊定理IV
    local wilson_iv=$(generate_wilson_iv)
    
    # 3. 混合两者（XOR运算）
    local mixed_iv=""
    for i in $(seq 0 2 30); do
        true_byte=0x${true_random_iv:$i:2}
        wilson_byte=0x${wilson_iv:$i:2}
        mixed_byte=$(( (true_byte ^ wilson_byte) & 0xFF ))
        mixed_iv="${mixed_iv}$(printf "%02x" $mixed_byte)"
    done
    
    echo "$mixed_iv"
}

generate_aes_key_iv() {
    # 生成基于威尔逊定理 + 随机混合的密钥和IV
    local key_hex=$(generate_enhanced_key)
    local iv_hex=$(generate_enhanced_iv)
    
    echo "${key_hex}:${iv_hex}"
}

aes_encrypt() {
    local input_file="$1"
    local key_hex="$2"
    local iv_hex="$3"
    
    if command -v openssl >/dev/null 2>&1; then
        openssl enc -aes-256-cbc \
            -K "$key_hex" \
            -iv "$iv_hex" \
            -in "$input_file" \
            -out "${input_file}.aes" 2>/dev/null
        
        if [ $? -eq 0 ] && [ -f "${input_file}.aes" ]; then
            xxd -p -c 0 "${input_file}.aes" 2>/dev/null | tr -d '\n'
            rm -f "${input_file}.aes"
            return 0
        fi
    fi
    
    log_error "openssl 不可用，无法进行 AES 加密"
    return 1
}

generate_stub_c() {
    local aes_encrypted_hex="$1"
    local key_hex="$2"
    local iv_hex="$3"
    
    cat << 'C_EOF'
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dlfcn.h>
#include <sys/wait.h>
#include <sys/syscall.h>
#include <fcntl.h>

static const unsigned char AES_KEY[32] = {
C_EOF
    
    for i in $(seq 0 2 $(( ${#key_hex} - 2 )) ); do
        byte="0x${key_hex:$i:2}"
        index=$((i/2))
        if [ $index -eq 31 ]; then
            echo "    $byte"
        else
            echo -n "    $byte, "
            if [ $(( (index+1) % 8 )) -eq 0 ]; then
                echo ""
            fi
        fi
    done
    
    cat << 'C_EOF'
};

static const unsigned char AES_IV[16] = {
C_EOF
    
    for i in $(seq 0 2 $(( ${#iv_hex} - 2 )) ); do
        byte="0x${iv_hex:$i:2}"
        index=$((i/2))
        if [ $index -eq 15 ]; then
            echo "    $byte"
        else
            echo -n "    $byte, "
            if [ $(( (index+1) % 8 )) -eq 0 ]; then
                echo ""
            fi
        fi
    done
    
    cat << 'C_EOF'
};

int aes256_cbc_decrypt(const unsigned char *ciphertext, int ciphertext_len,
                      unsigned char *key, unsigned char *iv,
                      unsigned char *plaintext) {
    void *handle;
    int (*EVP_DecryptInit_ex)(void*, const void*, void*, const unsigned char*, const unsigned char*);
    int (*EVP_DecryptUpdate)(void*, unsigned char*, int*, const unsigned char*, int);
    int (*EVP_DecryptFinal_ex)(void*, unsigned char*, int*);
    void* (*EVP_CIPHER_CTX_new)(void);
    void (*EVP_CIPHER_CTX_free)(void*);
    const void* (*EVP_aes_256_cbc)(void);
    
    handle = dlopen("/system/lib64/libcrypto.so", RTLD_LAZY);
    if (!handle) {
        return -1;
    }
    
    EVP_CIPHER_CTX_new = dlsym(handle, "EVP_CIPHER_CTX_new");
    EVP_CIPHER_CTX_free = dlsym(handle, "EVP_CIPHER_CTX_free");
    EVP_aes_256_cbc = dlsym(handle, "EVP_aes_256_cbc");
    EVP_DecryptInit_ex = dlsym(handle, "EVP_DecryptInit_ex");
    EVP_DecryptUpdate = dlsym(handle, "EVP_DecryptUpdate");
    EVP_DecryptFinal_ex = dlsym(handle, "EVP_DecryptFinal_ex");
    
    if (!EVP_CIPHER_CTX_new || !EVP_CIPHER_CTX_free || !EVP_aes_256_cbc ||
        !EVP_DecryptInit_ex || !EVP_DecryptUpdate || !EVP_DecryptFinal_ex) {
        dlclose(handle);
        return -2;
    }
    
    void *ctx = EVP_CIPHER_CTX_new();
    if (!ctx) {
        dlclose(handle);
        return -3;
    }
    
    int len, plaintext_len;
    
    if (EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv) != 1) {
        EVP_CIPHER_CTX_free(ctx);
        dlclose(handle);
        return -4;
    }
    
    if (EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len) != 1) {
        EVP_CIPHER_CTX_free(ctx);
        dlclose(handle);
        return -5;
    }
    plaintext_len = len;
    
    if (EVP_DecryptFinal_ex(ctx, plaintext + len, &len) != 1) {
        EVP_CIPHER_CTX_free(ctx);
        dlclose(handle);
        return -6;
    }
    plaintext_len += len;
    
    EVP_CIPHER_CTX_free(ctx);
    dlclose(handle);
    
    return plaintext_len;
}

int hex_to_bytes(const char *hex, unsigned char *bytes, int max_len) {
    int i, len = strlen(hex);
    if (len % 2 != 0 || len/2 > max_len) return -1;
    
    for (i = 0; i < len/2; i++) {
        sscanf(hex + i*2, "%2hhx", &bytes[i]);
    }
    return len/2;
}

int execute_shell_script(const char *script) {
    // 创建内存文件描述符（memfd）
    int fd = syscall(__NR_memfd_create, "android_shell", 0);
    if (fd < 0) {
        return -1;
    }
    
    // 写入脚本内容，添加shebang
    write(fd, "#!/system/bin/sh\n", 17);
    write(fd, script, strlen(script));
    lseek(fd, 0, SEEK_SET);
    
    // 获取memfd路径
    char memfd_path[64];
    snprintf(memfd_path, sizeof(memfd_path), "/proc/self/fd/%d", fd);
    
    // 创建子进程执行
    pid_t pid = fork();
    if (pid == -1) {
        close(fd);
        return -1;
    }
    
    if (pid == 0) {  // 子进程
        // 执行内存中的脚本
        execl("/system/bin/sh", "sh", memfd_path, NULL);
        _exit(127);  // 如果execl失败
    } else {  // 父进程
        close(fd);  // 父进程关闭fd
        
        // 等待子进程结束
        int status;
        waitpid(pid, &status, 0);
        
        return WIFEXITED(status) ? WEXITSTATUS(status) : -1;
    }
}

int main() {
    const char *encrypted_hex = 
C_EOF

    echo "\"$aes_encrypted_hex\";"
    
    cat << 'C_END'
    
    int hex_len = strlen(encrypted_hex);
    int ciphertext_len = hex_len / 2;
    unsigned char *ciphertext = malloc(ciphertext_len);
    unsigned char *plaintext = malloc(ciphertext_len + 32);
    
    if (!ciphertext || !plaintext) {
        return 1;
    }
    
    if (hex_to_bytes(encrypted_hex, ciphertext, ciphertext_len) != ciphertext_len) {
        free(ciphertext);
        free(plaintext);
        return 2;
    }
    
    int plaintext_len = aes256_cbc_decrypt(ciphertext, ciphertext_len,
                                          (unsigned char*)AES_KEY, 
                                          (unsigned char*)AES_IV,
                                          plaintext);
    
    if (plaintext_len <= 0) {
        free(ciphertext);
        free(plaintext);
        return 3;
   
    
    plaintext[plaintext_len] = '\0';
    
    // 执行解密后的shell脚本
    int result = execute_shell_script((char*)plaintext);
    
    free(ciphertext);
    free(plaintext);
    
    return result;
}
C_END
}

compile_aes_binary() {
    local input_file="$1"
    local output_file="$2"
    
    log_info "开始生成AES256 CBC加密壳..."
    log_info "使用基于威尔逊定理 + 随机混合的增强密钥生成"
    
    if [ ! -f "$input_file" ]; then
        log_error "输入文件不存在: $input_file"
        return 1
    fi
    
    if ! command -v openssl >/dev/null 2>&1; then
        log_error "系统缺少 openssl 工具，无法进行 AES 加密"
        return 1
    fi
    
    local key_iv=$(generate_aes_key_iv)
    local key_hex=$(echo "$key_iv" | cut -d: -f1)
    local iv_hex=$(echo "$key_iv" | cut -d: -f2)
    
    log_info "AES密钥: ${key_hex:0:16}..."
    log_info "AES IV: ${iv_hex:0:8}..."
    log_info "密钥生成算法: 威尔逊定理 + 随机混合增强"
    
    local encrypted_hex=$(aes_encrypt "$input_file" "$key_hex" "$iv_hex")
    
    if [ $? -ne 0 ] || [ -z "$encrypted_hex" ]; then
        log_error "加密失败"
        return 1
    fi
    
    log_info "加密完成，数据长度: ${#encrypted_hex} 字符"
    
    local stub_file="${input_file}.aes_stub.c"
    generate_stub_c "$encrypted_hex" "$key_hex" "$iv_hex" > "$stub_file"
    
    local cc="clang"
    if command -v $cc >/dev/null 2>&1; then
        $cc -o "$output_file" "$stub_file" -ldl
    else
        log_error "找不到编译器: $cc"
        rm -f "$stub_file"
        return 1
    fi
    
    rm -f "$stub_file"
    
    if [ -f "$output_file" ]; then
        chmod +x "$output_file"
        log_info "生成成功: $output_file"
        return 0
    else
        log_error "编译失败"
        return 1
    fi
}

get_script_path() {
    while true; do
        echo -n "请输入要加密的脚本路径: "
        read input_file
        
        input_file=$(echo "$input_file" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
        
        if [ -z "$input_file" ]; then
            echo "输入不能为空"
            continue
        fi
        
        if [ ! -f "$input_file" ]; then
            echo "文件不存在: $input_file"
            continue
        fi
        
        if [ ! -r "$input_file" ]; then
            echo "无法读取文件: $input_file"
            continue
        fi
        
        echo -n "请输入输出文件名（回车使用默认名称）: "
        read output_file
        
        output_file=$(echo "$output_file" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
        
        if [ -z "$output_file" ]; then
            filename=$(basename "$input_file")
            output_file="${filename%.*}AES.bin"
        fi
        
        # 保存到脚本目录
        output_file="${SCRIPT_DIR}/${output_file}"
        
        echo ""
        echo "输入文件: $input_file"
        echo "输出文件: $output_file"
        echo -n "确认开始加密？(y/n): "
        read confirm
        
        if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then
            break
        else
            echo "重新输入..."
            echo ""
        fi
    done
}

main() {
    echo "当前目录: $(pwd)"
    echo ""
    
    if [ $# -ge 1 ]; then
        input_file="$1"
        # 处理相对/绝对路径
        if [[ "$2" == /* ]]; then
            output_file="$2"
        else
            # 保存到脚本目录
            output_file="${SCRIPT_DIR}/${2:-${input_file%.*}_aes}"
        fi
    else
        get_script_path
    fi
    
    if compile_aes_binary "$input_file" "$output_file"; then
        echo ""
        echo "========================================"
        echo "加密生成成功！"
        echo "输入文件: $input_file"
        echo "输出文件: $output_file"
        echo "加密算法: AES256 CBC"
        echo "密钥算法: 威尔逊定理 + 随机混合增强"
        echo "系统库: /system/lib64/libcrypto.so"
        echo ""
        echo "使用方法: ./$(basename "$output_file")"
        echo "========================================"
    else
        echo "生成失败"
        exit 1
    fi
}

if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    main "$@"
fi