| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- 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)
- }
|