package inject import ( "bufio" "debug/elf" "fmt" klog "github.com/sirupsen/logrus" "io" "io/fs" "os" "path/filepath" "strings" "syscall" ) type LibNetInfo struct { LibName string LibPath string FuncSymbol InstInfo FuncConvert0Symbol InstInfo FuncGetTTLSymbol InstInfo InnerSymbol InnerSymbolInfo ProcLoadPath string FileDeleted bool MapFile string } type UprobeData struct { Offset int Func string ELFPath string } type JvmInjector struct { Pid int ReleaseLibNetInfo LibNetInfo DebugLibNetInfo LibNetInfo RecodeInfo LibNetInfo // 原方法首个指令不为jmp | ReleaseLibNetInfo 读取无异常 PreCheck struct { NeedInjectionCheck bool // 原指令校验 true表示可以继续执行注入 LoadingCheck bool // true 表示加载成功 IoFdCheck bool // fd地址校验 NetSendFuncCheck bool // netsend校验 EbpfCanInjection bool // 满足则注入ebpf } AfterCheck struct { IoFdCheck bool NetSendFuncCheck bool } Uprobe UprobeData Rootfs string } func FindLibBaseByPathFromProcMaps(pid int, libPath string) (uint64, string, error) { mapsFile := fmt.Sprintf("/proc/%d/maps", pid) file, err := os.Open(mapsFile) if err != nil { return 0, "", err } defer file.Close() var start, end uint64 scanner := bufio.NewScanner(file) for scanner.Scan() { line := scanner.Text() if strings.Contains(line, libPath) { fmt.Sscanf(line, "%x-%x", &start, &end) fields := strings.Fields(line) if len(fields) > 5 { path := fields[5] if strings.HasSuffix(path, ".so") { return start, path, nil } } } } return 1, "", fmt.Errorf("library %s not found in process.", libPath) } func FindLibBaseFromProcMaps(pid int, libName string) (uint64, string, string, bool, error) { mapsFile := fmt.Sprintf("/proc/%d/maps", pid) file, err := os.Open(mapsFile) if err != nil { return 0, "", "", false, err } defer file.Close() var start, end uint64 var deleted bool scanner := bufio.NewScanner(file) for scanner.Scan() { line := scanner.Text() if strings.Contains(line, "/"+libName) { fmt.Sscanf(line, "%x-%x", &start, &end) fields := strings.Fields(line) if len(fields) > 5 { path := fields[5] if len(fields) > 6 && fields[6] == "(deleted)" { deleted = true } if strings.HasSuffix(path, ".so") { klog.Infof("[inject] found library in map %s", path) return start, path, fmt.Sprintf("/proc/%d/map_files/%s", pid, fields[0]), deleted, nil } } } } return 1, "", "", false, fmt.Errorf("[FindLibBaseFromProcMaps] library %s not found", libName) } func CopyFileAndMatchPermissions(srcFile, destFile, permFile string) error { // 获取权限参考文件的信息 permInfo, err := os.Stat(permFile) if err != nil { return fmt.Errorf("failed to stat permission file: %w", err) } mode := permInfo.Mode() uid, gid := -1, -1 if stat, ok := permInfo.Sys().(*syscall.Stat_t); ok { uid = int(stat.Uid) gid = int(stat.Gid) } srcInfo, err := os.Stat(srcFile) if err != nil { return fmt.Errorf("failed to stat source file/dir: %w", err) } if srcInfo.IsDir() { // 复制整个目录 return filepath.WalkDir(srcFile, func(path string, d fs.DirEntry, err error) error { if err != nil { return err } relPath, err := filepath.Rel(srcFile, path) if err != nil { return err } targetPath := filepath.Join(destFile, relPath) if d.IsDir() { if err := os.MkdirAll(targetPath, mode); err != nil { return fmt.Errorf("failed to create directory %s: %w", targetPath, err) } if uid >= 0 && gid >= 0 { if err := os.Chown(targetPath, uid, gid); err != nil { return fmt.Errorf("failed to set directory ownership: %w", err) } } } else { if err := copyOneFile(path, targetPath, mode, uid, gid); err != nil { return fmt.Errorf("failed to copy file %s: %w", path, err) } } return nil }) } else { // 复制单个文件 return copyOneFile(srcFile, destFile, mode, uid, gid) } } func copyOneFile(src, dst string, mode os.FileMode, uid, gid int) error { in, err := os.Open(src) if err != nil { return fmt.Errorf("failed to open source file: %w", err) } defer in.Close() // 创建父目录 if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil { return fmt.Errorf("failed to create parent directory: %w", err) } out, err := os.OpenFile(dst, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, mode) if err != nil { return fmt.Errorf("failed to create destination file: %w", err) } defer out.Close() if _, err := io.Copy(out, in); err != nil { return fmt.Errorf("failed to copy file content: %w", err) } if uid >= 0 && gid >= 0 { if err := out.Chown(uid, gid); err != nil { return fmt.Errorf("failed to set file ownership: %w", err) } } return nil } func GetFunctionOffset(libPath, functionName string) (elf.Symbol, error) { elfFile, err := elf.Open(libPath) if err != nil { return elf.Symbol{}, fmt.Errorf("failed to open ELF file: %v", err) } defer elfFile.Close() symbols, err := elfFile.DynamicSymbols() if err != nil { return elf.Symbol{}, fmt.Errorf("failed to read dynamic symbols: %v", err) } for _, sym := range symbols { if sym.Name == functionName { //fmt.Println("size:", sym.Size) return sym, nil } } //textSection := elfFile.Section(".text") //if textSection == nil { // fmt.Println("textSection is null") // //return nil //} //textSectionData, err := textSection.Data() //if err != nil { // fmt.Println("textSectionData error is", err) // //return nil //} //textSectionLen := uint64(len(textSectionData) - 1) return elf.Symbol{}, fmt.Errorf("function %s not found", functionName) }