package inject import ( "encoding/json" "fmt" "io/ioutil" "log" "os" "os/exec" "path/filepath" "strings" "time" ) // Platform 平台类型 type Platform string const ( PlatformAndroid Platform = "android" PlatformWindows Platform = "windows" PlatformLinux Platform = "linux" PlatformIOS Platform = "ios" ) // Arch 架构类型 type Arch string const ( ArchX86 Arch = "x86" ArchX64 Arch = "x64" ArchARM Arch = "arm" ArchARM64 Arch = "arm64" ArchUniversal Arch = "universal" ) // InjectConfig 注入配置 type InjectConfig struct { Platform Platform `json:"platform"` Arch Arch `json:"arch"` TemplateName string `json:"template_name"` ShowVerification bool `json:"show_verification"` ShowAd bool `json:"show_ad"` AdURL string `json:"ad_url"` CountdownSeconds int `json:"countdown_seconds"` AppName string `json:"app_name"` VerifyURL string `json:"verify_url"` AppKey string `json:"app_key"` } // InjectResult 注入结果 type InjectResult struct { Success bool `json:"success"` ResultFile string `json:"result_file"` ResultSize int64 `json:"result_size"` Error string `json:"error"` ProcessTime int64 `json:"process_time"` // 处理耗时(毫秒) } // InjectService 注入服务 type InjectService struct { ApktoolPath string KeystorePath string KeystorePass string KeystoreAlias string KeyPass string ApksignerPath string WorkDir string } // NewInjectService 创建注入服务 func NewInjectService(workDir string) *InjectService { // 确保 workDir 是绝对路径 absWorkDir, err := filepath.Abs(workDir) if err != nil { absWorkDir = workDir } return &InjectService{ WorkDir: absWorkDir, ApktoolPath: getEnvOrDefault("APKTOOL_PATH", "apktool"), KeystorePath: getEnvOrDefault("KEYSTORE_PATH", ""), KeystorePass: getEnvOrDefault("KEYSTORE_PASS", "123456"), KeystoreAlias: getEnvOrDefault("KEYSTORE_ALIAS", "mykey"), KeyPass: getEnvOrDefault("KEY_PASS", "123456"), ApksignerPath: getEnvOrDefault("APKSIGNER_PATH", "apksigner"), } } func getEnvOrDefault(key, defaultValue string) string { if value := os.Getenv(key); value != "" { return value } return defaultValue } // Inject 执行注入 func (s *InjectService) Inject(inputFile string, config InjectConfig) (*InjectResult, error) { startTime := time.Now() // 创建工作目录 taskID := fmt.Sprintf("inject_%d", time.Now().UnixNano()) taskDir := filepath.Join(s.WorkDir, taskID) if err := os.MkdirAll(taskDir, 0755); err != nil { return nil, fmt.Errorf("创建工作目录失败: %v", err) } defer os.RemoveAll(taskDir) // 清理工作目录 var result *InjectResult var err error switch config.Platform { case PlatformAndroid: result, err = s.injectAndroid(inputFile, config, taskDir) case PlatformWindows: result, err = s.injectWindows(inputFile, config, taskDir) case PlatformLinux: result, err = s.injectLinux(inputFile, config, taskDir) case PlatformIOS: result, err = s.injectIOS(inputFile, config, taskDir) default: err = fmt.Errorf("不支持的平台: %s", config.Platform) } if err != nil { return &InjectResult{ Success: false, Error: err.Error(), ProcessTime: time.Since(startTime).Milliseconds(), }, err } result.ProcessTime = time.Since(startTime).Milliseconds() return result, nil } // injectAndroid Android APK 注入 func (s *InjectService) injectAndroid(inputFile string, config InjectConfig, taskDir string) (*InjectResult, error) { log.Printf("[INFO] 开始 Android APK 注入: %s", inputFile) // 1. 反编译 APK decompileDir := filepath.Join(taskDir, "decompiled") if err := s.decompileAPK(inputFile, decompileDir); err != nil { return nil, fmt.Errorf("反编译失败: %v", err) } // 2. 复制注入模板的 smali 文件 templateDir := filepath.Join("inject", "android") if err := s.mergeSmali(templateDir, decompileDir); err != nil { return nil, fmt.Errorf("合并 smali 失败: %v", err) } // 3. 配置注入参数 if err := s.configureAndroid(decompileDir, config); err != nil { return nil, fmt.Errorf("配置失败: %v", err) } // 4. 修改 AndroidManifest.xml if err := s.modifyAndroidManifest(decompileDir); err != nil { return nil, fmt.Errorf("修改 AndroidManifest 失败: %v", err) } // 5. 回编译 APK unsignedAPK := filepath.Join(taskDir, "unsigned.apk") if err := s.recompileAPK(decompileDir, unsignedAPK); err != nil { return nil, fmt.Errorf("回编译失败: %v", err) } // 6. 签名 APK signedAPK := filepath.Join(taskDir, "signed.apk") if err := s.signAPK(unsignedAPK, signedAPK); err != nil { return nil, fmt.Errorf("签名失败: %v", err) } // 7. 获取结果文件信息 fileInfo, err := os.Stat(signedAPK) if err != nil { return nil, fmt.Errorf("获取文件信息失败: %v", err) } // 8. 复制结果文件到输出目录 outputDir := filepath.Join("uploads", "inject") if err := os.MkdirAll(outputDir, 0755); err != nil { return nil, fmt.Errorf("创建输出目录失败: %v", err) } outputFile := filepath.Join(outputDir, fmt.Sprintf("injected_%d.apk", time.Now().Unix())) if err := copyFile(signedAPK, outputFile); err != nil { return nil, fmt.Errorf("复制结果文件失败: %v", err) } log.Printf("[INFO] Android APK 注入完成: %s", outputFile) return &InjectResult{ Success: true, ResultFile: "/" + strings.ReplaceAll(outputFile, "\\", "/"), ResultSize: fileInfo.Size(), }, nil } // injectWindows Windows PE 注入 (占位) func (s *InjectService) injectWindows(inputFile string, config InjectConfig, taskDir string) (*InjectResult, error) { return nil, fmt.Errorf("Windows 平台注入暂未实现") } // injectLinux Linux ELF 注入 (占位) func (s *InjectService) injectLinux(inputFile string, config InjectConfig, taskDir string) (*InjectResult, error) { return nil, fmt.Errorf("Linux 平台注入暂未实现") } // injectIOS iOS IPA 注入 (占位) func (s *InjectService) injectIOS(inputFile string, config InjectConfig, taskDir string) (*InjectResult, error) { return nil, fmt.Errorf("iOS 平台注入暂未实现") } // decompileAPK 反编译 APK func (s *InjectService) decompileAPK(apkFile, outputDir string) error { cmd := exec.Command("java", "-jar", s.ApktoolPath, "d", apkFile, "-o", outputDir, "-f") output, err := cmd.CombinedOutput() if err != nil { return fmt.Errorf("apktool d 失败: %v, output: %s", err, string(output)) } log.Printf("[DEBUG] decompile output: %s", string(output)) return nil } // recompileAPK 回编译 APK func (s *InjectService) recompileAPK(decompileDir, outputFile string) error { cmd := exec.Command("java", "-jar", s.ApktoolPath, "b", decompileDir, "-o", outputFile) output, err := cmd.CombinedOutput() if err != nil { return fmt.Errorf("apktool b 失败: %v, output: %s", err, string(output)) } log.Printf("[DEBUG] recompile output: %s", string(output)) return nil } // signAPK 签名 APK func (s *InjectService) signAPK(unsignedAPK, signedAPK string) error { // 如果没有配置 keystore,使用测试签名 if s.KeystorePath == "" { log.Printf("[WARN] 未配置 keystore,使用 zipalign 对齐") // 使用 zipalign 对齐 cmd := exec.Command("zipalign", "-v", "-p", "4", unsignedAPK, signedAPK) output, err := cmd.CombinedOutput() if err != nil { return fmt.Errorf("zipalign 失败: %v, output: %s", err, string(output)) } return nil } // 使用 apksigner 签名 cmd := exec.Command(s.ApksignerPath, "sign", "--ks", s.KeystorePath, "--ks-key-alias", s.KeystoreAlias, "--ks-pass", "pass:"+s.KeystorePass, "--key-pass", "pass:"+s.KeyPass, "--out", signedAPK, unsignedAPK) output, err := cmd.CombinedOutput() if err != nil { return fmt.Errorf("apksigner 签名失败: %v, output: %s", err, string(output)) } log.Printf("[DEBUG] sign output: %s", string(output)) return nil } // mergeSmali 合并 smali 文件 func (s *InjectService) mergeSmali(templateDir, decompileDir string) error { // 复制模板 smali 文件到反编译目录 smaliDirs := []string{"smali", "smali_classes2", "smali_classes3"} for _, smaliDir := range smaliDirs { srcSmali := filepath.Join(templateDir, smaliDir) if _, err := os.Stat(srcSmali); os.IsNotExist(err) { continue } dstSmali := filepath.Join(decompileDir, smaliDir) if smaliDir == "smali" { // 模板的 smali 直接覆盖 if err := copyDir(srcSmali, dstSmali); err != nil { return err } } else { // 其他 smali_classes 需要合并 if err := copyDir(srcSmali, dstSmali); err != nil { return err } } } return nil } // configureAndroid 配置 Android 注入参数 func (s *InjectService) configureAndroid(decompileDir string, config InjectConfig) error { // 查找并修改 HookApplication.java 中的配置 hookAppPath := filepath.Join(decompileDir, "smali", "com", "example", "shell", "HookApplication.smali") if _, err := os.Stat(hookAppPath); os.IsNotExist(err) { log.Printf("[WARN] HookApplication.smali 不存在,跳过配置") return nil } // 读取文件内容 content, err := ioutil.ReadFile(hookAppPath) if err != nil { return err } contentStr := string(content) // 替换配置参数 replacements := map[string]string{ "[OpenClassName]": config.AppName, "\"https://example.com\"": fmt.Sprintf("\"%s\"", config.VerifyURL), "[AppKey]": config.AppKey, } for old, new := range replacements { contentStr = strings.ReplaceAll(contentStr, old, new) } // 写回文件 return ioutil.WriteFile(hookAppPath, []byte(contentStr), 0644) } // modifyAndroidManifest 修改 AndroidManifest.xml func (s *InjectService) modifyAndroidManifest(decompileDir string) error { manifestPath := filepath.Join(decompileDir, "AndroidManifest.xml") content, err := ioutil.ReadFile(manifestPath) if err != nil { return err } contentStr := string(content) // 检查是否已有 android:name if strings.Contains(contentStr, "android:name=") { // 替换现有的 android:name re := strings.NewReplacer( `android:name="android.app.Application"`, `android:name="com.example.shell.HookApplication"`, ) contentStr = re.Replace(contentStr) } else { // 在