inject.go 5.6 KB

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