inject_linux_amd64.go 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930
  1. package inject
  2. /*
  3. #cgo CFLAGS: -I include
  4. #cgo amd64 LDFLAGS: ${SRCDIR}/lib/libhotpatch_amd64.a
  5. #cgo arm64 LDFLAGS: ${SRCDIR}/lib/libhotpatch_arm64.a
  6. #include "hotpatch.h"
  7. #include <stdlib.h>
  8. */
  9. import "C"
  10. import (
  11. "bufio"
  12. "debug/elf"
  13. "fmt"
  14. "github.com/coroot/coroot-node-agent/utils"
  15. klog "github.com/sirupsen/logrus"
  16. "golang.org/x/arch/x86/x86asm"
  17. "os"
  18. "path/filepath"
  19. "strings"
  20. "syscall"
  21. "unsafe"
  22. )
  23. const (
  24. IO_FD_FDID_SYM_OFFSET = 129
  25. NET_SEND_SYM_OFFSET = 518
  26. )
  27. type InstInfo struct {
  28. SymName string
  29. SymSize uint64
  30. SymAddr uint64
  31. PC uint64
  32. Inst x86asm.Inst
  33. OriginInst x86asm.Inst
  34. OriginCode []byte
  35. TargetAddr uint64
  36. OriginTargetAddr uint64
  37. }
  38. type InnerSymbolInfo struct {
  39. IO_fd_fdID InstInfo
  40. NET_Send InstInfo
  41. }
  42. func (j *JvmInjector) findReleaseAddressInfoFromMem() error {
  43. funcAbsAddress := j.ReleaseLibNetInfo.FuncSymbol.SymAddr
  44. releaseFuncSym := InnerSymbolInfo{}
  45. code, err := j.readMemory(funcAbsAddress, j.ReleaseLibNetInfo.FuncSymbol.SymSize)
  46. if err != nil {
  47. return err
  48. }
  49. pc := uint64(0)
  50. callCount := 0
  51. preContext := InstInfo{}
  52. for pc < uint64(len(code)) {
  53. inst, err := x86asm.Decode(code[pc:], 64)
  54. if err != nil {
  55. fmt.Printf("Decode error at offset 0x%x: %v\n", pc, err)
  56. pc++ // Skip this byte and try to decode again
  57. continue
  58. }
  59. //fmt.Printf("Decoded instuction at 0x%x: %v\n", funcAbsAddress+pc, Inst)
  60. //fmt.Printf("Decoded x86 instuction at 0x%x: %v\n", funcAbsAddress+pc, x86asm.IntelSyntax(inst, 0, nil))
  61. //fmt.Printf("Decoded GNU instuction at 0x%x: %v\n", funcAbsAddress+pc, x86asm.GNUSyntax(Inst, 0, nil))
  62. currentData := InstInfo{
  63. PC: pc,
  64. SymAddr: funcAbsAddress + pc,
  65. Inst: inst,
  66. //IntelInst: x86asm.IntelSyntax(inst, 0, nil),
  67. }
  68. if pc == 0 && inst.Op == x86asm.JMP {
  69. // 已经被修改过的首指令
  70. j.PreCheck.EbpfCanInjection = true
  71. j.Uprobe.ELFPath = j.DebugLibNetInfo.LibPath
  72. if j.DebugLibNetInfo.FileDeleted {
  73. j.Uprobe.ELFPath = j.DebugLibNetInfo.MapFile
  74. }
  75. klog.Infof("[inject] Inst already modified. <%s>;elf:%s", x86asm.IntelSyntax(inst, 0, nil), j.Uprobe.ELFPath)
  76. return nil
  77. }
  78. if pc == 0 {
  79. j.ReleaseLibNetInfo.FuncSymbol.PC = currentData.PC
  80. j.ReleaseLibNetInfo.FuncSymbol.Inst = currentData.Inst
  81. j.ReleaseLibNetInfo.FuncSymbol.OriginInst = currentData.Inst
  82. }
  83. if inst.Op == x86asm.MOV {
  84. if dst, okDst := inst.Args[0].(x86asm.Mem); okDst {
  85. if dst.Base == x86asm.RBP {
  86. if src, okSrc := inst.Args[1].(x86asm.Reg); okSrc {
  87. if src == x86asm.R9L {
  88. // debug so
  89. klog.Infof("[inject] release.so is debug.so. <%s>", x86asm.IntelSyntax(inst, 0, nil))
  90. j.PreCheck.EbpfCanInjection = true
  91. j.Uprobe.ELFPath = j.ReleaseLibNetInfo.LibPath
  92. if j.ReleaseLibNetInfo.FileDeleted {
  93. j.Uprobe.ELFPath = j.ReleaseLibNetInfo.MapFile
  94. }
  95. return fmt.Errorf("MOV from register %v to memory %v\n", src, dst)
  96. //return nil
  97. }
  98. }
  99. }
  100. }
  101. //src, okSrc := inst.Args[1].(x86asm.Reg)
  102. //fmt.Println(inst.Args)
  103. //fmt.Printf("Instruction: %+v\n", inst)
  104. //
  105. //fmt.Println(okSrc)
  106. //if okDst && okSrc && dst == x86asm.RBP && src == x86asm.R9L {
  107. // fmt.Println("Instruction is 'mov %r9d, %rbp'")
  108. //}
  109. }
  110. if inst.Op == x86asm.CALL {
  111. //fmt.Printf("Pre instuction at 0x%x: %v\n", preContext.PC, preContext.Inst)
  112. if callCount == 0 {
  113. releaseFuncSym.IO_fd_fdID = preContext
  114. releaseFuncSym.IO_fd_fdID.SymName = "<IO_fd_fdID>(Release)"
  115. preInst := preContext.Inst
  116. fmt.Println(preInst.Op)
  117. fmt.Println((preInst.Args))
  118. // 计算目标地址
  119. if preInst.Op == x86asm.MOV &&
  120. len(preInst.Args) == 4 &&
  121. preInst.Args[0] != nil &&
  122. preInst.Args[0] == x86asm.RDX &&
  123. preInst.Args[1] != nil {
  124. if mem, ok := preInst.Args[1].(x86asm.Mem); ok && mem.Base == x86asm.RIP {
  125. relOffset := mem.Disp // 直接从Mem结构体中读取偏移
  126. targetAddress := preContext.SymAddr + uint64(preInst.Len) + uint64(relOffset)
  127. fmt.Printf("Target address: 0x%x\n", targetAddress)
  128. releaseFuncSym.IO_fd_fdID.TargetAddr = targetAddress
  129. } else {
  130. return fmt.Errorf("The instruction does not use RIP-relative addressing.")
  131. }
  132. } else {
  133. return fmt.Errorf("The decoded instruction is not a MOV to RDX.")
  134. }
  135. //os.Exit(1)
  136. }
  137. callCount++
  138. if callCount == 4 {
  139. releaseFuncSym.NET_Send = currentData
  140. fmt.Printf("4 call Decoded instuction at 0x%x: %v\n", funcAbsAddress+pc, inst)
  141. relOffset, ok := inst.Args[0].(x86asm.Rel)
  142. if !ok {
  143. return fmt.Errorf("The instruction does not use RIP-relative addressing.")
  144. }
  145. targetAddress := currentData.SymAddr + uint64(inst.Len) + uint64(relOffset)
  146. releaseFuncSym.NET_Send.TargetAddr = targetAddress
  147. fmt.Println(releaseFuncSym.NET_Send)
  148. releaseFuncSym.NET_Send.SymName = "<NET_Send>(Release)"
  149. fmt.Printf("Target address: 0x%x\n", targetAddress)
  150. }
  151. }
  152. preContext = InstInfo{
  153. PC: pc,
  154. SymAddr: funcAbsAddress + pc,
  155. Inst: inst,
  156. }
  157. pc += uint64(inst.Len)
  158. }
  159. j.ReleaseLibNetInfo.InnerSymbol = releaseFuncSym
  160. j.ReleaseLibNetInfo.FuncSymbol.OriginCode = code[0:5]
  161. return nil
  162. }
  163. func (j *JvmInjector) findDebugAddressInfoFromMem() (uint64, error) {
  164. funcAbsAddress := j.DebugLibNetInfo.FuncSymbol.SymAddr
  165. debugFuncSym := InnerSymbolInfo{}
  166. //debugFuncSym.FuncSymbol.SymAddr = funcAbsAddress
  167. //offset := sym.Value
  168. size := j.DebugLibNetInfo.FuncSymbol.SymSize
  169. code, err := j.readMemory(funcAbsAddress, size)
  170. //fmt.Println(code, err)
  171. if err != nil {
  172. return 0, err
  173. }
  174. pc := uint64(0)
  175. preContext := InstInfo{}
  176. for pc < uint64(len(code)) {
  177. inst, err := x86asm.Decode(code[pc:], 64)
  178. if err != nil {
  179. fmt.Printf("Decode error at offset 0x%x: %v\n", pc, err)
  180. pc++ // Skip this byte and try to decode again
  181. continue
  182. }
  183. //fmt.Printf("Decoded instuction at 0x%x: %v\n", funcAbsAddress+pc, Inst)
  184. //fmt.Printf("Decoded x86 instuction at 0x%x: %v\n", funcAbsAddress+pc, x86asm.IntelSyntax(inst, 0, nil))
  185. //fmt.Printf("Decoded GNU instuction at 0x%x: %v\n", funcAbsAddress+pc, x86asm.GNUSyntax(Inst, 0, nil))
  186. currentData := InstInfo{
  187. PC: pc,
  188. SymAddr: funcAbsAddress + pc,
  189. Inst: inst,
  190. }
  191. if pc == 0 {
  192. j.DebugLibNetInfo.FuncSymbol.PC = currentData.PC
  193. j.DebugLibNetInfo.FuncSymbol.Inst = currentData.Inst
  194. j.DebugLibNetInfo.FuncSymbol.OriginInst = currentData.Inst
  195. }
  196. if pc == IO_FD_FDID_SYM_OFFSET {
  197. fmt.Printf("Instuction at 0x%x: %v\n", preContext.PC, preContext.Inst)
  198. debugFuncSym.IO_fd_fdID = currentData
  199. debugFuncSym.IO_fd_fdID.SymName = "<IO_fd_fdID>(Debug)"
  200. // 计算目标地址
  201. if currentData.Inst.Op == x86asm.MOV &&
  202. len(currentData.Inst.Args) == 4 &&
  203. currentData.Inst.Args[0] != nil &&
  204. currentData.Inst.Args[0] == x86asm.RDX &&
  205. currentData.Inst.Args[1] != nil {
  206. if mem, ok := currentData.Inst.Args[1].(x86asm.Mem); ok && mem.Base == x86asm.RIP {
  207. // 直接从Mem结构体中读取偏移
  208. relOffset := mem.Disp
  209. targetAddress := currentData.SymAddr + uint64(currentData.Inst.Len) + uint64(relOffset)
  210. fmt.Printf("Find %s Target address: 0x%x\n", debugFuncSym.IO_fd_fdID.SymName, targetAddress)
  211. debugFuncSym.IO_fd_fdID.TargetAddr = targetAddress
  212. // 保存原始数据
  213. debugFuncSym.IO_fd_fdID.OriginTargetAddr = targetAddress
  214. debugFuncSym.IO_fd_fdID.OriginInst = currentData.Inst
  215. j.PreCheck.IoFdCheck = true
  216. } else {
  217. return 0, fmt.Errorf("The instruction does not use RIP-relative addressing.")
  218. }
  219. } else {
  220. return 0, fmt.Errorf("The decoded instruction is not a MOV to RDX.")
  221. }
  222. }
  223. if pc == NET_SEND_SYM_OFFSET {
  224. debugFuncSym.NET_Send = currentData
  225. fmt.Printf("4 call Decoded instuction at 0x%x: %v\n", funcAbsAddress+pc, inst)
  226. relOffset, ok := (inst.Args[0].(x86asm.Rel))
  227. if !ok {
  228. return 0, fmt.Errorf("The decoded instruction is not a Rel.")
  229. }
  230. targetAddress := currentData.SymAddr + uint64(inst.Len) + uint64(relOffset)
  231. debugFuncSym.NET_Send.TargetAddr = targetAddress
  232. debugFuncSym.NET_Send.SymName = "<NET_Send>(Debug)"
  233. fmt.Printf("Find %s Target address: 0x%x\n", debugFuncSym.NET_Send.SymName, targetAddress)
  234. // 保存原始数据
  235. debugFuncSym.NET_Send.OriginTargetAddr = targetAddress
  236. debugFuncSym.NET_Send.OriginInst = currentData.Inst
  237. j.PreCheck.NetSendFuncCheck = true
  238. }
  239. preContext = InstInfo{
  240. PC: pc,
  241. SymAddr: funcAbsAddress + pc,
  242. Inst: inst,
  243. }
  244. pc += uint64(inst.Len)
  245. }
  246. j.DebugLibNetInfo.InnerSymbol = debugFuncSym
  247. return 0, nil
  248. }
  249. func (j *JvmInjector) checkDebugFuncSymAfterChange() (uint64, error) {
  250. funcAbsAddress := j.DebugLibNetInfo.FuncSymbol.SymAddr
  251. debugFuncSym := InnerSymbolInfo{}
  252. code, err := j.readMemory(funcAbsAddress, j.DebugLibNetInfo.FuncSymbol.SymSize)
  253. if err != nil {
  254. return 0, err
  255. }
  256. pc := uint64(0)
  257. preContext := InstInfo{}
  258. for pc < uint64(len(code)) {
  259. inst, err := x86asm.Decode(code[pc:], 64)
  260. if err != nil {
  261. fmt.Printf("Decode error at offset 0x%x: %v\n", pc, err)
  262. pc++ // Skip this byte and try to decode again
  263. continue
  264. }
  265. //fmt.Printf("Decoded instuction at 0x%x: %v\n", funcAbsAddress+pc, Inst)
  266. //fmt.Printf("Decoded x86 instuction at 0x%x: %v\n", funcAbsAddress+pc, x86asm.IntelSyntax(inst, 0, nil))
  267. //fmt.Printf("Decoded GNU instuction at 0x%x: %v\n", funcAbsAddress+pc, x86asm.GNUSyntax(Inst, 0, nil))
  268. currentData := InstInfo{
  269. PC: pc,
  270. SymAddr: funcAbsAddress + pc,
  271. Inst: inst,
  272. }
  273. if pc == NET_SEND_SYM_OFFSET {
  274. fmt.Printf("Instuction at 0x%x: %v\n", preContext.PC, preContext.Inst)
  275. debugFuncSym.IO_fd_fdID = currentData
  276. debugFuncSym.IO_fd_fdID.SymName = "<IO_fd_fdID>(Debug)"
  277. // 计算目标地址
  278. if currentData.Inst.Op == x86asm.MOV &&
  279. len(currentData.Inst.Args) == 4 &&
  280. currentData.Inst.Args[0] != nil &&
  281. currentData.Inst.Args[0] == x86asm.RDX &&
  282. currentData.Inst.Args[1] != nil {
  283. if mem, ok := currentData.Inst.Args[1].(x86asm.Mem); ok && mem.Base == x86asm.RIP {
  284. // 直接从Mem结构体中读取偏移
  285. relOffset := mem.Disp
  286. targetAddress := currentData.SymAddr + uint64(currentData.Inst.Len) + uint64(relOffset)
  287. fmt.Printf("Find %s Target address: 0x%x\n", debugFuncSym.IO_fd_fdID.SymName, targetAddress)
  288. debugFuncSym.IO_fd_fdID.TargetAddr = targetAddress
  289. //j.PreCheck.IoFdCheck = true
  290. if targetAddress == j.ReleaseLibNetInfo.InnerSymbol.IO_fd_fdID.TargetAddr {
  291. j.DebugLibNetInfo.InnerSymbol.IO_fd_fdID.TargetAddr = targetAddress
  292. j.DebugLibNetInfo.InnerSymbol.IO_fd_fdID.Inst = currentData.Inst
  293. j.AfterCheck.IoFdCheck = true
  294. fmt.Println("ok")
  295. }
  296. } else {
  297. return 0, fmt.Errorf("The instruction does not use RIP-relative addressing.")
  298. }
  299. } else {
  300. return 0, fmt.Errorf("The decoded instruction is not a MOV to RDX.")
  301. }
  302. }
  303. if pc == NET_SEND_SYM_OFFSET {
  304. debugFuncSym.NET_Send = currentData
  305. //fmt.Println(currentData.IntelInst)
  306. //fmt.Printf("4 call Decoded instuction at 0x%x: %v\n", funcAbsAddress+pc, inst)
  307. relOffset, ok := (inst.Args[0].(x86asm.Rel))
  308. if !ok {
  309. return 0, fmt.Errorf("The decoded instruction is not a Rel.")
  310. }
  311. targetAddress := currentData.SymAddr + uint64(inst.Len) + uint64(relOffset)
  312. debugFuncSym.NET_Send.TargetAddr = targetAddress
  313. debugFuncSym.NET_Send.SymName = "<NET_Send>(Debug)"
  314. fmt.Printf("Find %s Target address: 0x%x\n", debugFuncSym.NET_Send.SymName, targetAddress)
  315. if targetAddress == j.ReleaseLibNetInfo.InnerSymbol.NET_Send.TargetAddr {
  316. j.DebugLibNetInfo.InnerSymbol.NET_Send.TargetAddr = targetAddress
  317. j.DebugLibNetInfo.InnerSymbol.NET_Send.Inst = currentData.Inst
  318. j.AfterCheck.NetSendFuncCheck = true
  319. }
  320. }
  321. preContext = InstInfo{
  322. PC: pc,
  323. SymAddr: funcAbsAddress + pc,
  324. Inst: inst,
  325. }
  326. pc += uint64(inst.Len)
  327. }
  328. return 0, nil
  329. }
  330. func (j *JvmInjector) checkReleaseFuncSymAfterChange() error {
  331. funcAbsAddress := j.ReleaseLibNetInfo.FuncSymbol.SymAddr
  332. code, err := j.readMemory(funcAbsAddress, j.ReleaseLibNetInfo.FuncSymbol.SymSize)
  333. if err != nil {
  334. return fmt.Errorf("readMemory error in checkReleaseFuncSymAfterChange <%v>", err)
  335. }
  336. inst, err := x86asm.Decode(code[0:], 64)
  337. if err != nil {
  338. return fmt.Errorf("Decode error in checkReleaseFuncSymAfterChange <%v>", err)
  339. }
  340. if inst.Op != x86asm.JMP {
  341. return fmt.Errorf("The instruction does not JMP.")
  342. }
  343. relOffset, ok := inst.Args[0].(x86asm.Rel)
  344. if !ok {
  345. return fmt.Errorf("The instruction does not use RIP-relative addressing.")
  346. }
  347. // 验证target与Debug入口是否一致
  348. targetAddress := funcAbsAddress + uint64(inst.Len) + uint64(relOffset)
  349. if targetAddress != j.DebugLibNetInfo.FuncSymbol.SymAddr {
  350. return fmt.Errorf("Function entry jmp address does not match expectations.")
  351. }
  352. return nil
  353. }
  354. // readMemory 用于读取指定地址的内存数据
  355. func (j *JvmInjector) readMemory(address uint64, size uint64) ([]byte, error) {
  356. memFile := fmt.Sprintf("/proc/%d/mem", j.Pid)
  357. file, err := os.Open(memFile)
  358. if err != nil {
  359. return nil, err
  360. }
  361. defer file.Close()
  362. data := make([]byte, size)
  363. _, err = file.ReadAt(data, int64(address))
  364. if err != nil {
  365. return nil, err
  366. }
  367. return data, nil
  368. }
  369. // findLibraryBases 用于在 /proc/[pid]/maps 文件中查找库的所有基地址
  370. func findLibraryBasesList(pid int, libraryName string, libPath string) ([]uint64, error) {
  371. mapsFile := fmt.Sprintf("/proc/%d/maps", pid)
  372. file, err := os.Open(mapsFile)
  373. if err != nil {
  374. return nil, err
  375. }
  376. defer file.Close()
  377. var bases []uint64
  378. scanner := bufio.NewScanner(file)
  379. for scanner.Scan() {
  380. line := scanner.Text()
  381. if strings.Contains(line, libraryName) && strings.Contains(line, libPath) {
  382. var start, end uint64
  383. fmt.Sscanf(line, "%x-%x", &start, &end)
  384. bases = append(bases, start)
  385. }
  386. }
  387. if len(bases) == 0 {
  388. return nil, fmt.Errorf("library %s not found", libraryName)
  389. }
  390. return bases, nil
  391. }
  392. func (j *JvmInjector) findLibBaseFromProcMaps(pid int, libName string) (uint64, string, string, bool, error) {
  393. mapsFile := fmt.Sprintf("/proc/%d/maps", j.Pid)
  394. file, err := os.Open(mapsFile)
  395. if err != nil {
  396. return 0, "", "", false, err
  397. }
  398. defer file.Close()
  399. var start, end uint64
  400. var deleted bool
  401. scanner := bufio.NewScanner(file)
  402. for scanner.Scan() {
  403. line := scanner.Text()
  404. if strings.Contains(line, "/"+libName) {
  405. fmt.Sscanf(line, "%x-%x", &start, &end)
  406. fields := strings.Fields(line)
  407. if len(fields) > 5 {
  408. path := fields[5]
  409. if len(fields) > 6 && fields[6] == "(deleted)" {
  410. deleted = true
  411. }
  412. if strings.HasSuffix(path, ".so") {
  413. klog.Infof("[inject] found library in map %s", path)
  414. return start, path, fmt.Sprintf("/proc/%d/map_files/%s", j.Pid, fields[0]), deleted, nil
  415. }
  416. }
  417. }
  418. }
  419. return 1, "", "", false, fmt.Errorf("library %s not found", libName)
  420. }
  421. func (j *JvmInjector) findLibBaseByPathFromProcMaps(libPath string) (uint64, string, error) {
  422. mapsFile := fmt.Sprintf("/proc/%d/maps", j.Pid)
  423. file, err := os.Open(mapsFile)
  424. if err != nil {
  425. return 0, "", err
  426. }
  427. defer file.Close()
  428. var start, end uint64
  429. scanner := bufio.NewScanner(file)
  430. for scanner.Scan() {
  431. line := scanner.Text()
  432. if strings.Contains(line, libPath) {
  433. fmt.Sscanf(line, "%x-%x", &start, &end)
  434. fields := strings.Fields(line)
  435. if len(fields) > 5 {
  436. path := fields[5]
  437. if strings.HasSuffix(path, ".so") {
  438. return start, path, nil
  439. }
  440. }
  441. }
  442. }
  443. return 1, "", fmt.Errorf("library %s not found in process.", libPath)
  444. }
  445. func (j *JvmInjector) getFunctionOffset(libPath, functionName string) (elf.Symbol, error) {
  446. elfFile, err := elf.Open(libPath)
  447. if err != nil {
  448. return elf.Symbol{}, fmt.Errorf("failed to open ELF file: %v", err)
  449. }
  450. defer elfFile.Close()
  451. symbols, err := elfFile.DynamicSymbols()
  452. if err != nil {
  453. return elf.Symbol{}, fmt.Errorf("failed to read dynamic symbols: %v", err)
  454. }
  455. for _, sym := range symbols {
  456. if sym.Name == functionName {
  457. //fmt.Println("size:", sym.Size)
  458. return sym, nil
  459. }
  460. }
  461. //textSection := elfFile.Section(".text")
  462. //if textSection == nil {
  463. // fmt.Println("textSection is null")
  464. // //return nil
  465. //}
  466. //textSectionData, err := textSection.Data()
  467. //if err != nil {
  468. // fmt.Println("textSectionData error is", err)
  469. // //return nil
  470. //}
  471. //textSectionLen := uint64(len(textSectionData) - 1)
  472. return elf.Symbol{}, fmt.Errorf("function %s not found", functionName)
  473. }
  474. //var PID string
  475. func (j *JvmInjector) InitProg() error {
  476. // 获取release库的基地址
  477. baseAddress, releaseSoFilePathInProc, mapFilesPath, deleted, err := FindLibBaseFromProcMaps(j.Pid, j.ReleaseLibNetInfo.LibName)
  478. //j.ReleaseLibNetInfo.LibPath = releaseSoFilePathInProc
  479. j.ReleaseLibNetInfo.FileDeleted = deleted
  480. j.ReleaseLibNetInfo.MapFile = mapFilesPath
  481. pJvmlibnetPhysicalPath := j.Rootfs + releaseSoFilePathInProc
  482. j.ReleaseLibNetInfo.LibPath = pJvmlibnetPhysicalPath
  483. if err != nil {
  484. return fmt.Errorf("Error finding base addresses: %v", err)
  485. }
  486. // jvm prog base
  487. //pJvmLibBaseDir := filepath.Dir(pJvmlibnetPhysicalPath)
  488. jvmLibBaseDir := filepath.Dir(releaseSoFilePathInProc)
  489. // proc maps load path
  490. debugSoFilePathInProc := filepath.Join(jvmLibBaseDir, j.DebugLibNetInfo.LibName)
  491. // Physical path
  492. debugSoFilePhysicalPath := filepath.Join(j.Rootfs, debugSoFilePathInProc)
  493. _, noFileErr := os.Stat(debugSoFilePhysicalPath)
  494. // find cwlibnet.so in proc maps
  495. var readDebugSoPathInMaps string
  496. _, readDebugSoPathInMaps, j.DebugLibNetInfo.MapFile, j.DebugLibNetInfo.FileDeleted, _ = FindLibBaseFromProcMaps(j.Pid, j.DebugLibNetInfo.LibName)
  497. j.DebugLibNetInfo.LibPath = debugSoFilePhysicalPath
  498. j.DebugLibNetInfo.ProcLoadPath = filepath.Join(jvmLibBaseDir, j.DebugLibNetInfo.LibName)
  499. // condition create
  500. pathFromProg := utils.GetDefaultLibsPath("jvm", j.DebugLibNetInfo.LibName)
  501. if noFileErr != nil && readDebugSoPathInMaps == "" && !j.DebugLibNetInfo.FileDeleted {
  502. err = CopyFileAndMatchPermissions(pathFromProg, debugSoFilePhysicalPath, pJvmlibnetPhysicalPath)
  503. klog.Infof("[src:%s],[target:%s],[perm:%s]", pathFromProg, debugSoFilePhysicalPath, pJvmlibnetPhysicalPath)
  504. if err != nil {
  505. return err
  506. }
  507. }
  508. functionName := j.ReleaseLibNetInfo.FuncSymbol.SymName
  509. //j.ReleaseLibNetInfo.LibPath = pJvmlibnetPhysicalPath
  510. klog.Infof("[inject] Base address of [%s]:[%x]", j.ReleaseLibNetInfo.LibName, baseAddress)
  511. // 获取函数的偏移量
  512. functionSym, err := GetFunctionOffset(pJvmlibnetPhysicalPath, functionName)
  513. // 计算函数的实际内存地址
  514. j.ReleaseLibNetInfo.FuncSymbol.SymAddr = baseAddress + functionSym.Value
  515. j.ReleaseLibNetInfo.FuncSymbol.SymSize = functionSym.Size
  516. if err != nil {
  517. klog.WithError(err).Errorf("Error getting function offset")
  518. return err
  519. }
  520. klog.Infof("[inject] Actual memory address of %s at base 0x%x: 0x%x", functionName, baseAddress, j.ReleaseLibNetInfo.FuncSymbol.SymAddr)
  521. if j.Uprobe.ELFPath == "" {
  522. if j.DebugLibNetInfo.FileDeleted {
  523. j.Uprobe.ELFPath = j.DebugLibNetInfo.MapFile
  524. } else {
  525. j.Uprobe.ELFPath = debugSoFilePhysicalPath
  526. }
  527. }
  528. err = j.findReleaseAddressInfoFromMem()
  529. if err != nil {
  530. return err
  531. } else {
  532. j.PreCheck.NeedInjectionCheck = true
  533. }
  534. return nil
  535. }
  536. func (j *JvmInjector) findDebugFuncContextFromLibPath() error {
  537. //libName := j.DebugLibNetInfo.LibPath
  538. // 获取release库的基地址
  539. baseAddress, libPath, err := FindLibBaseByPathFromProcMaps(j.Pid, j.DebugLibNetInfo.ProcLoadPath)
  540. klog.Infof("[inject] debug base address of [%s] : %x", libPath, baseAddress)
  541. functionName := j.DebugLibNetInfo.FuncSymbol.SymName
  542. //j.DebugLibNetInfo.LibPath = libPath
  543. if err != nil {
  544. klog.WithError(err).Errorf("[inject] error.")
  545. return err
  546. }
  547. // 获取函数的偏移量
  548. functionSym, err := GetFunctionOffset(j.DebugLibNetInfo.LibPath, functionName)
  549. // 计算函数的实际内存地址
  550. j.DebugLibNetInfo.FuncSymbol.SymAddr = baseAddress + functionSym.Value
  551. j.DebugLibNetInfo.FuncSymbol.SymSize = functionSym.Size
  552. if err != nil {
  553. return fmt.Errorf("Error getting function offset: %v", err)
  554. }
  555. _, err = j.findDebugAddressInfoFromMem()
  556. if err != nil {
  557. return fmt.Errorf("Error finding first CALL instuction: %v", err)
  558. }
  559. fmt.Printf("First CALL instuction o1f %s at base 0x%x\n", functionName, baseAddress)
  560. return nil
  561. }
  562. func printCodeData(data LibNetInfo) {
  563. fmt.Printf("========FuncEnter <0x%x> \n", data.FuncSymbol.SymAddr)
  564. fmt.Printf("Name %s | CurrentAddr:<0x%x>\nOrigin-TargetAddr:<0x%x> | TargetAddr:<0x%x> \nOrigin-Inst:<%s> | Inst:<%s> \n",
  565. data.InnerSymbol.IO_fd_fdID.SymName,
  566. data.InnerSymbol.IO_fd_fdID.SymAddr,
  567. data.InnerSymbol.IO_fd_fdID.OriginTargetAddr,
  568. data.InnerSymbol.IO_fd_fdID.TargetAddr,
  569. x86asm.IntelSyntax(data.InnerSymbol.IO_fd_fdID.OriginInst, 0, nil),
  570. x86asm.IntelSyntax(data.InnerSymbol.IO_fd_fdID.Inst, 0, nil))
  571. fmt.Printf("\nName %s | CurrentAddr:<0x%x>\nOrigin-TargetAddr:<0x%x> | TargetAddr:<0x%x>\nOrigin-Inst:<%s> | Inst:<%s> \n",
  572. data.InnerSymbol.NET_Send.SymName,
  573. data.InnerSymbol.NET_Send.SymAddr,
  574. data.InnerSymbol.NET_Send.OriginTargetAddr,
  575. data.InnerSymbol.NET_Send.TargetAddr,
  576. x86asm.IntelSyntax(data.InnerSymbol.NET_Send.OriginInst, 0, nil),
  577. x86asm.IntelSyntax(data.InnerSymbol.NET_Send.Inst, 0, nil))
  578. fmt.Println("========")
  579. }
  580. func (j *JvmInjector) jvmInjectLib() int {
  581. dll := C.CString(j.DebugLibNetInfo.ProcLoadPath)
  582. rootfs := C.CString(j.Rootfs)
  583. defer C.free(unsafe.Pointer(dll))
  584. result := C.cw_inject_library(C.int(j.Pid), C.int(1), dll, rootfs)
  585. fmt.Printf("Result: %d\n", result)
  586. return int(result)
  587. }
  588. func (j *JvmInjector) validateAllPreCheck() bool {
  589. return j.PreCheck.NeedInjectionCheck && j.PreCheck.LoadingCheck && j.PreCheck.IoFdCheck && j.PreCheck.NetSendFuncCheck
  590. }
  591. func (j *JvmInjector) validateAllModifyCheck() bool {
  592. return j.AfterCheck.IoFdCheck && j.AfterCheck.NetSendFuncCheck
  593. }
  594. /*修改部分*/
  595. func readData(pid int, addr uintptr) (uint64, error) {
  596. var data uint64
  597. if _, err := syscall.PtracePeekData(pid, addr, (*[8]byte)(unsafe.Pointer(&data))[:]); err != nil {
  598. return 0, fmt.Errorf("ptrace PEEKDATA: %v", err)
  599. }
  600. return data, nil
  601. }
  602. func writeData(pid int, addr uintptr, data uint64) error {
  603. if _, err := syscall.PtracePokeData(pid, addr, (*[8]byte)(unsafe.Pointer(&data))[:]); err != nil {
  604. return fmt.Errorf("ptrace POKEDATA: %v", err)
  605. }
  606. return nil
  607. }
  608. func modifyIoFdTargetAddr(pid int, insertAddr, distAddr uintptr) error {
  609. newOffset := distAddr - (insertAddr + 7)
  610. targetAddr := insertAddr + 3
  611. // 获取目标地址处的数据
  612. originalData, err := readData(pid, targetAddr)
  613. if err != nil {
  614. return err
  615. }
  616. // 更新数据中的目标偏移
  617. updatedData := (originalData & 0xFFFFFFFF00000000) | uint64(newOffset&0xFFFFFFFF)
  618. err = writeData(pid, targetAddr, updatedData)
  619. if err != nil {
  620. return err
  621. }
  622. return nil
  623. }
  624. func modifyNetSetTargetAddr(pid int, sendDebugAddr, sendReleaseAddr uintptr) error {
  625. sendOffset := sendReleaseAddr - sendDebugAddr - 5
  626. // 读取原始数据
  627. alignedAddr := sendDebugAddr & ^(uintptr(unsafe.Sizeof(uintptr(0))) - 1)
  628. originalData, err := readData(pid, alignedAddr)
  629. if err != nil {
  630. return err
  631. }
  632. bytes := (*[8]byte)(unsafe.Pointer(&originalData))
  633. offsetLocation := (sendDebugAddr % uintptr(unsafe.Sizeof(uintptr(0)))) + 1
  634. *(*uint32)(unsafe.Pointer(&bytes[offsetLocation])) = uint32(sendOffset)
  635. err = writeData(pid, alignedAddr, originalData)
  636. if err != nil {
  637. return err
  638. }
  639. return nil
  640. }
  641. func modifyReleaseFuncEnter(pid int, originEnterAddr, debugEnterAddr uintptr) error {
  642. offset := debugEnterAddr - (originEnterAddr + 5)
  643. // 读取原始数据
  644. alignedAddr := originEnterAddr & ^(uintptr(unsafe.Sizeof(uintptr(0))) - 1)
  645. originalData, err := readData(pid, alignedAddr)
  646. if err != nil {
  647. return err
  648. }
  649. bytes := (*[8]byte)(unsafe.Pointer(&originalData))
  650. bytes[originEnterAddr%uintptr(unsafe.Sizeof(uintptr(0)))] = 0xe9
  651. *(*uint32)(unsafe.Pointer(&bytes[(originEnterAddr%uintptr(unsafe.Sizeof(uintptr(0))))+1])) = uint32(offset)
  652. err = writeData(pid, alignedAddr, originalData)
  653. if err != nil {
  654. return err
  655. }
  656. return nil
  657. }
  658. func restoreOriginalInstructions(pid int, addr uintptr, instructions []byte) error {
  659. alignedAddr := addr & ^(uintptr(unsafe.Sizeof(uintptr(0))) - 1)
  660. originalData, err := readData(pid, alignedAddr)
  661. if err != nil {
  662. return err
  663. }
  664. bytes := (*[8]byte)(unsafe.Pointer(&originalData))
  665. for i := 0; i < len(instructions); i++ {
  666. bytes[addr%uintptr(unsafe.Sizeof(uintptr(0)))+uintptr(i)] = instructions[i]
  667. }
  668. err = writeData(pid, alignedAddr, originalData)
  669. if err != nil {
  670. return err
  671. }
  672. return nil
  673. }
  674. // func main() {
  675. // flag.StringVar(&PID, "p", "", "PID")
  676. // flag.Parse()
  677. // pidStr := PID // 替换为目标进程的 PID
  678. // pid, err := strconv.Atoi(pidStr)
  679. // if err != nil {
  680. // log.Fatalf("Invalid PID: %v", err)
  681. // }
  682. // functionName := "Java_java_net_SocketOutputStream_socketWrite0"
  683. // libraryName := "libnet.so"
  684. //
  685. // cwLibraryName := "cwlibnet.so"
  686. // cwLibraryPath := "/root/cwlibnet.so"
  687. //
  688. // jvmInjector := &JvmInjector{
  689. // pid: pid,
  690. // ReleaseLibNetInfo: LibNetInfo{
  691. // libName: libraryName,
  692. // FuncSymbol: instInfo{
  693. // SymName: functionName,
  694. // },
  695. // },
  696. // DebugLibNetInfo: LibNetInfo{
  697. // // TODO 根据版本设置
  698. // libName: cwLibraryName,
  699. // // TODO 根据版本设置
  700. // libPath: cwLibraryPath,
  701. // FuncSymbol: instInfo{
  702. // SymName: functionName,
  703. // },
  704. // },
  705. // }
  706. //
  707. // err = jvmInject(jvmInjector)
  708. // fmt.Println(err)
  709. // }
  710. func JvmInject(jvmInjector *JvmInjector) error {
  711. pid := jvmInjector.Pid
  712. var err error
  713. err = jvmInjector.InitProg()
  714. // Debug版本无需修改寄存器
  715. // 已经加载so并指令修改正确的
  716. if jvmInjector.PreCheck.EbpfCanInjection {
  717. klog.Infoln("[inject] eBPF can injection.")
  718. return nil
  719. }
  720. if err != nil {
  721. klog.WithError(err).Errorf("[inject] Error message during release phase.")
  722. return err
  723. }
  724. // 原指令校验通过
  725. if !jvmInjector.PreCheck.NeedInjectionCheck {
  726. return err
  727. }
  728. printCodeData(jvmInjector.ReleaseLibNetInfo)
  729. _type, _, err := FindLibBaseByPathFromProcMaps(pid, jvmInjector.DebugLibNetInfo.ProcLoadPath)
  730. if err != nil {
  731. // load so
  732. if _type == 1 {
  733. klog.Infoln("[inject] start load so.")
  734. resCode := jvmInjector.jvmInjectLib()
  735. if resCode == 0 {
  736. klog.Infof("[inject] load so successful. proc load path is [%s], file path in node is [%s]", jvmInjector.DebugLibNetInfo.ProcLoadPath, jvmInjector.DebugLibNetInfo.LibPath)
  737. jvmInjector.PreCheck.LoadingCheck = true
  738. } else {
  739. klog.Errorf("[inject] Failed load so. so path is [%s]", jvmInjector.DebugLibNetInfo.LibPath)
  740. return fmt.Errorf("[inject] Failed load so. code is %d so path is [%s]", resCode, jvmInjector.DebugLibNetInfo.LibPath)
  741. }
  742. }
  743. } else {
  744. klog.Infoln("[inject] so already loaded.")
  745. jvmInjector.PreCheck.LoadingCheck = true
  746. }
  747. if !jvmInjector.PreCheck.LoadingCheck {
  748. klog.Infof("Failed load so")
  749. return err
  750. }
  751. err = jvmInjector.findDebugFuncContextFromLibPath()
  752. if err != nil {
  753. klog.WithError(err).Errorf("[inject] Failed to find debug Func Context from libPath")
  754. return err
  755. }
  756. if !jvmInjector.validateAllPreCheck() {
  757. klog.Errorf("[inject] validateAllPreCheck failed: "+
  758. "NeedInjectionCheck=%v, LoadingCheck=%v, IoFdCheck=%v, NetSendFuncCheck=%v",
  759. jvmInjector.PreCheck.NeedInjectionCheck,
  760. jvmInjector.PreCheck.LoadingCheck,
  761. jvmInjector.PreCheck.IoFdCheck,
  762. jvmInjector.PreCheck.NetSendFuncCheck,
  763. )
  764. return err
  765. }
  766. // 修改
  767. debugFuncEnterAddr := uintptr(jvmInjector.DebugLibNetInfo.FuncSymbol.SymAddr)
  768. debugIoFdAddr := uintptr(jvmInjector.DebugLibNetInfo.InnerSymbol.IO_fd_fdID.SymAddr)
  769. debugNetSendAddr := uintptr(jvmInjector.DebugLibNetInfo.InnerSymbol.NET_Send.SymAddr)
  770. originFuncEnterAddr := uintptr(jvmInjector.ReleaseLibNetInfo.FuncSymbol.SymAddr)
  771. ioFdReleaseTargetAddr := uintptr(jvmInjector.ReleaseLibNetInfo.InnerSymbol.IO_fd_fdID.TargetAddr)
  772. netSendReleaseTargetAddr := uintptr(jvmInjector.ReleaseLibNetInfo.InnerSymbol.NET_Send.TargetAddr)
  773. fmt.Printf("<0x%x> -> <0x%x>\n", originFuncEnterAddr, debugFuncEnterAddr)
  774. fmt.Printf("<0x%x> -> <0x%x>\n", debugIoFdAddr, ioFdReleaseTargetAddr)
  775. fmt.Printf("<0x%x> -> <0x%x>\n", debugNetSendAddr, netSendReleaseTargetAddr)
  776. // 附加到目标进程
  777. klog.Infof("attach")
  778. err = syscall.PtraceAttach(pid)
  779. if err != nil {
  780. fmt.Printf("ptrace ATTACH: %v", err)
  781. }
  782. // 等待目标进程停止
  783. klog.Infof("attach Wait")
  784. if _, err := syscall.Wait4(pid, nil, 0, nil); err != nil {
  785. fmt.Printf("wait4: %v", err)
  786. return err
  787. }
  788. //time.Now().UnixNano()
  789. // 修改目标的内存
  790. klog.Infof("modifyIoFdTargetAddr")
  791. err = modifyIoFdTargetAddr(pid, debugIoFdAddr, ioFdReleaseTargetAddr)
  792. if err != nil {
  793. fmt.Println(err)
  794. return err
  795. }
  796. klog.Infof("modifyNetSetTargetAddr")
  797. err = modifyNetSetTargetAddr(pid, debugNetSendAddr, netSendReleaseTargetAddr)
  798. if err != nil {
  799. fmt.Println(err)
  800. return err
  801. }
  802. // 二次效验 读取并验证地址
  803. klog.Infof("checkDebugFuncSymAfterChange")
  804. _, err = jvmInjector.checkDebugFuncSymAfterChange()
  805. printCodeData(jvmInjector.ReleaseLibNetInfo)
  806. printCodeData(jvmInjector.DebugLibNetInfo)
  807. // 效验目标函数内地址是否与预期一致
  808. if !jvmInjector.validateAllModifyCheck() && err == nil {
  809. klog.Errorf("[inject] failed validateAllModifyCheck")
  810. return err
  811. }
  812. // 更新函数入口
  813. klog.Infof("modifyReleaseFuncEnter")
  814. err = modifyReleaseFuncEnter(pid, originFuncEnterAddr, debugFuncEnterAddr)
  815. if err != nil {
  816. klog.Errorf("[inject] failed modifyReleaseFuncEnter")
  817. return err
  818. }
  819. // 校验jmp地址修改正确
  820. klog.Infof("checkReleaseFuncSymAfterChange")
  821. err = jvmInjector.checkReleaseFuncSymAfterChange()
  822. if err != nil {
  823. klog.Errorf("[inject] failed checkReleaseFuncSymAfterChange")
  824. if len(jvmInjector.ReleaseLibNetInfo.FuncSymbol.OriginCode) == 5 {
  825. err = restoreOriginalInstructions(pid, originFuncEnterAddr, jvmInjector.ReleaseLibNetInfo.FuncSymbol.OriginCode)
  826. if err != nil {
  827. fmt.Println(err)
  828. return err
  829. }
  830. }
  831. }
  832. // 恢复执行
  833. klog.Infof("Detach")
  834. if err = syscall.PtraceDetach(pid); err != nil {
  835. klog.Errorf("ptrace DETACH: %v", err)
  836. return err
  837. }
  838. return nil
  839. }