inject_linux_arm64.go 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390
  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. "bytes"
  13. "fmt"
  14. "github.com/coroot/coroot-node-agent/utils"
  15. klog "github.com/sirupsen/logrus"
  16. "os"
  17. "path/filepath"
  18. "strconv"
  19. "strings"
  20. "syscall"
  21. "golang.org/x/arch/arm64/arm64asm"
  22. "golang.org/x/arch/x86/x86asm"
  23. //"time"
  24. "unsafe"
  25. )
  26. var jumpOps = map[arm64asm.Op]bool{
  27. arm64asm.CBZ: true,
  28. arm64asm.CBNZ: true,
  29. arm64asm.B: true,
  30. arm64asm.TBZ: true,
  31. arm64asm.TBNZ: true,
  32. arm64asm.ADRP: true,
  33. arm64asm.BL: true,
  34. arm64asm.BLR: true,
  35. arm64asm.RET: true,
  36. arm64asm.BR: true,
  37. }
  38. const NOP_ENC = 0xd503201f
  39. const RET_ENC = 0xd65f03c0
  40. var nopBytes = []byte{0xd5, 0x03, 0x20, 0x1f}
  41. const (
  42. IO_FD_FDID_SYM_OFFSET = 192
  43. NET_SEND_SYM_OFFSET = 776
  44. )
  45. const (
  46. OFFSET_0 = 0
  47. OFFSET_16_BIT = 1
  48. OFFSET_32_BIT = 2
  49. OFFSET_48_BIT = 3
  50. PC_START = 0
  51. BLR_X18 = 0xd63f0240
  52. )
  53. var SrcAddrOffset uintptr
  54. const ChangeEncLen = 3
  55. type InstInfo struct {
  56. SymName string
  57. SymSize uint64
  58. SymAddr uint64
  59. PC uint64
  60. Inst arm64asm.Inst
  61. OriginInst arm64asm.Inst
  62. OriginCode []byte
  63. TargetAddr uint64
  64. OriginTargetAddr uint64
  65. TargetEnc uint32
  66. OriginEnc uint32
  67. }
  68. type InnerSymbolInfo struct {
  69. IO_fd_fdID_ADRP InstInfo
  70. IO_fd_fdID_ADD InstInfo
  71. NET_Send InstInfo
  72. }
  73. //
  74. //type LibNetInfo struct {
  75. // LibName string
  76. // LibPath string
  77. // FuncSymbol InstInfo
  78. // InnerSymbol InnerSymbolInfo
  79. //}
  80. //
  81. //type UprobeData struct {
  82. // Offset int
  83. // Func string
  84. // ELFPath string
  85. //}
  86. //
  87. //type JvmInjector struct {
  88. // Pid int
  89. // ReleaseLibNetInfo LibNetInfo
  90. // DebugLibNetInfo LibNetInfo
  91. // RecodeInfo LibNetInfo
  92. // // 原方法首个指令不为jmp | ReleaseLibNetInfo 读取无异常
  93. // PreCheck struct {
  94. // NeedInjectionCheck bool // 原指令校验 true表示可以继续执行注入
  95. // LoadingCheck bool // true 表示加载成功
  96. // IoFdCheck bool // fd地址校验
  97. // NetSendFuncCheck bool // netsend校验
  98. // EbpfCanInjection bool
  99. // }
  100. // AfterCheck struct {
  101. // IoFdCheck bool
  102. // NetSendFuncCheck bool
  103. // }
  104. // Uprobe UprobeData
  105. // Rootfs string
  106. //}
  107. func (j *JvmInjector) checkEnc(code []byte, start, len uint64, enc uint32) error {
  108. end := start + len
  109. inst, err := arm64asm.Decode(code[start:end])
  110. if err != nil {
  111. return fmt.Errorf("Decode code[%d:%d] %s: err is <%v>", start, end, arm64asm.GNUSyntax(inst), err)
  112. } else {
  113. if inst.Enc != enc {
  114. return fmt.Errorf("Validation inst failed:'%s <+%d>: %s'", fmt.Sprintf("0x%016x", j.ReleaseLibNetInfo.FuncSymbol.SymAddr+start), start, arm64asm.GNUSyntax(inst))
  115. }
  116. }
  117. return nil
  118. }
  119. func (j *JvmInjector) findReleaseAddressInfoFromMem() error {
  120. funcAbsAddress := j.ReleaseLibNetInfo.FuncSymbol.SymAddr
  121. releaseFuncSym := InnerSymbolInfo{}
  122. code, err := j.readMemory(funcAbsAddress, j.ReleaseLibNetInfo.FuncSymbol.SymSize)
  123. if err != nil {
  124. return err
  125. }
  126. klog.Infof("[inject] SymSize %d", j.ReleaseLibNetInfo.FuncSymbol.SymSize)
  127. // cwso是否载入,载入则从recode判断指令 ToDo更新位置信息
  128. baseAddress, _, err := j.findLibBaseFromProcMaps(j.DebugLibNetInfo.LibName)
  129. if err == nil {
  130. j.PreCheck.LoadingCheck = true
  131. klog.Infof("[inject] so already loaded check enc...")
  132. // 获取recode地址
  133. klog.Infof("[inject] baseAddress %d", baseAddress)
  134. recodeFunctionSym, err := GetFunctionOffset(j.DebugLibNetInfo.LibPath, j.RecodeInfo.FuncSymbol.SymName)
  135. if err != nil {
  136. klog.WithError(err).Errorf("[inject] get recode function symbol failed.")
  137. return err
  138. }
  139. j.RecodeInfo.FuncSymbol.SymAddr = baseAddress + recodeFunctionSym.Value
  140. recode, err := j.readMemory(j.RecodeInfo.FuncSymbol.SymAddr, 4)
  141. if err != nil {
  142. return err
  143. }
  144. if !bytes.Equal(recode, nopBytes) {
  145. j.PreCheck.EbpfCanInjection = true
  146. klog.Infof("[inject] successful...")
  147. return nil
  148. }
  149. klog.Infof("[inject] so already loaded. check failed.")
  150. }
  151. /*
  152. 0x0000fffbdc0ef24c <+56>: str x2, [x6,#120]
  153. 0x0000fffbdc0ef250 <+60>: str x3, [x29,#96]
  154. 0x0000fffbdc0ef254 <+64>: mov x21, x0
  155. 0x0000fffbdc0ef258 <+68>: mov w28, w4
  156. 0x0000fffbdc0ef25c <+72>: mov w23, w5
  157. */
  158. // 修改指令效验方式为首地址 w5向上偏移4段
  159. // TODO Position Independent check
  160. klog.Infof("[inject] start check...")
  161. if os.Getenv("jvm_offset") != "" {
  162. if off, err := strconv.Atoi(os.Getenv("jvm_offset")); err == nil {
  163. SrcAddrOffset = uintptr(off)
  164. if SrcAddrOffset == 0 {
  165. return fmt.Errorf("[attach] jvm_offset have no hook point.")
  166. } else {
  167. klog.Infof("[attach] use jvm_offset off:%d", SrcAddrOffset)
  168. return nil
  169. }
  170. }
  171. }
  172. pc := uint64(0)
  173. var findw5 bool
  174. var findx3 bool
  175. for pc < uint64(len(code)) {
  176. //err = j.checkEnc(code, pc, 4, 0x2a0503f3) // mov w19, w5
  177. inst, err := arm64asm.Decode(code[pc:])
  178. if err == nil && inst.Op == arm64asm.STR && inst.Args[0] == arm64asm.X3 && !findw5 {
  179. findx3 = true
  180. forwardOk := true
  181. // Step 1: 向后检查
  182. for i := 0; i <= ChangeEncLen; i++ {
  183. offset := pc + uint64(i*4)
  184. if offset+4 > uint64(len(code)) {
  185. forwardOk = false
  186. break
  187. }
  188. inst, err := arm64asm.Decode(code[offset : offset+4])
  189. if err != nil || jumpOps[inst.Op] {
  190. forwardOk = false
  191. break
  192. }
  193. }
  194. if forwardOk {
  195. SrcAddrOffset = uintptr(pc)
  196. klog.Infof("[inject] x3 start check ok [after]... SrcAddrOffset:%d", SrcAddrOffset)
  197. return nil
  198. }
  199. }
  200. if err == nil && inst.Op == arm64asm.MOV && inst.Args[1] == arm64asm.W5 && !findx3 {
  201. findw5 = true
  202. // Step 1: 向前检查(不包含当前指令)
  203. if pc >= uint64(ChangeEncLen*4) {
  204. backwardOk := true
  205. for i := 1; i <= ChangeEncLen; i++ {
  206. offset := pc - uint64(i*4)
  207. inst, err := arm64asm.Decode(code[offset : offset+4])
  208. if err != nil || jumpOps[inst.Op] {
  209. backwardOk = false
  210. break
  211. }
  212. }
  213. if backwardOk {
  214. SrcAddrOffset = uintptr(pc - uint64(ChangeEncLen*4))
  215. klog.Infof("[inject] w5 start check ok [before]... SrcAddrOffset:%d", SrcAddrOffset)
  216. return nil
  217. }
  218. }
  219. // Step 2: 向前失败 → 尝试向后
  220. forwardOk := true
  221. for i := 0; i <= ChangeEncLen; i++ {
  222. offset := pc + uint64(i*4)
  223. if offset+4 > uint64(len(code)) {
  224. forwardOk = false
  225. break
  226. }
  227. inst, err := arm64asm.Decode(code[offset : offset+4])
  228. if err != nil || jumpOps[inst.Op] {
  229. forwardOk = false
  230. break
  231. }
  232. }
  233. if forwardOk {
  234. SrcAddrOffset = uintptr(pc)
  235. klog.Infof("[inject] w5 start check ok [after]... SrcAddrOffset:%d", SrcAddrOffset)
  236. return nil
  237. }
  238. }
  239. pc += 4
  240. }
  241. klog.Infof("[inject] SrcAddrOffset:", SrcAddrOffset)
  242. //aaa, _ := strconv.Atoi(os.Getenv("offset"))
  243. //SrcAddrOffset = uintptr(aaa)
  244. if SrcAddrOffset == 0 {
  245. return fmt.Errorf("[attach] have no hook point.")
  246. }
  247. //err = j.checkEnc(code, 56, 4, 0xf9003cc2)
  248. //if err != nil {
  249. // return err
  250. //}
  251. //err = j.checkEnc(code, 60, 4, 0xf90033a3)
  252. //if err != nil {
  253. // return err
  254. //}
  255. //err = j.checkEnc(code, 64, 4, 0xaa0003f5)
  256. //if err != nil {
  257. // return err
  258. //}
  259. //err = j.checkEnc(code, 68, 4, 0x2a0403fc)
  260. //if err != nil {
  261. // return err
  262. //}
  263. //err = j.checkEnc(code, 72, 4, 0x2a0503f7)
  264. //if err != nil {
  265. // return err
  266. //}
  267. j.ReleaseLibNetInfo.InnerSymbol = releaseFuncSym
  268. j.ReleaseLibNetInfo.FuncSymbol.OriginCode = code[0:4]
  269. return nil
  270. }
  271. func (j *JvmInjector) findDebugAddressInfoFromMem() (uint64, error) {
  272. funcAbsAddress := j.DebugLibNetInfo.FuncSymbol.SymAddr
  273. debugFuncSym := InnerSymbolInfo{}
  274. //debugFuncSym.FuncSymbol.SymAddr = funcAbsAddress
  275. //offset := sym.Value
  276. size := j.DebugLibNetInfo.FuncSymbol.SymSize
  277. code, err := j.readMemory(funcAbsAddress, size)
  278. //klog.Infoln(code, err)
  279. if err != nil {
  280. return 0, err
  281. }
  282. pc := uint64(0)
  283. preContext := InstInfo{}
  284. for pc < uint64(len(code)) {
  285. inst, err := arm64asm.Decode(code[pc:])
  286. if err != nil {
  287. klog.Infof("Decode error at offset 0x%x: %v\n", pc, err)
  288. pc++ // Skip this byte and try to decode again
  289. continue
  290. }
  291. //klog.Infof("Decoded instuction at 0x%x: %v\n", funcAbsAddress+pc, Inst)
  292. //klog.Infof("Decoded x86 instuction at 0x%x: %v\n", funcAbsAddress+pc, x86asm.IntelSyntax(inst, 0, nil))
  293. //klog.Infof("Decoded GNU instuction at 0x%x: %v\n", funcAbsAddress+pc, x86asm.GNUSyntax(Inst, 0, nil))
  294. currentData := InstInfo{
  295. PC: pc,
  296. SymAddr: funcAbsAddress + pc,
  297. Inst: inst,
  298. }
  299. if pc == 0 {
  300. j.DebugLibNetInfo.FuncSymbol.PC = currentData.PC
  301. j.DebugLibNetInfo.FuncSymbol.Inst = currentData.Inst
  302. j.DebugLibNetInfo.FuncSymbol.OriginInst = currentData.Inst
  303. }
  304. // IO_fd_fdID
  305. if pc == IO_FD_FDID_SYM_OFFSET {
  306. if inst.Op == arm64asm.ADD {
  307. if preContext.Inst.Op == arm64asm.ADRP && inst.Args[0].String() == arm64asm.X0.String() {
  308. debugFuncSym.IO_fd_fdID_ADD = currentData
  309. debugFuncSym.IO_fd_fdID_ADD.SymName = "<IO_fd_fdID ADD>(Debug)"
  310. debugFuncSym.IO_fd_fdID_ADD.OriginEnc = currentData.Inst.Enc
  311. debugFuncSym.IO_fd_fdID_ADD.TargetEnc = j.ReleaseLibNetInfo.InnerSymbol.IO_fd_fdID_ADD.Inst.Enc & uint32(0xFFFFF000)
  312. /*
  313. |31 immlo | 27-24 |23 immhi 5|4 Rd 0|
  314. 1 00 1 0000 0001 1000 0000 1110 011 0 0000
  315. 9 0 1 8 0 e 6 0
  316. ( target- pc >> zero(12) )/4k
  317. */
  318. debugFuncSym.IO_fd_fdID_ADRP = preContext
  319. debugFuncSym.IO_fd_fdID_ADRP.SymName = "<IO_fd_fdID ADRP>(Debug)"
  320. debugFuncSym.IO_fd_fdID_ADRP.OriginEnc = preContext.Inst.Enc
  321. releaseTarget := j.ReleaseLibNetInfo.InnerSymbol.IO_fd_fdID_ADRP.TargetAddr
  322. offset := (releaseTarget - preContext.SymAddr&0xFFFFFFFFFFFFF000) / (1 << 12)
  323. immhi := offset >> 2
  324. immlo := offset & 0x03
  325. decimal31_24 := (1 << 7) + (immlo << 5) + (1 << 4)
  326. targetEnc := (decimal31_24 << 24) | (immhi << 5)
  327. debugFuncSym.IO_fd_fdID_ADRP.TargetEnc = uint32(targetEnc)
  328. j.PreCheck.IoFdCheck = true
  329. } else {
  330. return 0, fmt.Errorf("The decoded instruction is not a ADRP or X0. inst:<%s>, arg:<%s>", inst.String(), inst.Args)
  331. }
  332. } else {
  333. return 0, fmt.Errorf("The decoded instruction is not a ADD. inst:<%s>, arg:<%s>", inst.String(), inst.Args)
  334. }
  335. }
  336. if pc == NET_SEND_SYM_OFFSET {
  337. debugFuncSym.NET_Send = currentData
  338. //klog.Infof("4 call Decoded instuction at 0x%x: %v\n", funcAbsAddress+pc, inst)
  339. //relOffset, ok := (inst.Args[0].(x86asm.Rel))
  340. klog.Infoln(inst)
  341. klog.Infoln(inst.Args)
  342. //if !ok {
  343. // return 0, fmt.Errorf("The decoded instruction is not a Rel.")
  344. //}
  345. //targetAddress := currentData.SymAddr + uint64(inst.Len) + uint64(relOffset)
  346. //debugFuncSym.NET_Send.TargetAddr = targetAddress
  347. debugFuncSym.NET_Send.SymName = "<NET_Send>(Debug)"
  348. //klog.Infof("Find %s Target address: 0x%x\n", debugFuncSym.NET_Send.SymName, targetAddress)
  349. //
  350. //// 保存原始数据
  351. //debugFuncSym.NET_Send.OriginTargetAddr = targetAddress
  352. //debugFuncSym.NET_Send.OriginInst = currentData.Inst
  353. j.PreCheck.NetSendFuncCheck = true
  354. }
  355. preContext = InstInfo{
  356. PC: pc,
  357. SymAddr: funcAbsAddress + pc,
  358. Inst: inst,
  359. }
  360. pc += 4
  361. }
  362. j.DebugLibNetInfo.InnerSymbol = debugFuncSym
  363. return 0, nil
  364. }
  365. //func (j *JvmInjector) checkDebugFuncSymAfterChange() (uint64, error) {
  366. // funcAbsAddress := j.DebugLibNetInfo.FuncSymbol.SymAddr
  367. // debugFuncSym := InnerSymbolInfo{}
  368. // code, err := j.readMemory(funcAbsAddress, j.DebugLibNetInfo.FuncSymbol.SymSize)
  369. // if err != nil {
  370. // return 0, err
  371. // }
  372. //
  373. // pc := uint64(0)
  374. // preContext := InstInfo{}
  375. //
  376. // for pc < uint64(len(code)) {
  377. // inst, err := x86asm.Decode(code[pc:], 64)
  378. // if err != nil {
  379. // klog.Infof("Decode error at offset 0x%x: %v\n", pc, err)
  380. // pc++ // Skip this byte and try to decode again
  381. // continue
  382. // }
  383. // //klog.Infof("Decoded instuction at 0x%x: %v\n", funcAbsAddress+pc, Inst)
  384. // //klog.Infof("Decoded x86 instuction at 0x%x: %v\n", funcAbsAddress+pc, x86asm.IntelSyntax(inst, 0, nil))
  385. // //klog.Infof("Decoded GNU instuction at 0x%x: %v\n", funcAbsAddress+pc, x86asm.GNUSyntax(Inst, 0, nil))
  386. // currentData := InstInfo{
  387. // PC: pc,
  388. // SymAddr: funcAbsAddress + pc,
  389. // Inst: inst,
  390. // }
  391. // if pc == NET_SEND_SYM_OFFSET {
  392. // klog.Infof("Instuction at 0x%x: %v\n", preContext.PC, preContext.Inst)
  393. // debugFuncSym.IO_fd_fdID = currentData
  394. // debugFuncSym.IO_fd_fdID.SymName = "<IO_fd_fdID>(Debug)"
  395. // // 计算目标地址
  396. // if currentData.Inst.Op == x86asm.MOV &&
  397. // len(currentData.Inst.Args) == 4 &&
  398. // currentData.Inst.Args[0] != nil &&
  399. // currentData.Inst.Args[0] == x86asm.RDX &&
  400. // currentData.Inst.Args[1] != nil {
  401. // if mem, ok := currentData.Inst.Args[1].(x86asm.Mem); ok && mem.Base == x86asm.RIP {
  402. // // 直接从Mem结构体中读取偏移
  403. // relOffset := mem.Disp
  404. // targetAddress := currentData.SymAddr + uint64(currentData.Inst.Len) + uint64(relOffset)
  405. // klog.Infof("Find %s Target address: 0x%x\n", debugFuncSym.IO_fd_fdID.SymName, targetAddress)
  406. // debugFuncSym.IO_fd_fdID.TargetAddr = targetAddress
  407. // //j.PreCheck.IoFdCheck = true
  408. //
  409. // if targetAddress == j.ReleaseLibNetInfo.InnerSymbol.IO_fd_fdID.TargetAddr {
  410. // j.DebugLibNetInfo.InnerSymbol.IO_fd_fdID.TargetAddr = targetAddress
  411. // j.DebugLibNetInfo.InnerSymbol.IO_fd_fdID.Inst = currentData.Inst
  412. // j.AfterCheck.IoFdCheck = true
  413. // klog.Infoln("ok")
  414. // }
  415. // } else {
  416. // return 0, fmt.Errorf("The instruction does not use RIP-relative addressing.")
  417. // }
  418. // } else {
  419. // return 0, fmt.Errorf("The decoded instruction is not a MOV to RDX.")
  420. // }
  421. // }
  422. // if pc == NET_SEND_SYM_OFFSET {
  423. // debugFuncSym.NET_Send = currentData
  424. // //klog.Infoln(currentData.IntelInst)
  425. // //klog.Infof("4 call Decoded instuction at 0x%x: %v\n", funcAbsAddress+pc, inst)
  426. // relOffset, ok := (inst.Args[0].(x86asm.Rel))
  427. // if !ok {
  428. // return 0, fmt.Errorf("The decoded instruction is not a Rel.")
  429. // }
  430. // targetAddress := currentData.SymAddr + uint64(inst.Len) + uint64(relOffset)
  431. // debugFuncSym.NET_Send.TargetAddr = targetAddress
  432. // debugFuncSym.NET_Send.SymName = "<NET_Send>(Debug)"
  433. // klog.Infof("Find %s Target address: 0x%x\n", debugFuncSym.NET_Send.SymName, targetAddress)
  434. //
  435. // if targetAddress == j.ReleaseLibNetInfo.InnerSymbol.NET_Send.TargetAddr {
  436. // j.DebugLibNetInfo.InnerSymbol.NET_Send.TargetAddr = targetAddress
  437. // j.DebugLibNetInfo.InnerSymbol.NET_Send.Inst = currentData.Inst
  438. // j.AfterCheck.NetSendFuncCheck = true
  439. // }
  440. // }
  441. //
  442. // preContext = InstInfo{
  443. // PC: pc,
  444. // SymAddr: funcAbsAddress + pc,
  445. // Inst: inst,
  446. // }
  447. // pc += uint64(inst.Len)
  448. // }
  449. // return 0, nil
  450. //}
  451. func (j *JvmInjector) checkReleaseFuncSymAfterChange() error {
  452. funcAbsAddress := j.ReleaseLibNetInfo.FuncSymbol.SymAddr
  453. code, err := j.readMemory(funcAbsAddress, j.ReleaseLibNetInfo.FuncSymbol.SymSize)
  454. if err != nil {
  455. return fmt.Errorf("readMemory error in checkReleaseFuncSymAfterChange <%v>", err)
  456. }
  457. inst, err := x86asm.Decode(code[0:], 64)
  458. if err != nil {
  459. return fmt.Errorf("Decode error in checkReleaseFuncSymAfterChange <%v>", err)
  460. }
  461. if inst.Op != x86asm.JMP {
  462. return fmt.Errorf("The instruction does not JMP.")
  463. }
  464. relOffset, ok := inst.Args[0].(x86asm.Rel)
  465. if !ok {
  466. return fmt.Errorf("The instruction does not use RIP-relative addressing.")
  467. }
  468. // 验证target与Debug入口是否一致
  469. targetAddress := funcAbsAddress + uint64(inst.Len) + uint64(relOffset)
  470. if targetAddress != j.DebugLibNetInfo.FuncSymbol.SymAddr {
  471. return fmt.Errorf("Function entry jmp address does not match expectations.")
  472. }
  473. return nil
  474. }
  475. // readMemory 用于读取指定地址的内存数据
  476. func (j *JvmInjector) readMemory(address uint64, size uint64) ([]byte, error) {
  477. memFile := fmt.Sprintf("/proc/%d/mem", j.Pid)
  478. file, err := os.Open(memFile)
  479. if err != nil {
  480. return nil, err
  481. }
  482. defer file.Close()
  483. data := make([]byte, size)
  484. _, err = file.ReadAt(data, int64(address))
  485. if err != nil {
  486. return nil, err
  487. }
  488. return data, nil
  489. }
  490. // findLibraryBases 用于在 /proc/[pid]/maps 文件中查找库的所有基地址
  491. func findLibraryBasesList(pid int, libraryName string, libPath string) ([]uint64, error) {
  492. mapsFile := fmt.Sprintf("/proc/%d/maps", pid)
  493. file, err := os.Open(mapsFile)
  494. if err != nil {
  495. return nil, err
  496. }
  497. defer file.Close()
  498. var bases []uint64
  499. scanner := bufio.NewScanner(file)
  500. for scanner.Scan() {
  501. line := scanner.Text()
  502. if strings.Contains(line, libraryName) && strings.Contains(line, libPath) {
  503. var start, end uint64
  504. fmt.Sscanf(line, "%x-%x", &start, &end)
  505. bases = append(bases, start)
  506. }
  507. }
  508. if len(bases) == 0 {
  509. return nil, fmt.Errorf("library %s not found", libraryName)
  510. }
  511. return bases, nil
  512. }
  513. func (j *JvmInjector) findLibBaseFromProcMaps(libName string) (uint64, string, error) {
  514. mapsFile := fmt.Sprintf("/proc/%d/maps", j.Pid)
  515. file, err := os.Open(mapsFile)
  516. if err != nil {
  517. return 0, "", err
  518. }
  519. defer file.Close()
  520. var start, end uint64
  521. scanner := bufio.NewScanner(file)
  522. for scanner.Scan() {
  523. line := scanner.Text()
  524. if strings.Contains(line, "/"+libName) {
  525. fmt.Sscanf(line, "%x-%x", &start, &end)
  526. fields := strings.Fields(line)
  527. if len(fields) > 5 {
  528. path := fields[5]
  529. if strings.HasSuffix(path, ".so") {
  530. klog.Infof("Found library %s\n", path)
  531. return start, path, nil
  532. }
  533. }
  534. }
  535. }
  536. return 1, "", fmt.Errorf("[findLibBaseFromProcMaps] library %s not found", libName)
  537. }
  538. //func (j *JvmInjector) getFunctionOffset(libPath, functionName string) (elf.Symbol, error) {
  539. // elfFile, err := elf.Open(libPath)
  540. // if err != nil {
  541. // return elf.Symbol{}, fmt.Errorf("failed to open ELF file: %v", err)
  542. // }
  543. // defer elfFile.Close()
  544. //
  545. // symbols, err := elfFile.DynamicSymbols()
  546. // if err != nil {
  547. // return elf.Symbol{}, fmt.Errorf("failed to read dynamic symbols: %v", err)
  548. // }
  549. //
  550. // for _, sym := range symbols {
  551. // if sym.Name == functionName {
  552. // return sym, nil
  553. // }
  554. // }
  555. //
  556. // //textSection := elfFile.Section(".text")
  557. // //if textSection == nil {
  558. // // klog.Infoln("textSection is null")
  559. // // //return nil
  560. // //}
  561. // //textSectionData, err := textSection.Data()
  562. // //if err != nil {
  563. // // klog.Infoln("textSectionData error is", err)
  564. // // //return nil
  565. // //}
  566. // //textSectionLen := uint64(len(textSectionData) - 1)
  567. //
  568. // return elf.Symbol{}, fmt.Errorf("function %s not found", functionName)
  569. //}
  570. //var PID string
  571. //func (j *JvmInjector) findReleaseFuncContextFromLibPath() error {
  572. // // 获取release库的基地址
  573. // baseAddress, libPath, err := j.findLibBaseFromProcMaps(j.ReleaseLibNetInfo.LibName)
  574. // functionName := j.ReleaseLibNetInfo.FuncSymbol.SymName
  575. // j.ReleaseLibNetInfo.LibPath = libPath
  576. // libName := j.ReleaseLibNetInfo.LibName
  577. // if err != nil {
  578. // return fmt.Errorf("Error finding base addresses: %v", err)
  579. // }
  580. // klog.Infof("Base address of (%s)%s: %x\n", "", libName, baseAddress)
  581. //
  582. // // 获取函数的偏移量
  583. // functionSym, err := j.getFunctionOffset(libPath, functionName)
  584. //
  585. // // 计算函数的实际内存地址
  586. // j.ReleaseLibNetInfo.FuncSymbol.SymAddr = baseAddress + functionSym.Value
  587. // j.ReleaseLibNetInfo.FuncSymbol.SymSize = functionSym.Size
  588. // if err != nil {
  589. // return fmt.Errorf("Error getting function offset: %v", err)
  590. // }
  591. // klog.Infof("Actual memory address of %s at base 0x%x: 0x%x\n", functionName, baseAddress, j.ReleaseLibNetInfo.FuncSymbol.SymAddr)
  592. // err = j.findReleaseAddressInfoFromMem()
  593. //
  594. // if err != nil {
  595. // return err
  596. // } else {
  597. // j.PreCheck.NeedInjectionCheck = true
  598. // }
  599. //
  600. // return nil
  601. //}
  602. func (j *JvmInjector) InitProg() error {
  603. // 获取release库的基地址
  604. klog.Infof("[InitProg] find lib base from proc maps: %d|%s", j.Pid, j.ReleaseLibNetInfo.LibName)
  605. baseAddress, releaseSoFilePathInProc, mapFilesPath, deleted, err := FindLibBaseFromProcMaps(j.Pid, j.ReleaseLibNetInfo.LibName)
  606. //j.ReleaseLibNetInfo.LibPath = releaseSoFilePathInProc
  607. j.ReleaseLibNetInfo.FileDeleted = deleted
  608. j.ReleaseLibNetInfo.MapFile = mapFilesPath
  609. pJvmlibnetPhysicalPath := j.Rootfs + releaseSoFilePathInProc
  610. j.ReleaseLibNetInfo.LibPath = pJvmlibnetPhysicalPath
  611. if err != nil {
  612. klog.Errorf("[InitProg] Error finding base addresses: %v", err)
  613. return fmt.Errorf("[InitProg] Error finding base addresses: %v", err)
  614. }
  615. // jvm prog base
  616. //pJvmLibBaseDir := filepath.Dir(pJvmlibnetPhysicalPath)
  617. jvmLibBaseDir := filepath.Dir(releaseSoFilePathInProc)
  618. // proc maps load path
  619. debugSoFilePathInProc := filepath.Join(jvmLibBaseDir, j.DebugLibNetInfo.LibName)
  620. // Physical path
  621. debugSoFilePhysicalPath := filepath.Join(j.Rootfs, debugSoFilePathInProc)
  622. _, noFileErr := os.Stat(debugSoFilePhysicalPath)
  623. // find cwlibnet.so in proc maps
  624. var readDebugSoPathInMaps string
  625. _, readDebugSoPathInMaps, j.DebugLibNetInfo.MapFile, j.DebugLibNetInfo.FileDeleted, _ = FindLibBaseFromProcMaps(j.Pid, j.DebugLibNetInfo.LibName)
  626. j.DebugLibNetInfo.LibPath = debugSoFilePhysicalPath
  627. j.DebugLibNetInfo.ProcLoadPath = filepath.Join(jvmLibBaseDir, j.DebugLibNetInfo.LibName)
  628. // condition create
  629. pathFromProg := utils.GetDefaultLibsPath("jvm", j.DebugLibNetInfo.LibName)
  630. if noFileErr != nil && readDebugSoPathInMaps == "" && !j.DebugLibNetInfo.FileDeleted {
  631. err = CopyFileAndMatchPermissions(pathFromProg, debugSoFilePhysicalPath, pJvmlibnetPhysicalPath)
  632. klog.Infof("[src:%s],[target:%s],[perm:%s]", pathFromProg, debugSoFilePhysicalPath, pJvmlibnetPhysicalPath)
  633. if err != nil {
  634. klog.WithError(err).Errorf("[InitProg] Error copy.")
  635. return err
  636. }
  637. }
  638. functionName := j.ReleaseLibNetInfo.FuncSymbol.SymName
  639. //j.ReleaseLibNetInfo.LibPath = pJvmlibnetPhysicalPath
  640. klog.Infof("[inject] Base address of [%s]:[%x]", j.ReleaseLibNetInfo.LibName, baseAddress)
  641. // 获取函数的偏移量
  642. functionSym, err := GetFunctionOffset(pJvmlibnetPhysicalPath, functionName)
  643. // 计算函数的实际内存地址
  644. j.ReleaseLibNetInfo.FuncSymbol.SymAddr = baseAddress + functionSym.Value
  645. j.ReleaseLibNetInfo.FuncSymbol.SymSize = functionSym.Size
  646. if err != nil {
  647. klog.WithError(err).Errorf("Error getting function offset")
  648. return err
  649. }
  650. klog.Infof("[inject] Actual memory address of %s at base 0x%x: 0x%x", functionName, baseAddress, j.ReleaseLibNetInfo.FuncSymbol.SymAddr)
  651. if j.Uprobe.ELFPath == "" {
  652. if j.DebugLibNetInfo.FileDeleted {
  653. j.Uprobe.ELFPath = j.DebugLibNetInfo.MapFile
  654. } else {
  655. j.Uprobe.ELFPath = debugSoFilePhysicalPath
  656. }
  657. }
  658. err = j.findReleaseAddressInfoFromMem()
  659. if err != nil {
  660. klog.WithError(err).Errorf("[InitProg] Error copy.")
  661. return err
  662. } else {
  663. j.PreCheck.NeedInjectionCheck = true
  664. }
  665. // copy /NativeAgent
  666. nativePath := filepath.Join(j.Rootfs, "/tmp/NativeAgent")
  667. klog.Infof("[InitProg] init /tmp/NativeAgent.")
  668. if _, err := os.Stat(nativePath); err == nil {
  669. // 目标已存在,直接跳过
  670. klog.Infof("[InitProg] found /tmp/NativeAgent.")
  671. return nil
  672. }
  673. err = CopyFileAndMatchPermissions(utils.GetDefaultAgentsPath("NativeAgent"), nativePath, pJvmlibnetPhysicalPath)
  674. if err != nil {
  675. klog.WithError(err).Errorf("[InitProg] NativeAgent Error copy.")
  676. }
  677. return nil
  678. }
  679. func (j *JvmInjector) findDebugFuncContextFromLibPath() error {
  680. //libName := j.DebugLibNetInfo.LibName
  681. // 获取release库的基地址
  682. baseAddress, libPath, err := FindLibBaseByPathFromProcMaps(j.Pid, j.DebugLibNetInfo.ProcLoadPath)
  683. klog.Infof("[inject] debug base address of [%s] : %x", libPath, baseAddress)
  684. functionName := j.DebugLibNetInfo.FuncSymbol.SymName
  685. //j.DebugLibNetInfo.LibPath = libPath
  686. if err != nil {
  687. klog.WithError(err).Errorf("[inject] error.")
  688. return err
  689. }
  690. // 获取函数的偏移量
  691. functionSym, err := GetFunctionOffset(j.DebugLibNetInfo.LibPath, functionName)
  692. // 计算函数的实际内存地址
  693. j.DebugLibNetInfo.FuncSymbol.SymAddr = baseAddress + functionSym.Value
  694. j.DebugLibNetInfo.FuncSymbol.SymSize = functionSym.Size
  695. if err != nil {
  696. return fmt.Errorf("Error getting debug function:[%s] error: %v", functionName, err)
  697. }
  698. // 计算recode内存地址
  699. recodeFunctionSym, err := GetFunctionOffset(j.DebugLibNetInfo.LibPath, j.RecodeInfo.FuncSymbol.SymName)
  700. j.RecodeInfo.FuncSymbol.SymAddr = baseAddress + recodeFunctionSym.Value
  701. if err != nil {
  702. return fmt.Errorf("Error getting recode function:[%s] error: %v", j.RecodeInfo.FuncSymbol.SymName, err)
  703. }
  704. //klog.Infof("DEBUG Actual memory address of %s at base 0x%x: 0x%x\n", functionName, baseAddress, j.DebugLibNetInfo.FuncSymbol.SymAddr)
  705. //klog.Infof("DEBUG Actual memory address of %s at base 0x%x: 0x%x\n", j.RecodeInfo.FuncSymbol.SymName, baseAddress, j.RecodeInfo.FuncSymbol.SymAddr)
  706. //_, err = j.findDebugAddressInfoFromMem()
  707. //if err != nil {
  708. // return err
  709. //}
  710. return nil
  711. }
  712. func printCodeData(data LibNetInfo) {
  713. klog.Infof("========FuncEnter <0x%x> \n", data.FuncSymbol.SymAddr)
  714. //klog.Infof("%s | CurrentAddr:<0x%x>\nOrigin-TargetAddr:<0x%x> | TargetAddr:<0x%x> \nOrigin-Enc:<0x%x> | TargetEnc:<0x%x> \n",
  715. // data.InnerSymbol.IO_fd_fdID_ADRP.SymName,
  716. // data.InnerSymbol.IO_fd_fdID_ADRP.SymAddr,
  717. // data.InnerSymbol.IO_fd_fdID_ADRP.OriginTargetAddr,
  718. // data.InnerSymbol.IO_fd_fdID_ADRP.TargetAddr,
  719. // data.InnerSymbol.IO_fd_fdID_ADRP.OriginEnc,
  720. // data.InnerSymbol.IO_fd_fdID_ADRP.TargetEnc)
  721. //klog.Infof("\n%s | CurrentAddr:<0x%x>\nOrigin-TargetAddr:<0x%x> | TargetAddr:<0x%x> \nOrigin-Enc:<0x%x> | TargetEnc:<0x%x> \n",
  722. // data.InnerSymbol.IO_fd_fdID_ADD.SymName,
  723. // data.InnerSymbol.IO_fd_fdID_ADD.SymAddr,
  724. // data.InnerSymbol.IO_fd_fdID_ADD.OriginTargetAddr,
  725. // data.InnerSymbol.IO_fd_fdID_ADD.TargetAddr,
  726. // data.InnerSymbol.IO_fd_fdID_ADD.OriginEnc,
  727. // data.InnerSymbol.IO_fd_fdID_ADD.TargetEnc)
  728. //klog.Infof("\n%s | CurrentAddr:<0x%x>\nOrigin-TargetAddr:<0x%x> | TargetAddr:<0x%x>\nOrigin-Inst:<%s> | Inst:<%s> \n",
  729. // data.InnerSymbol.NET_Send.SymName,
  730. // data.InnerSymbol.NET_Send.SymAddr,
  731. // data.InnerSymbol.NET_Send.OriginTargetAddr,
  732. // data.InnerSymbol.NET_Send.TargetAddr,
  733. // arm64asm.GNUSyntax(data.InnerSymbol.NET_Send.OriginInst),
  734. // arm64asm.GNUSyntax(data.InnerSymbol.NET_Send.Inst))
  735. klog.Infoln("========")
  736. }
  737. func (j *JvmInjector) jvmInjectLib() int {
  738. dll := C.CString(j.DebugLibNetInfo.ProcLoadPath) // 替换为实际的DLL路径
  739. rootfs := C.CString(j.Rootfs) // 替换为实际的DLL路径
  740. defer C.free(unsafe.Pointer(dll)) // 确保在使用完字符串后释放内存
  741. result := C.cw_inject_library(C.int(j.Pid), C.int(1), dll, rootfs)
  742. klog.Infof("[inject] [pid:%d][rootfs:%s][dll:%s][result:%d]\n", j.Pid, j.Rootfs, j.DebugLibNetInfo.ProcLoadPath, int(result))
  743. return int(result)
  744. }
  745. func (j *JvmInjector) validateAllPreCheck() bool {
  746. return j.PreCheck.NeedInjectionCheck && j.PreCheck.LoadingCheck
  747. }
  748. func (j *JvmInjector) validateAllModifyCheck() bool {
  749. return j.AfterCheck.IoFdCheck && j.AfterCheck.NetSendFuncCheck
  750. }
  751. /*修改部分*/
  752. func readData(pid int, addr uintptr) (uint64, error) {
  753. var data uint64
  754. if _, err := syscall.PtracePeekData(pid, addr, (*[4]byte)(unsafe.Pointer(&data))[:]); err != nil {
  755. return 0, fmt.Errorf("ptrace PEEKDATA: %v", err)
  756. }
  757. return data, nil
  758. }
  759. func writeData(pid int, addr uintptr, data uint64) error {
  760. if _, err := syscall.PtracePokeData(pid, addr, (*[4]byte)(unsafe.Pointer(&data))[:]); err != nil {
  761. return fmt.Errorf("ptrace POKEDATA: %v", err)
  762. }
  763. return nil
  764. }
  765. func modifyIoFdTargetAddr(pid int, insertAddr, distAddr uintptr) error {
  766. newOffset := distAddr - (insertAddr + 7)
  767. targetAddr := insertAddr + 3
  768. // 获取目标地址处的数据
  769. originalData, err := readData(pid, targetAddr)
  770. if err != nil {
  771. return err
  772. }
  773. // 更新数据中的目标偏移
  774. updatedData := (originalData & 0xFFFFFFFF00000000) | uint64(newOffset&0xFFFFFFFF)
  775. err = writeData(pid, targetAddr, updatedData)
  776. if err != nil {
  777. return err
  778. }
  779. return nil
  780. }
  781. /*
  782. set *(unsigned int*)($debug) = *(unsigned int*)($origin+56)
  783. set *(unsigned int*)($debug+4) = *(unsigned int*)($origin+60)
  784. set *(unsigned int*)($debug+8) = *(unsigned int*)($origin+64)
  785. set *(unsigned int*)($debug+12) = *(unsigned int*)($origin+68)
  786. # SUB SP, SP, #0x080 // 将栈指针下移 8 字节,创建栈帧空间
  787. set *(unsigned int*)($debug+16) = 0xd10203ff
  788. # STR W5, [SP] // 将 W5 的值存储到栈顶
  789. set *(unsigned int*)($debug+20) = 0xb90003e5
  790. # LDR W5, [SP] // 从栈顶加载数据回 W5
  791. set *(unsigned int*)($debug+24) = 0xb94003e5
  792. # ADD SP, SP, #0x080 // 恢复栈指针
  793. set *(unsigned int*)($debug+28) = 0x910203ff
  794. #mov w23, w5
  795. set *(unsigned int*)($debug+32) = *(unsigned int*)($origin+72)
  796. # ret
  797. set *(unsigned int*)($debug+36) = 0xd65f03c0
  798. */
  799. func buildCwNopEnc(pid int, nopAddr, originAddr uintptr) error {
  800. // 指令不为空则返回
  801. originalData, err := readData(pid, nopAddr)
  802. if err != nil {
  803. return err
  804. }
  805. klog.Infof("0x%016x\n", originalData) // 16个字符宽度,左边补0
  806. if originalData != 0xd503201f {
  807. return fmt.Errorf("The cw enc not nop <0x%016x>\n", originAddr)
  808. }
  809. /*
  810. sub sp, sp, #0x80 ; 分配栈空间
  811. str w5, [sp] ; 保存 w5
  812. // nop
  813. ldr w5, [sp] ; 恢复 w5
  814. add sp, sp, #0x80 ; 回收栈空间
  815. */
  816. encodings := []uint64{
  817. 0xd10203ff, // sub sp, sp, #0x80
  818. 0xb90003e5, // str w5, [sp]
  819. NOP_ENC, // nop
  820. 0xb94003e5, // ldr w5, [sp]
  821. 0x910203ff, // add sp, sp, #0x80
  822. }
  823. for i, enc := range encodings {
  824. if enc == NOP_ENC {
  825. continue
  826. }
  827. addr := nopAddr + uintptr(i*4)
  828. if err = setEnc(pid, addr, enc); err != nil {
  829. return err
  830. }
  831. }
  832. //err = setEnc(pid, nopAddr+0, 0xd10203ff)
  833. //if err != nil {
  834. // return err
  835. //}
  836. //err = setEnc(pid, nopAddr+4, 0xb90003e5)
  837. //if err != nil {
  838. // return err
  839. //}
  840. ////nop
  841. //err = setEnc(pid, nopAddr+4+4, 0xd503201f)
  842. //if err != nil {
  843. // return err
  844. //}
  845. //err = setEnc(pid, nopAddr+4+8, 0xb94003e5)
  846. //if err != nil {
  847. // return err
  848. //}
  849. //
  850. //err = setEnc(pid, nopAddr+4+12, 0x910203ff)
  851. //if err != nil {
  852. // return err
  853. //}
  854. var encLine = ChangeEncLen
  855. for i := 0; i < encLine; i++ {
  856. src := originAddr + SrcAddrOffset + 4*uintptr(i)
  857. dst := nopAddr + (4 + 16) + 4*uintptr(i)
  858. err = setEncByAddr(pid, dst, src)
  859. if err != nil {
  860. return err
  861. }
  862. }
  863. //err = setEncByAddr(pid, nopAddr+4+16, originAddr+56)
  864. //if err != nil {
  865. // return err
  866. //}
  867. //err = setEncByAddr(pid, nopAddr+4+20, originAddr+60)
  868. //if err != nil {
  869. // return err
  870. //}
  871. //err = setEncByAddr(pid, nopAddr+4+24, originAddr+64)
  872. //if err != nil {
  873. // return err
  874. //}
  875. //err = setEncByAddr(pid, nopAddr+4+28, originAddr+68)
  876. //if err != nil {
  877. // return err
  878. //}
  879. //
  880. //err = setEncByAddr(pid, nopAddr+4+32, originAddr+72)
  881. //if err != nil {
  882. // return err
  883. //}
  884. //err = setEnc(pid, nopAddr+8 * 4, 0xd65f03c0)
  885. //if err != nil {
  886. // return err
  887. //}
  888. return nil
  889. }
  890. func setEncByAddr(pid int, currentAddr, targetAddr uintptr) error {
  891. // 获取目标地址处的数据
  892. originalData, err := readData(pid, targetAddr)
  893. if err != nil {
  894. return err
  895. }
  896. // 更新数据中的目标偏移
  897. err = writeData(pid, currentAddr, originalData)
  898. if err != nil {
  899. return err
  900. }
  901. return nil
  902. }
  903. func setEnc(pid int, soAddr uintptr, enc uint64) error {
  904. // 更新数据中的目标偏移
  905. err := writeData(pid, soAddr, enc)
  906. if err != nil {
  907. return err
  908. }
  909. return nil
  910. }
  911. func encodeADRP(rd int, targetAddr, originAddr uint64) uint32 {
  912. targetPage := targetAddr >> 12
  913. originPage := originAddr >> 12
  914. imm := int64(targetPage) - int64(originPage) // offset in 4KB pages
  915. if imm < -(1<<20) || imm >= (1<<20) {
  916. panic("adrp offset out of range")
  917. }
  918. immlo := uint32(imm & 0x3) // bits 30:29
  919. immhi := uint32((imm >> 2) & 0x7FFFF) // bits 23:5
  920. return (0x90000000 | (immlo << 29) | (immhi << 5) | uint32(rd))
  921. }
  922. func encodeADDLO12(rd int, targetAddr uint64) uint32 {
  923. imm12 := targetAddr & 0xFFF
  924. return (0x91000000 | uint32(imm12<<10) | uint32(rd<<5) | uint32(rd))
  925. }
  926. /*
  927. set *(unsigned int*)($origin+56) = 0xf2889692
  928. set *(unsigned int*)($origin+60) = 0xf2a363b2
  929. set *(unsigned int*)($origin+64) = 0xf2dfff92
  930. set *(unsigned int*)($origin+68) = 0xf2e00012
  931. # blr x18
  932. set *(unsigned int*)($origin+72) = 0xd63f0240
  933. */
  934. func modifyOriginEnc(pid int, trampolineAddr uint64, origin uintptr, recode uintptr) error {
  935. var err error
  936. // Original 64-bit address
  937. //blrAddr := trampolineAddr
  938. // 拆分四段16位地址
  939. // Extract the 16-bit chunks
  940. //part1 := blrAddr & 0xFFFF // Lower 16 bits
  941. //part2 := (blrAddr >> 16) & 0xFFFF // Next 16 bits
  942. //part3 := (blrAddr >> 32) & 0xFFFF // Upper 16 bits
  943. //part4 := (blrAddr >> 48) & 0xFFFF // MAXUpper 16 bits
  944. //changeParts := []struct {
  945. // part uint64
  946. // offset uint64
  947. // enc uint64
  948. //}{
  949. // {blrAddr & 0xFFFF, OFFSET_0, 0}, // Lower 16 bits
  950. // {(blrAddr >> 16) & 0xFFFF, OFFSET_16_BIT, 0}, // Next 16 bits
  951. // {(blrAddr >> 32) & 0xFFFF, OFFSET_32_BIT, 0}, // Upper 16 bits
  952. // {(blrAddr >> 48) & 0xFFFF, OFFSET_48_BIT, 0}, // MAXUpper 16 bits
  953. // {0, 0, BLR_X18},
  954. //}
  955. StepCount := ChangeEncLen
  956. originAddr := make([]uintptr, StepCount)
  957. for i := 0; i < StepCount; i++ {
  958. originAddr[i] = origin + SrcAddrOffset + uintptr(i*4)
  959. }
  960. changeParts := []struct {
  961. enc uint32
  962. }{
  963. {encodeADRP(18, trampolineAddr, uint64(originAddr[0]))}, // adrp x18, trampolineAddr
  964. {encodeADDLO12(18, trampolineAddr)}, // add x18, x18, :lo12:trampolineAddr
  965. {BLR_X18}, // blr x18
  966. }
  967. //for i, p := range changeParts {
  968. // if err := setEnc(pid, originInst[i], uint64(p.enc)); err != nil {
  969. // return err
  970. // }
  971. //}
  972. //callAddrOffset = 44
  973. //var addrSteps = []uintptr{
  974. // origin + callAddrOffset,
  975. // origin + callAddrOffset + 4,
  976. // origin + callAddrOffset + 8,
  977. // origin + callAddrOffset + 12,
  978. // origin + callAddrOffset + 16,
  979. //}
  980. // Save Change
  981. for i := 0; i < StepCount; i++ {
  982. if err = setEncByAddr(pid, recode+uintptr(i*4), originAddr[i]); err != nil {
  983. return err
  984. }
  985. }
  986. // 修改原函数入口
  987. for i, p := range changeParts {
  988. if err = setEnc(pid, originAddr[i], uint64(p.enc)); err != nil {
  989. return err
  990. }
  991. }
  992. //for i, p := range changeParts {
  993. // if p.enc == 0 {
  994. // p.enc = buildArm64Enc(p.part, p.offset)
  995. // }
  996. // if err = setEnc(pid, originInst[i], p.enc); err != nil {
  997. // return err
  998. // }
  999. //}
  1000. // blr x18
  1001. //if err = setEnc(pid, addrSteps[stepCount-1], BLR_X18); err != nil {
  1002. // return err
  1003. //}
  1004. //err = setEnc(pid, addrSteps[0], buildArm64Enc(part1, OFFSET_0))
  1005. //if err != nil {
  1006. // return err
  1007. //}
  1008. //err = setEnc(pid, addrSteps[1], buildArm64Enc(part2, OFFSET_16_BIT))
  1009. //if err != nil {
  1010. // return err
  1011. //}
  1012. //err = setEnc(pid, addrSteps[2], buildArm64Enc(part3, OFFSET_32_BIT))
  1013. //if err != nil {
  1014. // return err
  1015. //}
  1016. //err = setEnc(pid, addrSteps[3], buildArm64Enc(part4, OFFSET_48_BIT))
  1017. //if err != nil {
  1018. // return err
  1019. //}
  1020. klog.Infof("# blr x18 \nset *(unsigned int*)($origin+%d) = 0x%08x\n", PC_START+4*4, 0xD63F0240)
  1021. return nil
  1022. }
  1023. func buildArm64Enc(imm16, hw uint64) uint64 {
  1024. rd := 0x12 // x18
  1025. fixed := 0x1e5
  1026. // Combine all parts into a single 32-bit value
  1027. result := uint64(rd<<0) | (imm16 << 5) | (hw << 21) | uint64(fixed<<23)
  1028. klog.Infof("set *(unsigned int*)($origin+%d) = 0x%08x\n", PC_START+hw*4, result)
  1029. return result
  1030. }
  1031. func modifyNetSetTargetAddr(pid int, sendDebugAddr, sendReleaseAddr uintptr) error {
  1032. sendOffset := sendReleaseAddr - sendDebugAddr - 5
  1033. // 读取原始数据
  1034. alignedAddr := sendDebugAddr & ^(uintptr(unsafe.Sizeof(uintptr(0))) - 1)
  1035. originalData, err := readData(pid, alignedAddr)
  1036. if err != nil {
  1037. return err
  1038. }
  1039. bytes := (*[8]byte)(unsafe.Pointer(&originalData))
  1040. offsetLocation := (sendDebugAddr % uintptr(unsafe.Sizeof(uintptr(0)))) + 1
  1041. *(*uint32)(unsafe.Pointer(&bytes[offsetLocation])) = uint32(sendOffset)
  1042. err = writeData(pid, alignedAddr, originalData)
  1043. if err != nil {
  1044. return err
  1045. }
  1046. return nil
  1047. }
  1048. func modifyReleaseFuncEnter(pid int, originEnterAddr, debugEnterAddr uintptr) error {
  1049. offset := debugEnterAddr - (originEnterAddr + 5)
  1050. // 读取原始数据
  1051. alignedAddr := originEnterAddr & ^(uintptr(unsafe.Sizeof(uintptr(0))) - 1)
  1052. originalData, err := readData(pid, alignedAddr)
  1053. if err != nil {
  1054. return err
  1055. }
  1056. bytes := (*[8]byte)(unsafe.Pointer(&originalData))
  1057. bytes[originEnterAddr%uintptr(unsafe.Sizeof(uintptr(0)))] = 0xe9
  1058. *(*uint32)(unsafe.Pointer(&bytes[(originEnterAddr%uintptr(unsafe.Sizeof(uintptr(0))))+1])) = uint32(offset)
  1059. err = writeData(pid, alignedAddr, originalData)
  1060. if err != nil {
  1061. return err
  1062. }
  1063. return nil
  1064. }
  1065. func restoreOriginalInstructions(pid int, addr uintptr, instructions []byte) error {
  1066. alignedAddr := addr & ^(uintptr(unsafe.Sizeof(uintptr(0))) - 1)
  1067. originalData, err := readData(pid, alignedAddr)
  1068. if err != nil {
  1069. return err
  1070. }
  1071. bytes := (*[8]byte)(unsafe.Pointer(&originalData))
  1072. for i := 0; i < len(instructions); i++ {
  1073. bytes[addr%uintptr(unsafe.Sizeof(uintptr(0)))+uintptr(i)] = instructions[i]
  1074. }
  1075. err = writeData(pid, alignedAddr, originalData)
  1076. if err != nil {
  1077. return err
  1078. }
  1079. return nil
  1080. }
  1081. //func main() {
  1082. // flag.StringVar(&PID, "p", "", "PID")
  1083. // flag.Parse()
  1084. // pidStr := PID // 替换为目标进程的 PID
  1085. // pid, err := strconv.Atoi(pidStr)
  1086. // if err != nil {
  1087. // log.Fatalf("Invalid PID: %v", err)
  1088. // }
  1089. // functionName := "Java_java_net_SocketOutputStream_socketWrite0"
  1090. // libraryName := "libnet.so"
  1091. //
  1092. // cwLibraryName := "cwlibnet.so"
  1093. // cwLibraryPath := "/root/cwlibnet.so"
  1094. //
  1095. // jvmInjector := &JvmInjector{
  1096. // pid: pid,
  1097. // ReleaseLibNetInfo: LibNetInfo{
  1098. // libName: libraryName,
  1099. // FuncSymbol: instInfo{
  1100. // SymName: functionName,
  1101. // },
  1102. // },
  1103. // DebugLibNetInfo: LibNetInfo{
  1104. // // TODO 根据版本设置
  1105. // libName: cwLibraryName,
  1106. // // TODO 根据版本设置
  1107. // libPath: cwLibraryPath,
  1108. // FuncSymbol: instInfo{
  1109. // SymName: functionName,
  1110. // },
  1111. // },
  1112. // }
  1113. //
  1114. // err = jvmInject(jvmInjector)
  1115. // klog.Infoln(err)
  1116. //}
  1117. func JvmInject(jvmInjector *JvmInjector) error {
  1118. jvmInjector.DebugLibNetInfo.FuncSymbol.SymName = "CW_Java_java_net_SocketOutputStream_socketWrite0"
  1119. pid := jvmInjector.Pid
  1120. var err error
  1121. err = jvmInjector.InitProg()
  1122. //err = jvmInjector.findReleaseFuncContextFromLibPath()
  1123. //klog.Infoln(err)
  1124. // Debug版本无需修改寄存器 TODO 直接使用原函数 需要在ebpf层适配
  1125. // 已经加载so并指令修改正确的
  1126. if jvmInjector.PreCheck.EbpfCanInjection {
  1127. klog.Infoln("[inject] eBPF can injection.")
  1128. return nil
  1129. }
  1130. if err != nil {
  1131. klog.WithError(err).Errorf("[inject] Error message during release phase.")
  1132. return err
  1133. }
  1134. // 原指令校验通过
  1135. if !jvmInjector.PreCheck.NeedInjectionCheck {
  1136. return err
  1137. }
  1138. printCodeData(jvmInjector.ReleaseLibNetInfo)
  1139. klog.Info("[inject] Pre check suc.")
  1140. _type, _, err := jvmInjector.findLibBaseFromProcMaps(jvmInjector.DebugLibNetInfo.LibName)
  1141. if err != nil {
  1142. // load so
  1143. if _type == 1 {
  1144. klog.Infoln("[inject] start load so.")
  1145. resCode := jvmInjector.jvmInjectLib()
  1146. if resCode == 0 {
  1147. klog.Infof("[inject] load so successful. proc load path is [%s], file path in node is [%s]", jvmInjector.DebugLibNetInfo.ProcLoadPath, jvmInjector.DebugLibNetInfo.LibPath)
  1148. jvmInjector.PreCheck.LoadingCheck = true
  1149. } else {
  1150. klog.Errorf("[inject] Failed load so. so path is [%s]", jvmInjector.DebugLibNetInfo.LibPath)
  1151. return fmt.Errorf("[inject] Failed load so. code is %d so path is [%s]", resCode, jvmInjector.DebugLibNetInfo.LibPath)
  1152. }
  1153. }
  1154. } else {
  1155. klog.Infoln("[inject] so already loaded.")
  1156. jvmInjector.PreCheck.LoadingCheck = true
  1157. }
  1158. if !jvmInjector.PreCheck.LoadingCheck {
  1159. klog.Infof("Failed load so")
  1160. return err
  1161. }
  1162. err = jvmInjector.findDebugFuncContextFromLibPath()
  1163. if err != nil {
  1164. klog.WithError(err).Errorf("[inject] Failed to find debug Func Context from libPath")
  1165. return err
  1166. }
  1167. if !jvmInjector.validateAllPreCheck() {
  1168. klog.Errorf("[inject] validateAllPreCheck failed : "+
  1169. "NeedInjectionCheck=%v, LoadingCheck=%v",
  1170. jvmInjector.PreCheck.NeedInjectionCheck,
  1171. jvmInjector.PreCheck.LoadingCheck,
  1172. )
  1173. return err
  1174. }
  1175. //printCodeData(jvmInjector.DebugLibNetInfo)
  1176. //// 修改
  1177. debugFuncEnterAddr := uintptr(jvmInjector.DebugLibNetInfo.FuncSymbol.SymAddr)
  1178. originFuncEnterAddr := uintptr(jvmInjector.ReleaseLibNetInfo.FuncSymbol.SymAddr)
  1179. recodeFuncEnterAddr := uintptr(jvmInjector.RecodeInfo.FuncSymbol.SymAddr)
  1180. //klog.Infof("<0x%x> -> <0x%x>\n", originFuncEnterAddr, debugFuncEnterAddr)
  1181. //klog.Infof("<0x%x> -> <0x%x>\n", debugIoFdAddr, ioFdReleaseTargetAddr)
  1182. //klog.Infof("<0x%x> -> <0x%x>\n", debugNetSendAddr, netSendReleaseTargetAddr)
  1183. //
  1184. // 附加到目标进程
  1185. klog.Infof("[inject] %d attach", pid)
  1186. err = syscall.PtraceAttach(pid)
  1187. if err != nil {
  1188. klog.Infof("ptrace ATTACH: %v", err)
  1189. }
  1190. //
  1191. // 等待目标进程停止
  1192. klog.Infof("[inject] %d attach wait.", pid)
  1193. if _, err := syscall.Wait4(pid, nil, 0, nil); err != nil {
  1194. klog.WithError(err).Errorf("[inject] Wait4 error")
  1195. return err
  1196. }
  1197. // 保存原始指令并扩充新指令
  1198. klog.Infof("[inject] %d build cw enc", pid)
  1199. err = buildCwNopEnc(pid, debugFuncEnterAddr, originFuncEnterAddr)
  1200. if err != nil {
  1201. klog.Errorln(err)
  1202. return err
  1203. }
  1204. //
  1205. //err = modifyNetSetTargetAddr(pid, debugNetSendAddr, netSendReleaseTargetAddr)
  1206. //klog.Infoln(err)
  1207. //if err != nil {
  1208. // klog.Infoln(err)
  1209. // return err
  1210. //}
  1211. // todo 二次效验 读取并验证地址
  1212. //_, err = jvmInjector.checkDebugFuncSymAfterChange()
  1213. //printCodeData(jvmInjector.ReleaseLibNetInfo)
  1214. //printCodeData(jvmInjector.DebugLibNetInfo)
  1215. //
  1216. //// todo 效验目标函数内地址是否与预期一致
  1217. //if !jvmInjector.validateAllModifyCheck() && err == nil {
  1218. // return err
  1219. //}
  1220. //变更原指令 长跳转到新地址 保存到recode
  1221. klog.Infof("[inject] %d modifyNetSetTargetAddr", pid)
  1222. err = modifyOriginEnc(pid, uint64(debugFuncEnterAddr), originFuncEnterAddr, recodeFuncEnterAddr)
  1223. //// 更新函数入口
  1224. //err = modifyReleaseFuncEnter(pid, originFuncEnterAddr, debugFuncEnterAddr)
  1225. //if err != nil {
  1226. // klog.Infoln(err)
  1227. // return err
  1228. //}
  1229. //// 校验jmp地址修改正确
  1230. //err = jvmInjector.checkReleaseFuncSymAfterChange()
  1231. //if err != nil {
  1232. // klog.Infoln(err)
  1233. // if len(jvmInjector.ReleaseLibNetInfo.FuncSymbol.OriginCode) == 5 {
  1234. // err = restoreOriginalInstructions(pid, originFuncEnterAddr, jvmInjector.ReleaseLibNetInfo.FuncSymbol.OriginCode)
  1235. // if err != nil {
  1236. // klog.Infoln(err)
  1237. // return err
  1238. // }
  1239. // }
  1240. //}
  1241. //
  1242. // 恢复执行
  1243. klog.Infof("[inject] %d Detach", pid)
  1244. if err = syscall.PtraceDetach(pid); err != nil {
  1245. klog.Errorf("ptrace DETACH: %v", err)
  1246. return err
  1247. }
  1248. return nil
  1249. }