inject_linux_amd64.go 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163
  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 == 10 && 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:12]
  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. // 原函数内容注释掉
  337. // inst, err := x86asm.Decode(code[0:], 64)
  338. // if err != nil {
  339. // return fmt.Errorf("Decode error in checkReleaseFuncSymAfterChange <%v>", err)
  340. // }
  341. // if inst.Op != x86asm.JMP {
  342. // return fmt.Errorf("The instruction does not JMP.")
  343. // }
  344. // relOffset, ok := inst.Args[0].(x86asm.Rel)
  345. // if !ok {
  346. // return fmt.Errorf("The instruction does not use RIP-relative addressing.")
  347. // }
  348. // // 验证target与Debug入口是否一致
  349. // targetAddress := funcAbsAddress + uint64(inst.Len) + uint64(relOffset)
  350. // if targetAddress != j.DebugLibNetInfo.FuncSymbol.SymAddr {
  351. // return fmt.Errorf("Function entry jmp address does not match expectations.")
  352. // }
  353. // 新的验证逻辑:验证指令序列:movabs $imm64,%rax 和 jmp *%rax
  354. if len(code) < 13 { // movabs(10字节) + jmp(3字节) = 13字节
  355. return fmt.Errorf("Instruction sequence too short, expected at least 13 bytes, got %d", len(code))
  356. }
  357. // 验证第一个指令:movabs $imm64,%rax
  358. // movabs 指令格式:48 B8 + 8字节立即数 (RAX寄存器)
  359. // 48 B8 = movabs rax, imm64
  360. if code[0] != 0x48 || code[1] != 0xB8 {
  361. return fmt.Errorf("First instruction is not movabs rax, imm64. Got: 0x%02x 0x%02x", code[0], code[1])
  362. }
  363. // 提取立即数值 (小端序)
  364. imm64 := uint64(code[2]) | uint64(code[3])<<8 | uint64(code[4])<<16 | uint64(code[5])<<24 |
  365. uint64(code[6])<<32 | uint64(code[7])<<40 | uint64(code[8])<<48 | uint64(code[9])<<56
  366. // 验证立即数是否与 Debug 函数地址一致
  367. expectedAddr := j.DebugLibNetInfo.FuncSymbol.SymAddr
  368. if imm64 != expectedAddr {
  369. return fmt.Errorf("movabs immediate value mismatch. Expected: 0x%x (Debug function addr), Got: 0x%x", expectedAddr, imm64)
  370. }
  371. // 验证第二个指令:jmp *%rax
  372. // jmp *%rax 指令格式:FF E0
  373. if code[10] != 0xFF || code[11] != 0xE0 {
  374. return fmt.Errorf("Second instruction is not jmp *%%rax. Got: 0x%02x 0x%02x", code[10], code[11])
  375. }
  376. klog.Infof("[checkReleaseFuncSymAfterChange] Successfully verified instruction sequence: movabs $0x%x,%%rax; jmp *%%rax", imm64)
  377. return nil
  378. }
  379. // readMemory 用于读取指定地址的内存数据
  380. func (j *JvmInjector) readMemory(address uint64, size uint64) ([]byte, error) {
  381. memFile := fmt.Sprintf("/proc/%d/mem", j.Pid)
  382. file, err := os.Open(memFile)
  383. if err != nil {
  384. return nil, err
  385. }
  386. defer file.Close()
  387. data := make([]byte, size)
  388. _, err = file.ReadAt(data, int64(address))
  389. if err != nil {
  390. return nil, err
  391. }
  392. return data, nil
  393. }
  394. // findLibraryBases 用于在 /proc/[pid]/maps 文件中查找库的所有基地址
  395. func findLibraryBasesList(pid int, libraryName string, libPath string) ([]uint64, error) {
  396. mapsFile := fmt.Sprintf("/proc/%d/maps", pid)
  397. file, err := os.Open(mapsFile)
  398. if err != nil {
  399. return nil, err
  400. }
  401. defer file.Close()
  402. var bases []uint64
  403. scanner := bufio.NewScanner(file)
  404. for scanner.Scan() {
  405. line := scanner.Text()
  406. if strings.Contains(line, libraryName) && strings.Contains(line, libPath) {
  407. var start, end uint64
  408. fmt.Sscanf(line, "%x-%x", &start, &end)
  409. bases = append(bases, start)
  410. }
  411. }
  412. if len(bases) == 0 {
  413. return nil, fmt.Errorf("library %s not found", libraryName)
  414. }
  415. return bases, nil
  416. }
  417. func (j *JvmInjector) findLibBaseFromProcMaps(pid int, libName string) (uint64, string, string, bool, error) {
  418. mapsFile := fmt.Sprintf("/proc/%d/maps", j.Pid)
  419. file, err := os.Open(mapsFile)
  420. if err != nil {
  421. return 0, "", "", false, err
  422. }
  423. defer file.Close()
  424. var start, end uint64
  425. var deleted bool
  426. scanner := bufio.NewScanner(file)
  427. for scanner.Scan() {
  428. line := scanner.Text()
  429. if strings.Contains(line, "/"+libName) {
  430. fmt.Sscanf(line, "%x-%x", &start, &end)
  431. fields := strings.Fields(line)
  432. if len(fields) > 5 {
  433. path := fields[5]
  434. if len(fields) > 6 && fields[6] == "(deleted)" {
  435. deleted = true
  436. }
  437. if strings.HasSuffix(path, ".so") {
  438. klog.Infof("[inject] found library in map %s", path)
  439. return start, path, fmt.Sprintf("/proc/%d/map_files/%s", j.Pid, fields[0]), deleted, nil
  440. }
  441. }
  442. }
  443. }
  444. return 1, "", "", false, fmt.Errorf("library %s not found", libName)
  445. }
  446. func (j *JvmInjector) findLibBaseByPathFromProcMaps(libPath string) (uint64, string, error) {
  447. mapsFile := fmt.Sprintf("/proc/%d/maps", j.Pid)
  448. file, err := os.Open(mapsFile)
  449. if err != nil {
  450. return 0, "", err
  451. }
  452. defer file.Close()
  453. var start, end uint64
  454. scanner := bufio.NewScanner(file)
  455. for scanner.Scan() {
  456. line := scanner.Text()
  457. if strings.Contains(line, libPath) {
  458. fmt.Sscanf(line, "%x-%x", &start, &end)
  459. fields := strings.Fields(line)
  460. if len(fields) > 5 {
  461. path := fields[5]
  462. if strings.HasSuffix(path, ".so") {
  463. return start, path, nil
  464. }
  465. }
  466. }
  467. }
  468. return 1, "", fmt.Errorf("library %s not found in process.", libPath)
  469. }
  470. func (j *JvmInjector) getFunctionOffset(libPath, functionName string) (elf.Symbol, error) {
  471. elfFile, err := elf.Open(libPath)
  472. if err != nil {
  473. return elf.Symbol{}, fmt.Errorf("failed to open ELF file: %v", err)
  474. }
  475. defer elfFile.Close()
  476. symbols, err := elfFile.DynamicSymbols()
  477. if err != nil {
  478. return elf.Symbol{}, fmt.Errorf("failed to read dynamic symbols: %v", err)
  479. }
  480. for _, sym := range symbols {
  481. if sym.Name == functionName {
  482. //fmt.Println("size:", sym.Size)
  483. return sym, nil
  484. }
  485. }
  486. //textSection := elfFile.Section(".text")
  487. //if textSection == nil {
  488. // fmt.Println("textSection is null")
  489. // //return nil
  490. //}
  491. //textSectionData, err := textSection.Data()
  492. //if err != nil {
  493. // fmt.Println("textSectionData error is", err)
  494. // //return nil
  495. //}
  496. //textSectionLen := uint64(len(textSectionData) - 1)
  497. return elf.Symbol{}, fmt.Errorf("function %s not found", functionName)
  498. }
  499. //var PID string
  500. func (j *JvmInjector) InitProg() error {
  501. // 获取release库的基地址
  502. baseAddress, releaseSoFilePathInProc, mapFilesPath, deleted, err := FindLibBaseFromProcMaps(j.Pid, j.ReleaseLibNetInfo.LibName)
  503. //j.ReleaseLibNetInfo.LibPath = releaseSoFilePathInProc
  504. j.ReleaseLibNetInfo.FileDeleted = deleted
  505. j.ReleaseLibNetInfo.MapFile = mapFilesPath
  506. pJvmlibnetPhysicalPath := j.Rootfs + releaseSoFilePathInProc
  507. j.ReleaseLibNetInfo.LibPath = pJvmlibnetPhysicalPath
  508. if err != nil {
  509. return fmt.Errorf("Error finding base addresses: %v", err)
  510. }
  511. // jvm prog base
  512. //pJvmLibBaseDir := filepath.Dir(pJvmlibnetPhysicalPath)
  513. jvmLibBaseDir := filepath.Dir(releaseSoFilePathInProc)
  514. // proc maps load path
  515. debugSoFilePathInProc := filepath.Join(jvmLibBaseDir, j.DebugLibNetInfo.LibName)
  516. // Physical path
  517. debugSoFilePhysicalPath := filepath.Join(j.Rootfs, debugSoFilePathInProc)
  518. _, noFileErr := os.Stat(debugSoFilePhysicalPath)
  519. // find cwlibnet.so in proc maps
  520. var readDebugSoPathInMaps string
  521. _, readDebugSoPathInMaps, j.DebugLibNetInfo.MapFile, j.DebugLibNetInfo.FileDeleted, _ = FindLibBaseFromProcMaps(j.Pid, j.DebugLibNetInfo.LibName)
  522. j.DebugLibNetInfo.LibPath = debugSoFilePhysicalPath
  523. j.DebugLibNetInfo.ProcLoadPath = filepath.Join(jvmLibBaseDir, j.DebugLibNetInfo.LibName)
  524. // condition create
  525. pathFromProg := utils.GetDefaultLibsPath("jvm", j.DebugLibNetInfo.LibName)
  526. if noFileErr != nil && readDebugSoPathInMaps == "" && !j.DebugLibNetInfo.FileDeleted {
  527. err = CopyFileAndMatchPermissions(pathFromProg, debugSoFilePhysicalPath, pJvmlibnetPhysicalPath)
  528. klog.Infof("[src:%s],[target:%s],[perm:%s]", pathFromProg, debugSoFilePhysicalPath, pJvmlibnetPhysicalPath)
  529. if err != nil {
  530. return err
  531. }
  532. }
  533. functionName := j.ReleaseLibNetInfo.FuncSymbol.SymName
  534. //j.ReleaseLibNetInfo.LibPath = pJvmlibnetPhysicalPath
  535. klog.Infof("[inject] Base address of [%s]:[%x]", j.ReleaseLibNetInfo.LibName, baseAddress)
  536. // 获取函数的偏移量
  537. functionSym, err := GetFunctionOffset(pJvmlibnetPhysicalPath, functionName)
  538. // 计算函数的实际内存地址
  539. j.ReleaseLibNetInfo.FuncSymbol.SymAddr = baseAddress + functionSym.Value
  540. j.ReleaseLibNetInfo.FuncSymbol.SymSize = functionSym.Size
  541. if err != nil {
  542. klog.WithError(err).Errorf("Error getting function offset")
  543. return err
  544. }
  545. klog.Infof("[inject] Actual memory address of %s at base 0x%x: 0x%x", functionName, baseAddress, j.ReleaseLibNetInfo.FuncSymbol.SymAddr)
  546. if j.Uprobe.ELFPath == "" {
  547. if j.DebugLibNetInfo.FileDeleted {
  548. j.Uprobe.ELFPath = j.DebugLibNetInfo.MapFile
  549. } else {
  550. j.Uprobe.ELFPath = debugSoFilePhysicalPath
  551. }
  552. }
  553. err = j.findReleaseAddressInfoFromMem()
  554. if err != nil {
  555. return err
  556. } else {
  557. j.PreCheck.NeedInjectionCheck = true
  558. }
  559. return nil
  560. }
  561. func (j *JvmInjector) findDebugFuncContextFromLibPath() error {
  562. //libName := j.DebugLibNetInfo.LibPath
  563. // 获取release库的基地址
  564. baseAddress, libPath, err := FindLibBaseByPathFromProcMaps(j.Pid, j.DebugLibNetInfo.ProcLoadPath)
  565. klog.Infof("[inject] debug base address of [%s] : %x", libPath, baseAddress)
  566. functionName := j.DebugLibNetInfo.FuncSymbol.SymName
  567. //j.DebugLibNetInfo.LibPath = libPath
  568. if err != nil {
  569. klog.WithError(err).Errorf("[inject] error.")
  570. return err
  571. }
  572. // 获取函数的偏移量
  573. functionSym, err := GetFunctionOffset(j.DebugLibNetInfo.LibPath, functionName)
  574. // 计算函数的实际内存地址
  575. j.DebugLibNetInfo.FuncSymbol.SymAddr = baseAddress + functionSym.Value
  576. j.DebugLibNetInfo.FuncSymbol.SymSize = functionSym.Size
  577. if err != nil {
  578. return fmt.Errorf("Error getting function offset: %v", err)
  579. }
  580. functionConvert0Sym, err := GetFunctionOffset(j.DebugLibNetInfo.LibPath, j.DebugLibNetInfo.FuncConvert0Symbol.SymName)
  581. // 计算函数的实际内存地址
  582. j.DebugLibNetInfo.FuncConvert0Symbol.SymAddr = baseAddress + functionConvert0Sym.Value
  583. j.DebugLibNetInfo.FuncConvert0Symbol.SymSize = functionConvert0Sym.Size
  584. if err != nil {
  585. return fmt.Errorf("Error getting function offset: %v", err)
  586. }
  587. functionGetTTLSym, err := GetFunctionOffset(j.DebugLibNetInfo.LibPath, j.DebugLibNetInfo.FuncGetTTLSymbol.SymName)
  588. // 计算函数的实际内存地址
  589. j.DebugLibNetInfo.FuncGetTTLSymbol.SymAddr = baseAddress + functionGetTTLSym.Value
  590. j.DebugLibNetInfo.FuncGetTTLSymbol.SymSize = functionGetTTLSym.Size
  591. if err != nil {
  592. return fmt.Errorf("Error getting function offset: %v", err)
  593. }
  594. _, err = j.findDebugAddressInfoFromMem()
  595. if err != nil {
  596. return fmt.Errorf("Error finding first CALL instuction: %v", err)
  597. }
  598. fmt.Printf("First CALL instuction o1f %s at base 0x%x\n", functionName, baseAddress)
  599. return nil
  600. }
  601. func printCodeData(data LibNetInfo) {
  602. fmt.Printf("========FuncEnter <0x%x> \n", data.FuncSymbol.SymAddr)
  603. fmt.Printf("Name %s | CurrentAddr:<0x%x>\nOrigin-TargetAddr:<0x%x> | TargetAddr:<0x%x> \nOrigin-Inst:<%s> | Inst:<%s> \n",
  604. data.InnerSymbol.IO_fd_fdID.SymName,
  605. data.InnerSymbol.IO_fd_fdID.SymAddr,
  606. data.InnerSymbol.IO_fd_fdID.OriginTargetAddr,
  607. data.InnerSymbol.IO_fd_fdID.TargetAddr,
  608. x86asm.IntelSyntax(data.InnerSymbol.IO_fd_fdID.OriginInst, 0, nil),
  609. x86asm.IntelSyntax(data.InnerSymbol.IO_fd_fdID.Inst, 0, nil))
  610. fmt.Printf("\nName %s | CurrentAddr:<0x%x>\nOrigin-TargetAddr:<0x%x> | TargetAddr:<0x%x>\nOrigin-Inst:<%s> | Inst:<%s> \n",
  611. data.InnerSymbol.NET_Send.SymName,
  612. data.InnerSymbol.NET_Send.SymAddr,
  613. data.InnerSymbol.NET_Send.OriginTargetAddr,
  614. data.InnerSymbol.NET_Send.TargetAddr,
  615. x86asm.IntelSyntax(data.InnerSymbol.NET_Send.OriginInst, 0, nil),
  616. x86asm.IntelSyntax(data.InnerSymbol.NET_Send.Inst, 0, nil))
  617. fmt.Println("========")
  618. }
  619. func (j *JvmInjector) jvmInjectLib() int {
  620. dll := C.CString(j.DebugLibNetInfo.ProcLoadPath)
  621. rootfs := C.CString(j.Rootfs)
  622. defer C.free(unsafe.Pointer(dll))
  623. result := C.cw_inject_library(C.int(j.Pid), C.int(1), dll, rootfs)
  624. fmt.Printf("Result: %d\n", result)
  625. return int(result)
  626. }
  627. func (j *JvmInjector) validateAllPreCheck() bool {
  628. return j.PreCheck.NeedInjectionCheck && j.PreCheck.LoadingCheck && j.PreCheck.IoFdCheck && j.PreCheck.NetSendFuncCheck
  629. }
  630. func (j *JvmInjector) validateAllModifyCheck() bool {
  631. return j.AfterCheck.IoFdCheck && j.AfterCheck.NetSendFuncCheck
  632. }
  633. /*修改部分*/
  634. func readData(pid int, addr uintptr) (uint64, error) {
  635. var data uint64
  636. if _, err := syscall.PtracePeekData(pid, addr, (*[8]byte)(unsafe.Pointer(&data))[:]); err != nil {
  637. return 0, fmt.Errorf("ptrace PEEKDATA: %v", err)
  638. }
  639. return data, nil
  640. }
  641. func writeData(pid int, addr uintptr, data uint64) error {
  642. if _, err := syscall.PtracePokeData(pid, addr, (*[8]byte)(unsafe.Pointer(&data))[:]); err != nil {
  643. return fmt.Errorf("ptrace POKEDATA: %v", err)
  644. }
  645. return nil
  646. }
  647. func readDataBytes(pid int, addr uintptr, size int) ([]byte, error) {
  648. data := make([]byte, size)
  649. if _, err := syscall.PtracePeekData(pid, addr, data); err != nil {
  650. return nil, fmt.Errorf("ptrace PEEKDATA: %v", err)
  651. }
  652. return data, nil
  653. }
  654. func writeDataBytes(pid int, addr uintptr, data []byte) error {
  655. if _, err := syscall.PtracePokeData(pid, addr, data); err != nil {
  656. return fmt.Errorf("ptrace POKEDATA: %v", err)
  657. }
  658. return nil
  659. }
  660. func modifyIoFdTargetAddr(pid int, insertAddr, distAddr, getTTLFunctionAddr uintptr) error {
  661. // newOffset := distAddr - (insertAddr + 7)
  662. // targetAddr := insertAddr + 3
  663. // // 获取目标地址处的数据
  664. // originalData, err := readData(pid, targetAddr)
  665. // if err != nil {
  666. // return err
  667. // }
  668. // // 更新数据中的目标偏移
  669. // updatedData := (originalData & 0xFFFFFFFF00000000) | uint64(newOffset&0xFFFFFFFF)
  670. // err = writeData(pid, targetAddr, updatedData)
  671. // if err != nil {
  672. // return err
  673. // }
  674. getTTLOffset := getTTLFunctionAddr - insertAddr - 5
  675. // 读取原始数据
  676. // alignedAddr := insertAddr & ^(uintptr(unsafe.Sizeof(uintptr(0))) - 1)
  677. originalData, err := readDataBytes(pid, insertAddr, 7)
  678. if err != nil {
  679. return err
  680. }
  681. // offset := insertAddr % uintptr(unsafe.Sizeof(uintptr(0)))
  682. offset := 0
  683. // 写入AMD64的绝对跳转指令: mov rax, addr; jmp rax
  684. var getTTLOffset32 uint32 = uint32(getTTLOffset)
  685. originalData[offset] = 0xE8 // call
  686. originalData[offset+1] = byte(getTTLOffset32)
  687. originalData[offset+2] = byte(getTTLOffset32 >> 8)
  688. originalData[offset+3] = byte(getTTLOffset32 >> 16)
  689. originalData[offset+4] = byte(getTTLOffset32 >> 24)
  690. originalData[offset+5] = 0x90 //nop
  691. originalData[offset+6] = 0x90 //nop
  692. err = writeDataBytes(pid, insertAddr, originalData)
  693. if err != nil {
  694. return err
  695. }
  696. //以上是先跳转到2GB内存的无用函数中
  697. //以下来写真正的跳转函数
  698. TTLOriginalData, err := readDataBytes(pid, getTTLFunctionAddr, 16)
  699. if err != nil {
  700. return err
  701. }
  702. TTLOriginalData[offset] = 0x50
  703. TTLOriginalData[offset+1] = 0x48
  704. TTLOriginalData[offset+2] = 0xb8
  705. TTLOriginalData[offset+3] = byte(distAddr)
  706. TTLOriginalData[offset+4] = byte(distAddr >> 8)
  707. TTLOriginalData[offset+5] = byte(distAddr >> 16)
  708. TTLOriginalData[offset+6] = byte(distAddr >> 24)
  709. TTLOriginalData[offset+7] = byte(distAddr >> 32)
  710. TTLOriginalData[offset+8] = byte(distAddr >> 40)
  711. TTLOriginalData[offset+9] = byte(distAddr >> 48)
  712. TTLOriginalData[offset+10] = byte(distAddr >> 56)
  713. TTLOriginalData[offset+11] = 0x48
  714. TTLOriginalData[offset+12] = 0x8b
  715. TTLOriginalData[offset+13] = 0x10
  716. TTLOriginalData[offset+14] = 0x58 //pop rax
  717. TTLOriginalData[offset+15] = 0xc3 //ret
  718. err = writeDataBytes(pid, getTTLFunctionAddr, TTLOriginalData)
  719. if err != nil {
  720. return err
  721. }
  722. return nil
  723. }
  724. func modifyNetSetTargetAddr(pid int, sendDebugAddr, sendReleaseAddr, convert0FunctionAddr uintptr) error {
  725. // sendOffset := sendReleaseAddr - sendDebugAddr - 5
  726. // // 读取原始数据
  727. // alignedAddr := sendDebugAddr & ^(uintptr(unsafe.Sizeof(uintptr(0))) - 1)
  728. // originalData, err := readData(pid, alignedAddr)
  729. // if err != nil {
  730. // return err
  731. // }
  732. // bytes := (*[8]byte)(unsafe.Pointer(&originalData))
  733. // offsetLocation := (sendDebugAddr % uintptr(unsafe.Sizeof(uintptr(0)))) + 1
  734. // *(*uint32)(unsafe.Pointer(&bytes[offsetLocation])) = uint32(sendOffset)
  735. // err = writeData(pid, alignedAddr, originalData)
  736. // if err != nil {
  737. // return err
  738. // }
  739. convert0Offset := convert0FunctionAddr - sendDebugAddr - 5
  740. // 读取原始数据
  741. // alignedAddr := insertAddr & ^(uintptr(unsafe.Sizeof(uintptr(0))) - 1)
  742. originalData, err := readDataBytes(pid, sendDebugAddr, 5)
  743. if err != nil {
  744. return err
  745. }
  746. // offset := insertAddr % uintptr(unsafe.Sizeof(uintptr(0)))
  747. offset := 0
  748. // 写入AMD64的绝对跳转指令: mov rax, addr; jmp rax
  749. var convert0Offset32 uint32 = uint32(convert0Offset)
  750. originalData[offset] = 0xE8 // call
  751. originalData[offset+1] = byte(convert0Offset32)
  752. originalData[offset+2] = byte(convert0Offset32 >> 8)
  753. originalData[offset+3] = byte(convert0Offset32 >> 16)
  754. originalData[offset+4] = byte(convert0Offset32 >> 24)
  755. err = writeDataBytes(pid, sendDebugAddr, originalData)
  756. if err != nil {
  757. return err
  758. }
  759. convert0OriginalData, err := readDataBytes(pid, convert0FunctionAddr, 13)
  760. if err != nil {
  761. return err
  762. }
  763. convert0OriginalData[offset] = 0x48
  764. convert0OriginalData[offset+1] = 0xb8
  765. convert0OriginalData[offset+2] = byte(sendReleaseAddr)
  766. convert0OriginalData[offset+3] = byte(sendReleaseAddr >> 8)
  767. convert0OriginalData[offset+4] = byte(sendReleaseAddr >> 16)
  768. convert0OriginalData[offset+5] = byte(sendReleaseAddr >> 24)
  769. convert0OriginalData[offset+6] = byte(sendReleaseAddr >> 32)
  770. convert0OriginalData[offset+7] = byte(sendReleaseAddr >> 40)
  771. convert0OriginalData[offset+8] = byte(sendReleaseAddr >> 48)
  772. convert0OriginalData[offset+9] = byte(sendReleaseAddr >> 56)
  773. convert0OriginalData[offset+10] = 0xff
  774. convert0OriginalData[offset+11] = 0xd0
  775. convert0OriginalData[offset+12] = 0xc3
  776. err = writeDataBytes(pid, convert0FunctionAddr, convert0OriginalData)
  777. if err != nil {
  778. return err
  779. }
  780. return nil
  781. }
  782. // func modifyReleaseFuncEnter(pid int, originEnterAddr, debugEnterAddr uintptr) error {
  783. // offset := debugEnterAddr - (originEnterAddr + 5)
  784. // // 读取原始数据
  785. // alignedAddr := originEnterAddr & ^(uintptr(unsafe.Sizeof(uintptr(0))) - 1)
  786. // originalData, err := readData(pid, alignedAddr)
  787. // if err != nil {
  788. // return err
  789. // }
  790. // bytes := (*[8]byte)(unsafe.Pointer(&originalData))
  791. // bytes[originEnterAddr%uintptr(unsafe.Sizeof(uintptr(0)))] = 0xe9
  792. // *(*uint32)(unsafe.Pointer(&bytes[(originEnterAddr%uintptr(unsafe.Sizeof(uintptr(0))))+1])) = uint32(offset)
  793. // err = writeData(pid, alignedAddr, originalData)
  794. // if err != nil {
  795. // return err
  796. // }
  797. // return nil
  798. // }
  799. func modifyReleaseFuncEnter(pid int, originEnterAddr, debugEnterAddr uintptr) error {
  800. // 读取原始数据 - 需要12字节来存储完整的跳转指令
  801. alignedAddr := originEnterAddr & ^(uintptr(unsafe.Sizeof(uintptr(0))) - 1)
  802. originalData, err := readDataBytes(pid, alignedAddr, 12)
  803. if err != nil {
  804. return err
  805. }
  806. offset := originEnterAddr % uintptr(unsafe.Sizeof(uintptr(0)))
  807. // 写入AMD64的绝对跳转指令: mov rax, addr; jmp rax
  808. originalData[offset] = 0x48 // REX.W prefix
  809. originalData[offset+1] = 0xb8 // mov rax, imm64
  810. // 按小端序写入64位地址
  811. originalData[offset+2] = byte(debugEnterAddr)
  812. originalData[offset+3] = byte(debugEnterAddr >> 8)
  813. originalData[offset+4] = byte(debugEnterAddr >> 16)
  814. originalData[offset+5] = byte(debugEnterAddr >> 24)
  815. originalData[offset+6] = byte(debugEnterAddr >> 32)
  816. originalData[offset+7] = byte(debugEnterAddr >> 40)
  817. originalData[offset+8] = byte(debugEnterAddr >> 48)
  818. originalData[offset+9] = byte(debugEnterAddr >> 56)
  819. originalData[offset+10] = 0xff // jmp rax
  820. originalData[offset+11] = 0xe0
  821. err = writeDataBytes(pid, alignedAddr, originalData)
  822. if err != nil {
  823. return err
  824. }
  825. return nil
  826. }
  827. func restoreOriginalInstructions(pid int, addr uintptr, instructions []byte) error {
  828. // alignedAddr := addr & ^(uintptr(unsafe.Sizeof(uintptr(0))) - 1)
  829. // originalData, err := readData(pid, alignedAddr)
  830. originalData, err := readDataBytes(pid, addr, len(instructions))
  831. if err != nil {
  832. return err
  833. }
  834. // bytes := (*[8]byte)(unsafe.Pointer(&originalData))
  835. // for i := 0; i < len(instructions); i++ {
  836. // bytes[addr%uintptr(unsafe.Sizeof(uintptr(0)))+uintptr(i)] = instructions[i]
  837. // }
  838. // offset := addr % uintptr(unsafe.Sizeof(uintptr(0)))
  839. for i := 0; i < len(instructions); i++ {
  840. originalData[i] = instructions[i]
  841. }
  842. // err = writeData(pid, alignedAddr, originalData)
  843. err = writeDataBytes(pid, addr, originalData)
  844. if err != nil {
  845. return err
  846. }
  847. return nil
  848. }
  849. // func main() {
  850. // flag.StringVar(&PID, "p", "", "PID")
  851. // flag.Parse()
  852. // pidStr := PID // 替换为目标进程的 PID
  853. // pid, err := strconv.Atoi(pidStr)
  854. // if err != nil {
  855. // log.Fatalf("Invalid PID: %v", err)
  856. // }
  857. // functionName := "Java_java_net_SocketOutputStream_socketWrite0"
  858. // libraryName := "libnet.so"
  859. //
  860. // cwLibraryName := "cwlibnet.so"
  861. // cwLibraryPath := "/root/cwlibnet.so"
  862. //
  863. // jvmInjector := &JvmInjector{
  864. // pid: pid,
  865. // ReleaseLibNetInfo: LibNetInfo{
  866. // libName: libraryName,
  867. // FuncSymbol: instInfo{
  868. // SymName: functionName,
  869. // },
  870. // },
  871. // DebugLibNetInfo: LibNetInfo{
  872. // // TODO 根据版本设置
  873. // libName: cwLibraryName,
  874. // // TODO 根据版本设置
  875. // libPath: cwLibraryPath,
  876. // FuncSymbol: instInfo{
  877. // SymName: functionName,
  878. // },
  879. // },
  880. // }
  881. //
  882. // err = jvmInject(jvmInjector)
  883. // fmt.Println(err)
  884. // }
  885. func JvmInject(jvmInjector *JvmInjector) error {
  886. pid := jvmInjector.Pid
  887. var err error
  888. err = jvmInjector.InitProg()
  889. // Debug版本无需修改寄存器
  890. // 已经加载so并指令修改正确的
  891. if jvmInjector.PreCheck.EbpfCanInjection {
  892. klog.Infoln("[inject] eBPF can injection.")
  893. return nil
  894. }
  895. if err != nil {
  896. klog.WithError(err).Errorf("[inject] Error message during release phase.")
  897. return err
  898. }
  899. // 原指令校验通过
  900. if !jvmInjector.PreCheck.NeedInjectionCheck {
  901. return err
  902. }
  903. printCodeData(jvmInjector.ReleaseLibNetInfo)
  904. _type, _, err := FindLibBaseByPathFromProcMaps(pid, jvmInjector.DebugLibNetInfo.ProcLoadPath)
  905. if err != nil {
  906. // load so
  907. if _type == 1 {
  908. klog.Infoln("[inject] start load so.")
  909. resCode := jvmInjector.jvmInjectLib()
  910. if resCode == 0 {
  911. klog.Infof("[inject] load so successful. proc load path is [%s], file path in node is [%s]", jvmInjector.DebugLibNetInfo.ProcLoadPath, jvmInjector.DebugLibNetInfo.LibPath)
  912. jvmInjector.PreCheck.LoadingCheck = true
  913. } else {
  914. klog.Errorf("[inject] Failed load so. so path is [%s]", jvmInjector.DebugLibNetInfo.LibPath)
  915. return fmt.Errorf("[inject] Failed load so. code is %d so path is [%s]", resCode, jvmInjector.DebugLibNetInfo.LibPath)
  916. }
  917. }
  918. } else {
  919. klog.Infoln("[inject] so already loaded.")
  920. jvmInjector.PreCheck.LoadingCheck = true
  921. }
  922. if !jvmInjector.PreCheck.LoadingCheck {
  923. klog.Infof("Failed load so")
  924. return err
  925. }
  926. err = jvmInjector.findDebugFuncContextFromLibPath()
  927. if err != nil {
  928. klog.WithError(err).Errorf("[inject] Failed to find debug Func Context from libPath")
  929. return err
  930. }
  931. if !jvmInjector.validateAllPreCheck() {
  932. klog.Errorf("[inject] validateAllPreCheck failed: "+
  933. "NeedInjectionCheck=%v, LoadingCheck=%v, IoFdCheck=%v, NetSendFuncCheck=%v",
  934. jvmInjector.PreCheck.NeedInjectionCheck,
  935. jvmInjector.PreCheck.LoadingCheck,
  936. jvmInjector.PreCheck.IoFdCheck,
  937. jvmInjector.PreCheck.NetSendFuncCheck,
  938. )
  939. return err
  940. }
  941. // 修改
  942. debugFuncEnterAddr := uintptr(jvmInjector.DebugLibNetInfo.FuncSymbol.SymAddr)
  943. debugFuncGetTTLEnterAddr := uintptr(jvmInjector.DebugLibNetInfo.FuncGetTTLSymbol.SymAddr)
  944. debugFuncConvert0EnterAddr := uintptr(jvmInjector.DebugLibNetInfo.FuncConvert0Symbol.SymAddr)
  945. debugIoFdAddr := uintptr(jvmInjector.DebugLibNetInfo.InnerSymbol.IO_fd_fdID.SymAddr)
  946. debugNetSendAddr := uintptr(jvmInjector.DebugLibNetInfo.InnerSymbol.NET_Send.SymAddr)
  947. originFuncEnterAddr := uintptr(jvmInjector.ReleaseLibNetInfo.FuncSymbol.SymAddr)
  948. ioFdReleaseTargetAddr := uintptr(jvmInjector.ReleaseLibNetInfo.InnerSymbol.IO_fd_fdID.TargetAddr)
  949. netSendReleaseTargetAddr := uintptr(jvmInjector.ReleaseLibNetInfo.InnerSymbol.NET_Send.TargetAddr)
  950. fmt.Printf("<0x%x> -> <0x%x>\n", originFuncEnterAddr, debugFuncEnterAddr)
  951. fmt.Printf("<0x%x> -> <0x%x>\n", debugIoFdAddr, ioFdReleaseTargetAddr)
  952. fmt.Printf("<0x%x> -> <0x%x>\n", debugNetSendAddr, netSendReleaseTargetAddr)
  953. fmt.Printf("conver0 -> <0x%x>\n", debugFuncConvert0EnterAddr)
  954. fmt.Printf("getttl -> <0x%x>\n", debugFuncGetTTLEnterAddr)
  955. // 附加到目标进程
  956. klog.Infof("attach")
  957. err = syscall.PtraceAttach(pid)
  958. if err != nil {
  959. fmt.Printf("ptrace ATTACH: %v", err)
  960. }
  961. // 等待目标进程停止
  962. klog.Infof("attach Wait")
  963. if _, err := syscall.Wait4(pid, nil, 0, nil); err != nil {
  964. fmt.Printf("wait4: %v", err)
  965. return err
  966. }
  967. //time.Now().UnixNano()
  968. // 修改目标的内存
  969. klog.Infof("modifyIoFdTargetAddr")
  970. err = modifyIoFdTargetAddr(pid, debugIoFdAddr, ioFdReleaseTargetAddr, debugFuncGetTTLEnterAddr)
  971. if err != nil {
  972. klog.Error(err)
  973. PtraceDetach(pid)
  974. return err
  975. }
  976. klog.Infof("modifyNetSetTargetAddr")
  977. err = modifyNetSetTargetAddr(pid, debugNetSendAddr, netSendReleaseTargetAddr, debugFuncConvert0EnterAddr)
  978. if err != nil {
  979. klog.Error(err)
  980. PtraceDetach(pid)
  981. return err
  982. }
  983. // 二次效验 读取并验证地址
  984. klog.Infof("checkDebugFuncSymAfterChange")
  985. _, err = jvmInjector.checkDebugFuncSymAfterChange()
  986. printCodeData(jvmInjector.ReleaseLibNetInfo)
  987. printCodeData(jvmInjector.DebugLibNetInfo)
  988. // 效验目标函数内地址是否与预期一致
  989. if !jvmInjector.validateAllModifyCheck() && err == nil {
  990. klog.WithError(err).Errorf("[inject] failed validateAllModifyCheck")
  991. PtraceDetach(pid)
  992. return err
  993. }
  994. // 更新函数入口
  995. klog.Infof("modifyReleaseFuncEnter")
  996. err = modifyReleaseFuncEnter(pid, originFuncEnterAddr, debugFuncEnterAddr)
  997. if err != nil {
  998. klog.WithError(err).Errorf("[inject] failed modifyReleaseFuncEnter")
  999. PtraceDetach(pid)
  1000. return err
  1001. }
  1002. // 校验jmp地址修改正确 临时注释
  1003. klog.Infof("checkReleaseFuncSymAfterChange")
  1004. errReleaseFuncSymAfterChange := jvmInjector.checkReleaseFuncSymAfterChange()
  1005. if errReleaseFuncSymAfterChange != nil {
  1006. klog.WithError(errReleaseFuncSymAfterChange).Errorf("[inject] failed checkReleaseFuncSymAfterChange")
  1007. // 回滚
  1008. if len(jvmInjector.ReleaseLibNetInfo.FuncSymbol.OriginCode) == 12 {
  1009. err = restoreOriginalInstructions(pid, originFuncEnterAddr, jvmInjector.ReleaseLibNetInfo.FuncSymbol.OriginCode)
  1010. if err != nil {
  1011. klog.WithError(err).Errorf("[inject] failed restoreOriginalInstructions")
  1012. PtraceDetach(pid)
  1013. return err
  1014. }
  1015. }
  1016. //PtraceDetach(pid)
  1017. //return errReleaseFuncSymAfterChange
  1018. }
  1019. return PtraceDetach(pid)
  1020. }
  1021. func PtraceDetach(pid int) error {
  1022. // 恢复执行
  1023. klog.Infof("Detach")
  1024. if err := syscall.PtraceDetach(pid); err != nil {
  1025. klog.Errorf("ptrace DETACH: %v", err)
  1026. return err
  1027. }
  1028. return nil
  1029. }