├── README.md ├── build.bat ├── go.mod ├── injector-go └── main.go /README.md: -------------------------------------------------------------------------------- 1 | # Ref 2 | 3 | - https://github.com/erfur/linjector-rs 4 | 5 | # Build 6 | 7 | build libs/liblinjector_rs.a from here 8 | 9 | - https://github.com/SeeFlowerX/linjector-rs 10 | 11 | ```bash 12 | cargo ndk --target aarch64-linux-android build --release 13 | ``` 14 | 15 | then copy target/aarch64-linux-android/release/liblinjector_rs.a to current project libs/linjector_rs.a 16 | 17 | ```bat 18 | set NDK_PATH=path\to\ndk 19 | build.bat 20 | ``` 21 | 22 | # Usage 23 | 24 | ```bash 25 | adb push injector-go /data/local/tmp/injector-go 26 | adb shell chmod +x /data/local/tmp/injector-go 27 | adb shell "su -c \"/data/local/tmp/injector-go -p `pidof com.smile.gifmaker` -i raw-dlopen -f /data/local/tmp/libeloader.so\"" 28 | adb shell "su -c \"/data/local/tmp/injector-go -a com.smile.gifmaker -i raw-dlopen -f /data/local/tmp/libeloader.so\"" 29 | ``` 30 | 31 | # Help 32 | 33 | ```bash 34 | Usage: injector-go [options] 35 | Options: 36 | -V Print version 37 | -a string 38 | target application's package name, get pid by pidof and do injection 39 | -d enable debug logs 40 | -f string 41 | path of the library/shellcode to inject 42 | -func-sym string 43 | function to hijack for injection, in the form "lib.so!symbol_name" 44 | -h Print help (see a summary with '-h') 45 | -i string 46 | type of injection. Possible values: raw-dlopen, memfd-dlopen, raw-shellcode (default "raw-dlopen") 47 | -logcat 48 | print logs to logcat 49 | -p int 50 | pid of the target process 51 | -var-sym string 52 | variable to hijack for injection, in the form "lib.so!symbol_name" 53 | ``` -------------------------------------------------------------------------------- /build.bat: -------------------------------------------------------------------------------- 1 | @echo on 2 | 3 | :: 设置环境变量 4 | set GOOS=android 5 | set GOARCH=arm64 6 | set CGO_ENABLED=1 7 | 8 | :: 检查 NDK_PATH 环境变量是否已设置 9 | if "%NDK_PATH%"=="" ( 10 | echo Error: NDK_PATH environment variable is not set. Please set it to the NDK home directory. 11 | exit /b 1 12 | ) 13 | 14 | :: 构建 CC 路径 15 | set CC=%NDK_PATH%\toolchains\llvm\prebuilt\windows-x86_64\bin\aarch64-linux-android21-clang 16 | 17 | :: 编译 Go 项目 18 | echo Building for Android... 19 | go build -ldflags="-s -w" -o injector-go main.go -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module linjector-go 2 | 3 | go 1.23.3 4 | -------------------------------------------------------------------------------- /injector-go: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/linjector-go/b43457c2f599103d0da213d8061f697999392f28/injector-go -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | /* 4 | #cgo LDFLAGS: -L${SRCDIR}/libs -Wl,-Bstatic -llinjector_rs -Wl,-Bdynamic -ldl 5 | #include 6 | int inject(int pid, const char* file_path, int injection_type, const char* func_sym, const char* var_sym, int debug, int logcat); 7 | */ 8 | import "C" 9 | import ( 10 | "flag" 11 | "fmt" 12 | "os" 13 | "os/exec" 14 | "strings" 15 | "unsafe" 16 | ) 17 | 18 | func main() { 19 | // 定义命令行参数 20 | pid := flag.Int("p", 0, "pid of the target process") 21 | appPackageName := flag.String("a", "", "target application's package name, get pid by pidof and do injection") 22 | filePath := flag.String("f", "", "path of the library/shellcode to inject") 23 | injectionTypeStr := flag.String("i", "raw-dlopen", "type of injection. Possible values: raw-dlopen, memfd-dlopen, raw-shellcode") 24 | funcSym := flag.String("func-sym", "", "function to hijack for injection, in the form \"lib.so!symbol_name\"") 25 | varSym := flag.String("var-sym", "", "variable to hijack for injection, in the form \"lib.so!symbol_name\"") 26 | debug := flag.Bool("d", false, "enable debug logs") 27 | logcat := flag.Bool("logcat", false, "print logs to logcat") 28 | help := flag.Bool("h", false, "Print help (see a summary with '-h')") 29 | version := flag.Bool("V", false, "Print version") 30 | 31 | // 解析命令行参数 32 | flag.Parse() 33 | 34 | // 显示帮助信息 35 | if *help { 36 | fmt.Println("Usage: injector-go [options]") 37 | fmt.Println("Options:") 38 | flag.PrintDefaults() 39 | os.Exit(0) 40 | } 41 | 42 | // 显示版本信息 43 | if *version { 44 | fmt.Println("Version: 1.0") 45 | os.Exit(0) 46 | } 47 | 48 | // 如果没有提供 pid,尝试通过包名获取 pid 49 | if *pid == 0 && *appPackageName != "" { 50 | output, err := exec.Command("pidof", *appPackageName).Output() 51 | if err != nil { 52 | fmt.Printf("Failed to get PID for package %s: %v\n", *appPackageName, err) 53 | os.Exit(1) 54 | } 55 | pidStr := strings.TrimSpace(string(output)) 56 | if pidStr == "" { 57 | fmt.Printf("No process found for package %s\n", *appPackageName) 58 | os.Exit(1) 59 | } 60 | _, err = fmt.Sscanf(pidStr, "%d", pid) 61 | if err != nil { 62 | fmt.Printf("Failed to parse PID: %v\n", err) 63 | os.Exit(1) 64 | } 65 | } 66 | // 检查必要参数 67 | if *pid == 0 || *filePath == "" { 68 | fmt.Println("Both PID and file path are required. Use -h for help.") 69 | os.Exit(1) 70 | } 71 | // 将注入类型字符串转换为整数 72 | injectionType := 0 73 | switch *injectionTypeStr { 74 | case "raw-dlopen": 75 | injectionType = 0 76 | case "memfd-dlopen": 77 | injectionType = 1 78 | case "raw-shellcode": 79 | injectionType = 2 80 | default: 81 | fmt.Printf("Invalid injection type: %s\n", *injectionTypeStr) 82 | os.Exit(1) 83 | } 84 | 85 | // 转换文件路径、函数符号、变量符号为 C 字符串 86 | cFilePath := C.CString(*filePath) 87 | defer C.free(unsafe.Pointer(cFilePath)) 88 | 89 | var cFuncSym *C.char 90 | if *funcSym != "" { 91 | cFuncSym = C.CString(*funcSym) 92 | defer C.free(unsafe.Pointer(cFuncSym)) 93 | } 94 | 95 | var cVarSym *C.char 96 | if *varSym != "" { 97 | cVarSym = C.CString(*varSym) 98 | defer C.free(unsafe.Pointer(cVarSym)) 99 | } 100 | 101 | // 调用注入函数 102 | result := C.inject( 103 | C.int(*pid), 104 | cFilePath, 105 | C.int(injectionType), 106 | cFuncSym, 107 | cVarSym, 108 | boolToInt(*debug), 109 | boolToInt(*logcat), 110 | ) 111 | 112 | if result != 0 { 113 | fmt.Println("Injection failed") 114 | } else { 115 | fmt.Println("Injection succeeded") 116 | } 117 | } 118 | 119 | // boolToInt 将布尔值转换为整数 120 | func boolToInt(b bool) C.int { 121 | if b { 122 | return 1 123 | } 124 | return 0 125 | } 126 | --------------------------------------------------------------------------------