inject.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. package inject
  2. import (
  3. "bufio"
  4. "debug/elf"
  5. "fmt"
  6. klog "github.com/sirupsen/logrus"
  7. "io"
  8. "io/fs"
  9. "os"
  10. "path/filepath"
  11. "strings"
  12. "syscall"
  13. )
  14. type LibNetInfo struct {
  15. LibName string
  16. LibPath string
  17. FuncSymbol InstInfo
  18. FuncConvert0Symbol InstInfo
  19. FuncGetTTLSymbol InstInfo
  20. InnerSymbol InnerSymbolInfo
  21. ProcLoadPath string
  22. FileDeleted bool
  23. MapFile string
  24. }
  25. type UprobeData struct {
  26. Offset int
  27. Func string
  28. ELFPath string
  29. }
  30. type JvmInjector struct {
  31. Pid int
  32. ReleaseLibNetInfo LibNetInfo
  33. DebugLibNetInfo LibNetInfo
  34. RecodeInfo LibNetInfo
  35. // 原方法首个指令不为jmp | ReleaseLibNetInfo 读取无异常
  36. PreCheck struct {
  37. NeedInjectionCheck bool // 原指令校验 true表示可以继续执行注入
  38. LoadingCheck bool // true 表示加载成功
  39. IoFdCheck bool // fd地址校验
  40. NetSendFuncCheck bool // netsend校验
  41. EbpfCanInjection bool // 满足则注入ebpf
  42. }
  43. AfterCheck struct {
  44. IoFdCheck bool
  45. NetSendFuncCheck bool
  46. }
  47. Uprobe UprobeData
  48. Rootfs string
  49. }
  50. func FindLibBaseByPathFromProcMaps(pid int, libPath string) (uint64, string, error) {
  51. mapsFile := fmt.Sprintf("/proc/%d/maps", pid)
  52. file, err := os.Open(mapsFile)
  53. if err != nil {
  54. return 0, "", err
  55. }
  56. defer file.Close()
  57. var start, end uint64
  58. scanner := bufio.NewScanner(file)
  59. for scanner.Scan() {
  60. line := scanner.Text()
  61. if strings.Contains(line, libPath) {
  62. fmt.Sscanf(line, "%x-%x", &start, &end)
  63. fields := strings.Fields(line)
  64. if len(fields) > 5 {
  65. path := fields[5]
  66. if strings.HasSuffix(path, ".so") {
  67. return start, path, nil
  68. }
  69. }
  70. }
  71. }
  72. return 1, "", fmt.Errorf("library %s not found in process.", libPath)
  73. }
  74. func FindLibBaseFromProcMaps(pid int, libName string) (uint64, string, string, bool, error) {
  75. mapsFile := fmt.Sprintf("/proc/%d/maps", pid)
  76. file, err := os.Open(mapsFile)
  77. if err != nil {
  78. return 0, "", "", false, err
  79. }
  80. defer file.Close()
  81. var start, end uint64
  82. var deleted bool
  83. scanner := bufio.NewScanner(file)
  84. for scanner.Scan() {
  85. line := scanner.Text()
  86. if strings.Contains(line, "/"+libName) {
  87. fmt.Sscanf(line, "%x-%x", &start, &end)
  88. fields := strings.Fields(line)
  89. if len(fields) > 5 {
  90. path := fields[5]
  91. if len(fields) > 6 && fields[6] == "(deleted)" {
  92. deleted = true
  93. }
  94. if strings.HasSuffix(path, ".so") {
  95. klog.Infof("[inject] found library in map %s", path)
  96. return start, path, fmt.Sprintf("/proc/%d/map_files/%s", pid, fields[0]), deleted, nil
  97. }
  98. }
  99. }
  100. }
  101. return 1, "", "", false, fmt.Errorf("[FindLibBaseFromProcMaps] library %s not found", libName)
  102. }
  103. func CopyFileAndMatchPermissions(srcFile, destFile, permFile string) error {
  104. // 获取权限参考文件的信息
  105. permInfo, err := os.Stat(permFile)
  106. if err != nil {
  107. return fmt.Errorf("failed to stat permission file: %w", err)
  108. }
  109. mode := permInfo.Mode()
  110. uid, gid := -1, -1
  111. if stat, ok := permInfo.Sys().(*syscall.Stat_t); ok {
  112. uid = int(stat.Uid)
  113. gid = int(stat.Gid)
  114. }
  115. srcInfo, err := os.Stat(srcFile)
  116. if err != nil {
  117. return fmt.Errorf("failed to stat source file/dir: %w", err)
  118. }
  119. if srcInfo.IsDir() {
  120. // 复制整个目录
  121. return filepath.WalkDir(srcFile, func(path string, d fs.DirEntry, err error) error {
  122. if err != nil {
  123. return err
  124. }
  125. relPath, err := filepath.Rel(srcFile, path)
  126. if err != nil {
  127. return err
  128. }
  129. targetPath := filepath.Join(destFile, relPath)
  130. if d.IsDir() {
  131. if err := os.MkdirAll(targetPath, mode); err != nil {
  132. return fmt.Errorf("failed to create directory %s: %w", targetPath, err)
  133. }
  134. if uid >= 0 && gid >= 0 {
  135. if err := os.Chown(targetPath, uid, gid); err != nil {
  136. return fmt.Errorf("failed to set directory ownership: %w", err)
  137. }
  138. }
  139. } else {
  140. if err := copyOneFile(path, targetPath, mode, uid, gid); err != nil {
  141. return fmt.Errorf("failed to copy file %s: %w", path, err)
  142. }
  143. }
  144. return nil
  145. })
  146. } else {
  147. // 复制单个文件
  148. return copyOneFile(srcFile, destFile, mode, uid, gid)
  149. }
  150. }
  151. func copyOneFile(src, dst string, mode os.FileMode, uid, gid int) error {
  152. in, err := os.Open(src)
  153. if err != nil {
  154. return fmt.Errorf("failed to open source file: %w", err)
  155. }
  156. defer in.Close()
  157. // 创建父目录
  158. if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil {
  159. return fmt.Errorf("failed to create parent directory: %w", err)
  160. }
  161. out, err := os.OpenFile(dst, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, mode)
  162. if err != nil {
  163. return fmt.Errorf("failed to create destination file: %w", err)
  164. }
  165. defer out.Close()
  166. if _, err := io.Copy(out, in); err != nil {
  167. return fmt.Errorf("failed to copy file content: %w", err)
  168. }
  169. if uid >= 0 && gid >= 0 {
  170. if err := out.Chown(uid, gid); err != nil {
  171. return fmt.Errorf("failed to set file ownership: %w", err)
  172. }
  173. }
  174. return nil
  175. }
  176. func GetFunctionOffset(libPath, functionName string) (elf.Symbol, error) {
  177. elfFile, err := elf.Open(libPath)
  178. if err != nil {
  179. return elf.Symbol{}, fmt.Errorf("failed to open ELF file: %v", err)
  180. }
  181. defer elfFile.Close()
  182. symbols, err := elfFile.DynamicSymbols()
  183. if err != nil {
  184. return elf.Symbol{}, fmt.Errorf("failed to read dynamic symbols: %v", err)
  185. }
  186. for _, sym := range symbols {
  187. if sym.Name == functionName {
  188. //fmt.Println("size:", sym.Size)
  189. return sym, nil
  190. }
  191. }
  192. //textSection := elfFile.Section(".text")
  193. //if textSection == nil {
  194. // fmt.Println("textSection is null")
  195. // //return nil
  196. //}
  197. //textSectionData, err := textSection.Data()
  198. //if err != nil {
  199. // fmt.Println("textSectionData error is", err)
  200. // //return nil
  201. //}
  202. //textSectionLen := uint64(len(textSectionData) - 1)
  203. return elf.Symbol{}, fmt.Errorf("function %s not found", functionName)
  204. }