inject_linux_arm64.go 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048
  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. "debug/elf"
  14. "fmt"
  15. "golang.org/x/arch/arm64/arm64asm"
  16. "golang.org/x/arch/x86/x86asm"
  17. "os"
  18. "strings"
  19. "syscall"
  20. //"time"
  21. "unsafe"
  22. )
  23. const (
  24. IO_FD_FDID_SYM_OFFSET = 192
  25. NET_SEND_SYM_OFFSET = 776
  26. )
  27. const (
  28. OFFSET_0 = 0
  29. OFFSET_16 = 1
  30. OFFSET_32 = 2
  31. OFFSET_48 = 3
  32. PC_START = 56
  33. BLR_X18 = 0xd63f0240
  34. )
  35. type InstInfo struct {
  36. SymName string
  37. SymSize uint64
  38. SymAddr uint64
  39. PC uint64
  40. Inst arm64asm.Inst
  41. OriginInst arm64asm.Inst
  42. OriginCode []byte
  43. TargetAddr uint64
  44. OriginTargetAddr uint64
  45. TargetEnc uint32
  46. OriginEnc uint32
  47. }
  48. type InnerSymbolInfo struct {
  49. IO_fd_fdID_ADRP InstInfo
  50. IO_fd_fdID_ADD InstInfo
  51. NET_Send InstInfo
  52. }
  53. type LibNetInfo struct {
  54. LibName string
  55. LibPath string
  56. FuncSymbol InstInfo
  57. InnerSymbol InnerSymbolInfo
  58. }
  59. type UprobeData struct {
  60. Offset int
  61. Func string
  62. ELFPath string
  63. }
  64. type JvmInjector struct {
  65. Pid int
  66. ReleaseLibNetInfo LibNetInfo
  67. DebugLibNetInfo LibNetInfo
  68. RecodeInfo LibNetInfo
  69. // 原方法首个指令不为jmp | ReleaseLibNetInfo 读取无异常
  70. PreCheck struct {
  71. NeedInjectionCheck bool // 原指令校验 true表示可以继续执行注入
  72. LoadingCheck bool // true 表示加载成功
  73. IoFdCheck bool // fd地址校验
  74. NetSendFuncCheck bool // netsend校验
  75. EbpfCanInjection bool
  76. }
  77. AfterCheck struct {
  78. IoFdCheck bool
  79. NetSendFuncCheck bool
  80. }
  81. Uprobe UprobeData
  82. }
  83. func (j *JvmInjector) checkEnc(code []byte, start, len uint64, enc uint32) error {
  84. end := start + len
  85. inst, err := arm64asm.Decode(code[start:end])
  86. if err != nil {
  87. return fmt.Errorf("Decode code[%d:%d] %s: err is <%v>", start, end, arm64asm.GNUSyntax(inst), err)
  88. } else {
  89. if inst.Enc != enc {
  90. return fmt.Errorf("Validation inst failed:'%s <+%d>: %s'", fmt.Sprintf("0x%016x", j.ReleaseLibNetInfo.FuncSymbol.SymAddr+start), start, arm64asm.GNUSyntax(inst))
  91. }
  92. }
  93. return nil
  94. }
  95. func (j *JvmInjector) findReleaseAddressInfoFromMem() error {
  96. funcAbsAddress := j.ReleaseLibNetInfo.FuncSymbol.SymAddr
  97. releaseFuncSym := InnerSymbolInfo{}
  98. code, err := j.readMemory(funcAbsAddress, j.ReleaseLibNetInfo.FuncSymbol.SymSize)
  99. if err != nil {
  100. return err
  101. }
  102. fmt.Println(j.ReleaseLibNetInfo.FuncSymbol.SymSize)
  103. // cwso是否载入,载入则从recode判断指令
  104. baseAddress, libPath, err := j.findLibBaseFromProcMaps(j.DebugLibNetInfo.LibName)
  105. if err == nil {
  106. j.PreCheck.LoadingCheck = true
  107. fmt.Println("so already loaded check enc...")
  108. // 获取recode地址
  109. fmt.Println(baseAddress)
  110. recodeFunctionSym, err := j.getFunctionOffset(libPath, j.RecodeInfo.FuncSymbol.SymName)
  111. if err != nil {
  112. return err
  113. }
  114. j.RecodeInfo.FuncSymbol.SymAddr = baseAddress + recodeFunctionSym.Value
  115. recode, err := j.readMemory(j.RecodeInfo.FuncSymbol.SymAddr, 20)
  116. if err != nil {
  117. return err
  118. }
  119. if bytes.Equal(recode, code[56:56+20]) {
  120. j.PreCheck.EbpfCanInjection = true
  121. fmt.Println("successful...")
  122. return nil
  123. }
  124. fmt.Println("so already loaded. check failed.")
  125. }
  126. /*
  127. 0x0000fffbdc0ef24c <+56>: str x2, [x6,#120]
  128. 0x0000fffbdc0ef250 <+60>: str x3, [x29,#96]
  129. 0x0000fffbdc0ef254 <+64>: mov x21, x0
  130. 0x0000fffbdc0ef258 <+68>: mov w28, w4
  131. 0x0000fffbdc0ef25c <+72>: mov w23, w5
  132. */
  133. err = j.checkEnc(code, 56, 4, 0xf9003cc2)
  134. if err != nil {
  135. return err
  136. }
  137. err = j.checkEnc(code, 60, 4, 0xf90033a3)
  138. if err != nil {
  139. return err
  140. }
  141. err = j.checkEnc(code, 64, 4, 0xaa0003f5)
  142. if err != nil {
  143. return err
  144. }
  145. err = j.checkEnc(code, 68, 4, 0x2a0403fc)
  146. if err != nil {
  147. return err
  148. }
  149. err = j.checkEnc(code, 72, 4, 0x2a0503f7)
  150. if err != nil {
  151. return err
  152. }
  153. j.ReleaseLibNetInfo.InnerSymbol = releaseFuncSym
  154. j.ReleaseLibNetInfo.FuncSymbol.OriginCode = code[0:4]
  155. return nil
  156. }
  157. func (j *JvmInjector) findDebugAddressInfoFromMem() (uint64, error) {
  158. funcAbsAddress := j.DebugLibNetInfo.FuncSymbol.SymAddr
  159. debugFuncSym := InnerSymbolInfo{}
  160. //debugFuncSym.FuncSymbol.SymAddr = funcAbsAddress
  161. //offset := sym.Value
  162. size := j.DebugLibNetInfo.FuncSymbol.SymSize
  163. code, err := j.readMemory(funcAbsAddress, size)
  164. //fmt.Println(code, err)
  165. if err != nil {
  166. return 0, err
  167. }
  168. pc := uint64(0)
  169. preContext := InstInfo{}
  170. for pc < uint64(len(code)) {
  171. inst, err := arm64asm.Decode(code[pc:])
  172. if err != nil {
  173. fmt.Printf("Decode error at offset 0x%x: %v\n", pc, err)
  174. pc++ // Skip this byte and try to decode again
  175. continue
  176. }
  177. //fmt.Printf("Decoded instuction at 0x%x: %v\n", funcAbsAddress+pc, Inst)
  178. //fmt.Printf("Decoded x86 instuction at 0x%x: %v\n", funcAbsAddress+pc, x86asm.IntelSyntax(inst, 0, nil))
  179. //fmt.Printf("Decoded GNU instuction at 0x%x: %v\n", funcAbsAddress+pc, x86asm.GNUSyntax(Inst, 0, nil))
  180. currentData := InstInfo{
  181. PC: pc,
  182. SymAddr: funcAbsAddress + pc,
  183. Inst: inst,
  184. }
  185. if pc == 0 {
  186. j.DebugLibNetInfo.FuncSymbol.PC = currentData.PC
  187. j.DebugLibNetInfo.FuncSymbol.Inst = currentData.Inst
  188. j.DebugLibNetInfo.FuncSymbol.OriginInst = currentData.Inst
  189. }
  190. // IO_fd_fdID
  191. if pc == IO_FD_FDID_SYM_OFFSET {
  192. if inst.Op == arm64asm.ADD {
  193. if preContext.Inst.Op == arm64asm.ADRP && inst.Args[0].String() == arm64asm.X0.String() {
  194. debugFuncSym.IO_fd_fdID_ADD = currentData
  195. debugFuncSym.IO_fd_fdID_ADD.SymName = "<IO_fd_fdID ADD>(Debug)"
  196. debugFuncSym.IO_fd_fdID_ADD.OriginEnc = currentData.Inst.Enc
  197. debugFuncSym.IO_fd_fdID_ADD.TargetEnc = j.ReleaseLibNetInfo.InnerSymbol.IO_fd_fdID_ADD.Inst.Enc & uint32(0xFFFFF000)
  198. /*
  199. |31 immlo | 27-24 |23 immhi 5|4 Rd 0|
  200. 1 00 1 0000 0001 1000 0000 1110 011 0 0000
  201. 9 0 1 8 0 e 6 0
  202. ( target- pc >> zero(12) )/4k
  203. */
  204. debugFuncSym.IO_fd_fdID_ADRP = preContext
  205. debugFuncSym.IO_fd_fdID_ADRP.SymName = "<IO_fd_fdID ADRP>(Debug)"
  206. debugFuncSym.IO_fd_fdID_ADRP.OriginEnc = preContext.Inst.Enc
  207. releaseTarget := j.ReleaseLibNetInfo.InnerSymbol.IO_fd_fdID_ADRP.TargetAddr
  208. offset := (releaseTarget - preContext.SymAddr&0xFFFFFFFFFFFFF000) / (1 << 12)
  209. immhi := offset >> 2
  210. immlo := offset & 0x03
  211. decimal31_24 := (1 << 7) + (immlo << 5) + (1 << 4)
  212. targetEnc := (decimal31_24 << 24) | (immhi << 5)
  213. debugFuncSym.IO_fd_fdID_ADRP.TargetEnc = uint32(targetEnc)
  214. j.PreCheck.IoFdCheck = true
  215. } else {
  216. return 0, fmt.Errorf("The decoded instruction is not a ADRP or X0. inst:<%s>, arg:<%s>", inst.String(), inst.Args)
  217. }
  218. } else {
  219. return 0, fmt.Errorf("The decoded instruction is not a ADD. inst:<%s>, arg:<%s>", inst.String(), inst.Args)
  220. }
  221. }
  222. if pc == NET_SEND_SYM_OFFSET {
  223. debugFuncSym.NET_Send = currentData
  224. //fmt.Printf("4 call Decoded instuction at 0x%x: %v\n", funcAbsAddress+pc, inst)
  225. //relOffset, ok := (inst.Args[0].(x86asm.Rel))
  226. fmt.Println(inst)
  227. fmt.Println(inst.Args)
  228. //if !ok {
  229. // return 0, fmt.Errorf("The decoded instruction is not a Rel.")
  230. //}
  231. //targetAddress := currentData.SymAddr + uint64(inst.Len) + uint64(relOffset)
  232. //debugFuncSym.NET_Send.TargetAddr = targetAddress
  233. debugFuncSym.NET_Send.SymName = "<NET_Send>(Debug)"
  234. //fmt.Printf("Find %s Target address: 0x%x\n", debugFuncSym.NET_Send.SymName, targetAddress)
  235. //
  236. //// 保存原始数据
  237. //debugFuncSym.NET_Send.OriginTargetAddr = targetAddress
  238. //debugFuncSym.NET_Send.OriginInst = currentData.Inst
  239. j.PreCheck.NetSendFuncCheck = true
  240. }
  241. preContext = InstInfo{
  242. PC: pc,
  243. SymAddr: funcAbsAddress + pc,
  244. Inst: inst,
  245. }
  246. pc += 4
  247. }
  248. j.DebugLibNetInfo.InnerSymbol = debugFuncSym
  249. return 0, nil
  250. }
  251. //func (j *JvmInjector) checkDebugFuncSymAfterChange() (uint64, error) {
  252. // funcAbsAddress := j.DebugLibNetInfo.FuncSymbol.SymAddr
  253. // debugFuncSym := InnerSymbolInfo{}
  254. // code, err := j.readMemory(funcAbsAddress, j.DebugLibNetInfo.FuncSymbol.SymSize)
  255. // if err != nil {
  256. // return 0, err
  257. // }
  258. //
  259. // pc := uint64(0)
  260. // preContext := InstInfo{}
  261. //
  262. // for pc < uint64(len(code)) {
  263. // inst, err := x86asm.Decode(code[pc:], 64)
  264. // if err != nil {
  265. // fmt.Printf("Decode error at offset 0x%x: %v\n", pc, err)
  266. // pc++ // Skip this byte and try to decode again
  267. // continue
  268. // }
  269. // //fmt.Printf("Decoded instuction at 0x%x: %v\n", funcAbsAddress+pc, Inst)
  270. // //fmt.Printf("Decoded x86 instuction at 0x%x: %v\n", funcAbsAddress+pc, x86asm.IntelSyntax(inst, 0, nil))
  271. // //fmt.Printf("Decoded GNU instuction at 0x%x: %v\n", funcAbsAddress+pc, x86asm.GNUSyntax(Inst, 0, nil))
  272. // currentData := InstInfo{
  273. // PC: pc,
  274. // SymAddr: funcAbsAddress + pc,
  275. // Inst: inst,
  276. // }
  277. // if pc == NET_SEND_SYM_OFFSET {
  278. // fmt.Printf("Instuction at 0x%x: %v\n", preContext.PC, preContext.Inst)
  279. // debugFuncSym.IO_fd_fdID = currentData
  280. // debugFuncSym.IO_fd_fdID.SymName = "<IO_fd_fdID>(Debug)"
  281. // // 计算目标地址
  282. // if currentData.Inst.Op == x86asm.MOV &&
  283. // len(currentData.Inst.Args) == 4 &&
  284. // currentData.Inst.Args[0] != nil &&
  285. // currentData.Inst.Args[0] == x86asm.RDX &&
  286. // currentData.Inst.Args[1] != nil {
  287. // if mem, ok := currentData.Inst.Args[1].(x86asm.Mem); ok && mem.Base == x86asm.RIP {
  288. // // 直接从Mem结构体中读取偏移
  289. // relOffset := mem.Disp
  290. // targetAddress := currentData.SymAddr + uint64(currentData.Inst.Len) + uint64(relOffset)
  291. // fmt.Printf("Find %s Target address: 0x%x\n", debugFuncSym.IO_fd_fdID.SymName, targetAddress)
  292. // debugFuncSym.IO_fd_fdID.TargetAddr = targetAddress
  293. // //j.PreCheck.IoFdCheck = true
  294. //
  295. // if targetAddress == j.ReleaseLibNetInfo.InnerSymbol.IO_fd_fdID.TargetAddr {
  296. // j.DebugLibNetInfo.InnerSymbol.IO_fd_fdID.TargetAddr = targetAddress
  297. // j.DebugLibNetInfo.InnerSymbol.IO_fd_fdID.Inst = currentData.Inst
  298. // j.AfterCheck.IoFdCheck = true
  299. // fmt.Println("ok")
  300. // }
  301. // } else {
  302. // return 0, fmt.Errorf("The instruction does not use RIP-relative addressing.")
  303. // }
  304. // } else {
  305. // return 0, fmt.Errorf("The decoded instruction is not a MOV to RDX.")
  306. // }
  307. // }
  308. // if pc == NET_SEND_SYM_OFFSET {
  309. // debugFuncSym.NET_Send = currentData
  310. // //fmt.Println(currentData.IntelInst)
  311. // //fmt.Printf("4 call Decoded instuction at 0x%x: %v\n", funcAbsAddress+pc, inst)
  312. // relOffset, ok := (inst.Args[0].(x86asm.Rel))
  313. // if !ok {
  314. // return 0, fmt.Errorf("The decoded instruction is not a Rel.")
  315. // }
  316. // targetAddress := currentData.SymAddr + uint64(inst.Len) + uint64(relOffset)
  317. // debugFuncSym.NET_Send.TargetAddr = targetAddress
  318. // debugFuncSym.NET_Send.SymName = "<NET_Send>(Debug)"
  319. // fmt.Printf("Find %s Target address: 0x%x\n", debugFuncSym.NET_Send.SymName, targetAddress)
  320. //
  321. // if targetAddress == j.ReleaseLibNetInfo.InnerSymbol.NET_Send.TargetAddr {
  322. // j.DebugLibNetInfo.InnerSymbol.NET_Send.TargetAddr = targetAddress
  323. // j.DebugLibNetInfo.InnerSymbol.NET_Send.Inst = currentData.Inst
  324. // j.AfterCheck.NetSendFuncCheck = true
  325. // }
  326. // }
  327. //
  328. // preContext = InstInfo{
  329. // PC: pc,
  330. // SymAddr: funcAbsAddress + pc,
  331. // Inst: inst,
  332. // }
  333. // pc += uint64(inst.Len)
  334. // }
  335. // return 0, nil
  336. //}
  337. func (j *JvmInjector) checkReleaseFuncSymAfterChange() error {
  338. funcAbsAddress := j.ReleaseLibNetInfo.FuncSymbol.SymAddr
  339. code, err := j.readMemory(funcAbsAddress, j.ReleaseLibNetInfo.FuncSymbol.SymSize)
  340. if err != nil {
  341. return fmt.Errorf("readMemory error in checkReleaseFuncSymAfterChange <%v>", err)
  342. }
  343. inst, err := x86asm.Decode(code[0:], 64)
  344. if err != nil {
  345. return fmt.Errorf("Decode error in checkReleaseFuncSymAfterChange <%v>", err)
  346. }
  347. if inst.Op != x86asm.JMP {
  348. return fmt.Errorf("The instruction does not JMP.")
  349. }
  350. relOffset, ok := inst.Args[0].(x86asm.Rel)
  351. if !ok {
  352. return fmt.Errorf("The instruction does not use RIP-relative addressing.")
  353. }
  354. // 验证target与Debug入口是否一致
  355. targetAddress := funcAbsAddress + uint64(inst.Len) + uint64(relOffset)
  356. if targetAddress != j.DebugLibNetInfo.FuncSymbol.SymAddr {
  357. return fmt.Errorf("Function entry jmp address does not match expectations.")
  358. }
  359. return nil
  360. }
  361. // readMemory 用于读取指定地址的内存数据
  362. func (j *JvmInjector) readMemory(address uint64, size uint64) ([]byte, error) {
  363. memFile := fmt.Sprintf("/proc/%d/mem", j.Pid)
  364. file, err := os.Open(memFile)
  365. if err != nil {
  366. return nil, err
  367. }
  368. defer file.Close()
  369. data := make([]byte, size)
  370. _, err = file.ReadAt(data, int64(address))
  371. if err != nil {
  372. return nil, err
  373. }
  374. return data, nil
  375. }
  376. // findLibraryBases 用于在 /proc/[pid]/maps 文件中查找库的所有基地址
  377. func findLibraryBasesList(pid int, libraryName string, libPath string) ([]uint64, error) {
  378. mapsFile := fmt.Sprintf("/proc/%d/maps", pid)
  379. file, err := os.Open(mapsFile)
  380. if err != nil {
  381. return nil, err
  382. }
  383. defer file.Close()
  384. var bases []uint64
  385. scanner := bufio.NewScanner(file)
  386. for scanner.Scan() {
  387. line := scanner.Text()
  388. if strings.Contains(line, libraryName) && strings.Contains(line, libPath) {
  389. var start, end uint64
  390. fmt.Sscanf(line, "%x-%x", &start, &end)
  391. bases = append(bases, start)
  392. }
  393. }
  394. if len(bases) == 0 {
  395. return nil, fmt.Errorf("library %s not found", libraryName)
  396. }
  397. return bases, nil
  398. }
  399. func (j *JvmInjector) findLibBaseFromProcMaps(libName string) (uint64, string, error) {
  400. mapsFile := fmt.Sprintf("/proc/%d/maps", j.Pid)
  401. file, err := os.Open(mapsFile)
  402. if err != nil {
  403. return 0, "", err
  404. }
  405. defer file.Close()
  406. var start, end uint64
  407. scanner := bufio.NewScanner(file)
  408. for scanner.Scan() {
  409. line := scanner.Text()
  410. if strings.Contains(line, "/"+libName) {
  411. fmt.Sscanf(line, "%x-%x", &start, &end)
  412. fields := strings.Fields(line)
  413. if len(fields) > 5 {
  414. path := fields[5]
  415. if strings.HasSuffix(path, ".so") {
  416. fmt.Printf("Found library %s\n", path)
  417. return start, path, nil
  418. }
  419. }
  420. }
  421. }
  422. return 1, "", fmt.Errorf("library %s not found", libName)
  423. }
  424. func (j *JvmInjector) getFunctionOffset(libPath, functionName string) (elf.Symbol, error) {
  425. elfFile, err := elf.Open(libPath)
  426. if err != nil {
  427. return elf.Symbol{}, fmt.Errorf("failed to open ELF file: %v", err)
  428. }
  429. defer elfFile.Close()
  430. symbols, err := elfFile.DynamicSymbols()
  431. if err != nil {
  432. return elf.Symbol{}, fmt.Errorf("failed to read dynamic symbols: %v", err)
  433. }
  434. for _, sym := range symbols {
  435. if sym.Name == functionName {
  436. return sym, nil
  437. }
  438. }
  439. //textSection := elfFile.Section(".text")
  440. //if textSection == nil {
  441. // fmt.Println("textSection is null")
  442. // //return nil
  443. //}
  444. //textSectionData, err := textSection.Data()
  445. //if err != nil {
  446. // fmt.Println("textSectionData error is", err)
  447. // //return nil
  448. //}
  449. //textSectionLen := uint64(len(textSectionData) - 1)
  450. return elf.Symbol{}, fmt.Errorf("function %s not found", functionName)
  451. }
  452. //var PID string
  453. func (j *JvmInjector) findReleaseFuncContextFromLibPath() error {
  454. // 获取release库的基地址
  455. baseAddress, libPath, err := j.findLibBaseFromProcMaps(j.ReleaseLibNetInfo.LibName)
  456. functionName := j.ReleaseLibNetInfo.FuncSymbol.SymName
  457. j.ReleaseLibNetInfo.LibPath = libPath
  458. libName := j.ReleaseLibNetInfo.LibName
  459. if err != nil {
  460. return fmt.Errorf("Error finding base addresses: %v", err)
  461. }
  462. fmt.Printf("Base address of (%s)%s: %x\n", "", libName, baseAddress)
  463. // 获取函数的偏移量
  464. functionSym, err := j.getFunctionOffset(libPath, functionName)
  465. // 计算函数的实际内存地址
  466. j.ReleaseLibNetInfo.FuncSymbol.SymAddr = baseAddress + functionSym.Value
  467. j.ReleaseLibNetInfo.FuncSymbol.SymSize = functionSym.Size
  468. if err != nil {
  469. return fmt.Errorf("Error getting function offset: %v", err)
  470. }
  471. fmt.Printf("Actual memory address of %s at base 0x%x: 0x%x\n", functionName, baseAddress, j.ReleaseLibNetInfo.FuncSymbol.SymAddr)
  472. err = j.findReleaseAddressInfoFromMem()
  473. if err != nil {
  474. return err
  475. } else {
  476. j.PreCheck.NeedInjectionCheck = true
  477. }
  478. return nil
  479. }
  480. func (j *JvmInjector) findDebugFuncContextFromLibPath() error {
  481. libName := j.DebugLibNetInfo.LibName
  482. // 获取release库的基地址
  483. baseAddress, libPath, err := j.findLibBaseFromProcMaps(libName)
  484. fmt.Println(libPath)
  485. functionName := j.DebugLibNetInfo.FuncSymbol.SymName
  486. j.DebugLibNetInfo.LibPath = libPath
  487. if err != nil {
  488. return fmt.Errorf("Error finding base addresses: %v", err)
  489. }
  490. // 获取函数的偏移量
  491. functionSym, err := j.getFunctionOffset(libPath, functionName)
  492. // 计算函数的实际内存地址
  493. j.DebugLibNetInfo.FuncSymbol.SymAddr = baseAddress + functionSym.Value
  494. j.DebugLibNetInfo.FuncSymbol.SymSize = functionSym.Size
  495. if err != nil {
  496. return fmt.Errorf("Error getting function offset: %v", err)
  497. }
  498. // 计算recode内存地址
  499. recodeFunctionSym, err := j.getFunctionOffset(libPath, j.RecodeInfo.FuncSymbol.SymName)
  500. j.RecodeInfo.FuncSymbol.SymAddr = baseAddress + recodeFunctionSym.Value
  501. if err != nil {
  502. return fmt.Errorf("Error getting function offset: %v", err)
  503. }
  504. fmt.Printf("DEBUG Actual memory address of %s at base 0x%x: 0x%x\n", functionName, baseAddress, j.DebugLibNetInfo.FuncSymbol.SymAddr)
  505. fmt.Printf("DEBUG Actual memory address of %s at base 0x%x: 0x%x\n", j.RecodeInfo.FuncSymbol.SymName, baseAddress, j.RecodeInfo.FuncSymbol.SymAddr)
  506. _, err = j.findDebugAddressInfoFromMem()
  507. if err != nil {
  508. return err
  509. }
  510. return nil
  511. }
  512. func printCodeData(data LibNetInfo) {
  513. fmt.Printf("========FuncEnter <0x%x> \n", data.FuncSymbol.SymAddr)
  514. //fmt.Printf("%s | CurrentAddr:<0x%x>\nOrigin-TargetAddr:<0x%x> | TargetAddr:<0x%x> \nOrigin-Enc:<0x%x> | TargetEnc:<0x%x> \n",
  515. // data.InnerSymbol.IO_fd_fdID_ADRP.SymName,
  516. // data.InnerSymbol.IO_fd_fdID_ADRP.SymAddr,
  517. // data.InnerSymbol.IO_fd_fdID_ADRP.OriginTargetAddr,
  518. // data.InnerSymbol.IO_fd_fdID_ADRP.TargetAddr,
  519. // data.InnerSymbol.IO_fd_fdID_ADRP.OriginEnc,
  520. // data.InnerSymbol.IO_fd_fdID_ADRP.TargetEnc)
  521. //fmt.Printf("\n%s | CurrentAddr:<0x%x>\nOrigin-TargetAddr:<0x%x> | TargetAddr:<0x%x> \nOrigin-Enc:<0x%x> | TargetEnc:<0x%x> \n",
  522. // data.InnerSymbol.IO_fd_fdID_ADD.SymName,
  523. // data.InnerSymbol.IO_fd_fdID_ADD.SymAddr,
  524. // data.InnerSymbol.IO_fd_fdID_ADD.OriginTargetAddr,
  525. // data.InnerSymbol.IO_fd_fdID_ADD.TargetAddr,
  526. // data.InnerSymbol.IO_fd_fdID_ADD.OriginEnc,
  527. // data.InnerSymbol.IO_fd_fdID_ADD.TargetEnc)
  528. //fmt.Printf("\n%s | CurrentAddr:<0x%x>\nOrigin-TargetAddr:<0x%x> | TargetAddr:<0x%x>\nOrigin-Inst:<%s> | Inst:<%s> \n",
  529. // data.InnerSymbol.NET_Send.SymName,
  530. // data.InnerSymbol.NET_Send.SymAddr,
  531. // data.InnerSymbol.NET_Send.OriginTargetAddr,
  532. // data.InnerSymbol.NET_Send.TargetAddr,
  533. // arm64asm.GNUSyntax(data.InnerSymbol.NET_Send.OriginInst),
  534. // arm64asm.GNUSyntax(data.InnerSymbol.NET_Send.Inst))
  535. fmt.Println("========")
  536. }
  537. func (j *JvmInjector) jvmInjectLib() int {
  538. dll := C.CString(j.DebugLibNetInfo.LibPath) // 替换为实际的DLL路径
  539. defer C.free(unsafe.Pointer(dll)) // 确保在使用完字符串后释放内存
  540. result := C.cw_inject_library(C.int(j.Pid), C.int(1), dll)
  541. fmt.Printf("Result: %d\n", result)
  542. return int(result)
  543. }
  544. func (j *JvmInjector) validateAllPreCheck() bool {
  545. return j.PreCheck.NeedInjectionCheck && j.PreCheck.LoadingCheck && j.PreCheck.IoFdCheck && j.PreCheck.NetSendFuncCheck
  546. }
  547. func (j *JvmInjector) validateAllModifyCheck() bool {
  548. return j.AfterCheck.IoFdCheck && j.AfterCheck.NetSendFuncCheck
  549. }
  550. /*修改部分*/
  551. func readData(pid int, addr uintptr) (uint64, error) {
  552. var data uint64
  553. if _, err := syscall.PtracePeekData(pid, addr, (*[4]byte)(unsafe.Pointer(&data))[:]); err != nil {
  554. return 0, fmt.Errorf("ptrace PEEKDATA: %v", err)
  555. }
  556. return data, nil
  557. }
  558. func writeData(pid int, addr uintptr, data uint64) error {
  559. if _, err := syscall.PtracePokeData(pid, addr, (*[4]byte)(unsafe.Pointer(&data))[:]); err != nil {
  560. return fmt.Errorf("ptrace POKEDATA: %v", err)
  561. }
  562. return nil
  563. }
  564. func modifyIoFdTargetAddr(pid int, insertAddr, distAddr uintptr) error {
  565. newOffset := distAddr - (insertAddr + 7)
  566. targetAddr := insertAddr + 3
  567. // 获取目标地址处的数据
  568. originalData, err := readData(pid, targetAddr)
  569. if err != nil {
  570. return err
  571. }
  572. // 更新数据中的目标偏移
  573. updatedData := (originalData & 0xFFFFFFFF00000000) | uint64(newOffset&0xFFFFFFFF)
  574. err = writeData(pid, targetAddr, updatedData)
  575. if err != nil {
  576. return err
  577. }
  578. return nil
  579. }
  580. /*
  581. set *(unsigned int*)($debug) = *(unsigned int*)($origin+56)
  582. set *(unsigned int*)($debug+4) = *(unsigned int*)($origin+60)
  583. set *(unsigned int*)($debug+8) = *(unsigned int*)($origin+64)
  584. set *(unsigned int*)($debug+12) = *(unsigned int*)($origin+68)
  585. # SUB SP, SP, #0x080 // 将栈指针下移 8 字节,创建栈帧空间
  586. set *(unsigned int*)($debug+16) = 0xd10203ff
  587. # STR W5, [SP] // 将 W5 的值存储到栈顶
  588. set *(unsigned int*)($debug+20) = 0xb90003e5
  589. # LDR W5, [SP] // 从栈顶加载数据回 W5
  590. set *(unsigned int*)($debug+24) = 0xb94003e5
  591. # ADD SP, SP, #0x080 // 恢复栈指针
  592. set *(unsigned int*)($debug+28) = 0x910203ff
  593. #mov w23, w5
  594. set *(unsigned int*)($debug+32) = *(unsigned int*)($origin+72)
  595. # ret
  596. set *(unsigned int*)($debug+36) = 0xd65f03c0
  597. */
  598. func buildNopEnc(pid int, nopAddr, originAddr uintptr) error {
  599. // 指令不为空则返回
  600. originalData, err := readData(pid, nopAddr)
  601. if err != nil {
  602. return err
  603. }
  604. fmt.Printf("0x%016x\n", originalData) // 16个字符宽度,左边补0
  605. if originalData != 0xd503201f {
  606. return fmt.Errorf("The cw enc not nop <0x%016x>\n", originAddr)
  607. }
  608. err = setEnc(pid, nopAddr+0, 0xd10203ff)
  609. if err != nil {
  610. return err
  611. }
  612. err = setEnc(pid, nopAddr+4, 0xb90003e5)
  613. if err != nil {
  614. return err
  615. }
  616. // nop
  617. //err = setEnc(pid, nopAddr+4+4, 0xd503201f)
  618. //if err != nil {
  619. // return err
  620. //}
  621. err = setEnc(pid, nopAddr+4+8, 0xb94003e5)
  622. if err != nil {
  623. return err
  624. }
  625. err = setEnc(pid, nopAddr+4+12, 0x910203ff)
  626. if err != nil {
  627. return err
  628. }
  629. err = setEncByAddr(pid, nopAddr+4+16, originAddr+56)
  630. if err != nil {
  631. return err
  632. }
  633. err = setEncByAddr(pid, nopAddr+4+20, originAddr+60)
  634. if err != nil {
  635. return err
  636. }
  637. err = setEncByAddr(pid, nopAddr+4+24, originAddr+64)
  638. if err != nil {
  639. return err
  640. }
  641. err = setEncByAddr(pid, nopAddr+4+28, originAddr+68)
  642. if err != nil {
  643. return err
  644. }
  645. err = setEncByAddr(pid, nopAddr+4+32, originAddr+72)
  646. if err != nil {
  647. return err
  648. }
  649. err = setEnc(pid, nopAddr+4+36, 0xd65f03c0)
  650. if err != nil {
  651. return err
  652. }
  653. return nil
  654. }
  655. func setEncByAddr(pid int, currentAddr, targetAddr uintptr) error {
  656. // 获取目标地址处的数据
  657. originalData, err := readData(pid, targetAddr)
  658. if err != nil {
  659. return err
  660. }
  661. // 更新数据中的目标偏移
  662. err = writeData(pid, currentAddr, originalData)
  663. if err != nil {
  664. return err
  665. }
  666. return nil
  667. }
  668. func setEnc(pid int, soAddr uintptr, enc uint64) error {
  669. // 更新数据中的目标偏移
  670. err := writeData(pid, soAddr, enc)
  671. if err != nil {
  672. return err
  673. }
  674. return nil
  675. }
  676. /*
  677. set *(unsigned int*)($origin+56) = 0xf2889692
  678. set *(unsigned int*)($origin+60) = 0xf2a363b2
  679. set *(unsigned int*)($origin+64) = 0xf2dfff92
  680. set *(unsigned int*)($origin+68) = 0xf2e00012
  681. # blr x18
  682. set *(unsigned int*)($origin+72) = 0xd63f0240
  683. */
  684. func modifyOriginEnc(pid int, nopAddr uint64, origin uintptr, recode uintptr) error {
  685. var err error
  686. // Original 64-bit address
  687. blrAddr := nopAddr
  688. // 拆分四段16位地址
  689. // Extract the 16-bit chunks
  690. part1 := blrAddr & 0xFFFF // Lower 16 bits
  691. part2 := (blrAddr >> 16) & 0xFFFF // Next 16 bits
  692. part3 := (blrAddr >> 32) & 0xFFFF // Upper 16 bits
  693. part4 := (blrAddr >> 48) & 0xFFFF // MAXUpper 16 bits
  694. err = setEnc(pid, origin+56, buildArm64Enc(part1, OFFSET_0))
  695. if err != nil {
  696. return err
  697. }
  698. err = setEnc(pid, origin+60, buildArm64Enc(part2, OFFSET_16))
  699. if err != nil {
  700. return err
  701. }
  702. err = setEnc(pid, origin+64, buildArm64Enc(part3, OFFSET_32))
  703. if err != nil {
  704. return err
  705. }
  706. err = setEnc(pid, origin+68, buildArm64Enc(part4, OFFSET_48))
  707. if err != nil {
  708. return err
  709. }
  710. err = setEnc(pid, origin+72, BLR_X18)
  711. if err != nil {
  712. return err
  713. }
  714. // save change
  715. err = setEncByAddr(pid, recode, origin+56)
  716. if err != nil {
  717. return err
  718. }
  719. err = setEncByAddr(pid, recode+4, origin+60)
  720. if err != nil {
  721. return err
  722. }
  723. err = setEncByAddr(pid, recode+8, origin+64)
  724. if err != nil {
  725. return err
  726. }
  727. err = setEncByAddr(pid, recode+12, origin+68)
  728. if err != nil {
  729. return err
  730. }
  731. err = setEncByAddr(pid, recode+16, origin+72)
  732. if err != nil {
  733. return err
  734. }
  735. fmt.Printf("# blr x18 \nset *(unsigned int*)($origin+%d) = 0x%08x\n", PC_START+4*4, 0xD63F0240)
  736. return nil
  737. }
  738. func buildArm64Enc(imm16, hw uint64) uint64 {
  739. rd := 0x12 // x18
  740. fixed := 0x1e5
  741. // Combine all parts into a single 32-bit value
  742. result := uint64(rd<<0) | (imm16 << 5) | (hw << 21) | uint64(fixed<<23)
  743. fmt.Printf("set *(unsigned int*)($origin+%d) = 0x%08x\n", PC_START+hw*4, result)
  744. return result
  745. }
  746. func modifyNetSetTargetAddr(pid int, sendDebugAddr, sendReleaseAddr uintptr) error {
  747. sendOffset := sendReleaseAddr - sendDebugAddr - 5
  748. // 读取原始数据
  749. alignedAddr := sendDebugAddr & ^(uintptr(unsafe.Sizeof(uintptr(0))) - 1)
  750. originalData, err := readData(pid, alignedAddr)
  751. if err != nil {
  752. return err
  753. }
  754. bytes := (*[8]byte)(unsafe.Pointer(&originalData))
  755. offsetLocation := (sendDebugAddr % uintptr(unsafe.Sizeof(uintptr(0)))) + 1
  756. *(*uint32)(unsafe.Pointer(&bytes[offsetLocation])) = uint32(sendOffset)
  757. err = writeData(pid, alignedAddr, originalData)
  758. if err != nil {
  759. return err
  760. }
  761. return nil
  762. }
  763. func modifyReleaseFuncEnter(pid int, originEnterAddr, debugEnterAddr uintptr) error {
  764. offset := debugEnterAddr - (originEnterAddr + 5)
  765. // 读取原始数据
  766. alignedAddr := originEnterAddr & ^(uintptr(unsafe.Sizeof(uintptr(0))) - 1)
  767. originalData, err := readData(pid, alignedAddr)
  768. if err != nil {
  769. return err
  770. }
  771. bytes := (*[8]byte)(unsafe.Pointer(&originalData))
  772. bytes[originEnterAddr%uintptr(unsafe.Sizeof(uintptr(0)))] = 0xe9
  773. *(*uint32)(unsafe.Pointer(&bytes[(originEnterAddr%uintptr(unsafe.Sizeof(uintptr(0))))+1])) = uint32(offset)
  774. err = writeData(pid, alignedAddr, originalData)
  775. if err != nil {
  776. return err
  777. }
  778. return nil
  779. }
  780. func restoreOriginalInstructions(pid int, addr uintptr, instructions []byte) error {
  781. alignedAddr := addr & ^(uintptr(unsafe.Sizeof(uintptr(0))) - 1)
  782. originalData, err := readData(pid, alignedAddr)
  783. if err != nil {
  784. return err
  785. }
  786. bytes := (*[8]byte)(unsafe.Pointer(&originalData))
  787. for i := 0; i < len(instructions); i++ {
  788. bytes[addr%uintptr(unsafe.Sizeof(uintptr(0)))+uintptr(i)] = instructions[i]
  789. }
  790. err = writeData(pid, alignedAddr, originalData)
  791. if err != nil {
  792. return err
  793. }
  794. return nil
  795. }
  796. //func main() {
  797. // flag.StringVar(&PID, "p", "", "PID")
  798. // flag.Parse()
  799. // pidStr := PID // 替换为目标进程的 PID
  800. // pid, err := strconv.Atoi(pidStr)
  801. // if err != nil {
  802. // log.Fatalf("Invalid PID: %v", err)
  803. // }
  804. // functionName := "Java_java_net_SocketOutputStream_socketWrite0"
  805. // libraryName := "libnet.so"
  806. //
  807. // cwLibraryName := "cwlibnet.so"
  808. // cwLibraryPath := "/root/cwlibnet.so"
  809. //
  810. // jvmInjector := &JvmInjector{
  811. // pid: pid,
  812. // ReleaseLibNetInfo: LibNetInfo{
  813. // libName: libraryName,
  814. // FuncSymbol: instInfo{
  815. // SymName: functionName,
  816. // },
  817. // },
  818. // DebugLibNetInfo: LibNetInfo{
  819. // // TODO 根据版本设置
  820. // libName: cwLibraryName,
  821. // // TODO 根据版本设置
  822. // libPath: cwLibraryPath,
  823. // FuncSymbol: instInfo{
  824. // SymName: functionName,
  825. // },
  826. // },
  827. // }
  828. //
  829. // err = jvmInject(jvmInjector)
  830. // fmt.Println(err)
  831. //}
  832. func JvmInject(jvmInjector *JvmInjector) error {
  833. jvmInjector.DebugLibNetInfo.FuncSymbol.SymName = "CW_Java_java_net_SocketOutputStream_socketWrite0"
  834. pid := jvmInjector.Pid
  835. var err error
  836. err = jvmInjector.findReleaseFuncContextFromLibPath()
  837. fmt.Println(err)
  838. // Debug版本无需修改寄存器 TODO 直接使用原函数 需要在ebpf层适配
  839. // 已经加载so并指令修改正确的
  840. if jvmInjector.PreCheck.EbpfCanInjection {
  841. return nil
  842. }
  843. if err != nil {
  844. return err
  845. }
  846. // 原指令校验通过
  847. if !jvmInjector.PreCheck.NeedInjectionCheck {
  848. return err
  849. }
  850. printCodeData(jvmInjector.ReleaseLibNetInfo)
  851. _type, _, err := jvmInjector.findLibBaseFromProcMaps(jvmInjector.DebugLibNetInfo.LibName)
  852. if err != nil {
  853. // load so
  854. if _type == 1 {
  855. fmt.Println(err, "Start load so.")
  856. if jvmInjector.jvmInjectLib() == 0 {
  857. jvmInjector.PreCheck.LoadingCheck = true
  858. } else {
  859. return err
  860. }
  861. }
  862. } else {
  863. if jvmInjector.jvmInjectLib() == 0 {
  864. jvmInjector.PreCheck.LoadingCheck = true
  865. } else {
  866. return err
  867. }
  868. //jvmInjector.PreCheck.LoadingCheck = true
  869. //fmt.Println(err, "So already loaded.")
  870. //TODO 指令校验成功后 return nil
  871. //return fmt.Errorf("So already loaded.")
  872. }
  873. if !jvmInjector.PreCheck.LoadingCheck {
  874. return fmt.Errorf("Failed load so")
  875. }
  876. err = jvmInjector.findDebugFuncContextFromLibPath()
  877. if err != nil {
  878. return fmt.Errorf("Failed to find debug Context: %v", err)
  879. }
  880. printCodeData(jvmInjector.DebugLibNetInfo)
  881. //// 修改
  882. debugFuncEnterAddr := uintptr(jvmInjector.DebugLibNetInfo.FuncSymbol.SymAddr)
  883. originFuncEnterAddr := uintptr(jvmInjector.ReleaseLibNetInfo.FuncSymbol.SymAddr)
  884. recodeFuncEnterAddr := uintptr(jvmInjector.RecodeInfo.FuncSymbol.SymAddr)
  885. //fmt.Printf("<0x%x> -> <0x%x>\n", originFuncEnterAddr, debugFuncEnterAddr)
  886. //fmt.Printf("<0x%x> -> <0x%x>\n", debugIoFdAddr, ioFdReleaseTargetAddr)
  887. //fmt.Printf("<0x%x> -> <0x%x>\n", debugNetSendAddr, netSendReleaseTargetAddr)
  888. //
  889. // 附加到目标进程
  890. err = syscall.PtraceAttach(pid)
  891. if err != nil {
  892. fmt.Printf("ptrace ATTACH: %v", err)
  893. }
  894. //
  895. // 等待目标进程停止
  896. if _, err := syscall.Wait4(pid, nil, 0, nil); err != nil {
  897. fmt.Printf("wait4: %v", err)
  898. return err
  899. }
  900. // 保存原始指令并扩充新指令
  901. err = buildNopEnc(pid, debugFuncEnterAddr, originFuncEnterAddr)
  902. if err != nil {
  903. fmt.Println(err)
  904. return err
  905. }
  906. //
  907. //err = modifyNetSetTargetAddr(pid, debugNetSendAddr, netSendReleaseTargetAddr)
  908. //fmt.Println(err)
  909. //if err != nil {
  910. // fmt.Println(err)
  911. // return err
  912. //}
  913. // todo 二次效验 读取并验证地址
  914. //_, err = jvmInjector.checkDebugFuncSymAfterChange()
  915. //printCodeData(jvmInjector.ReleaseLibNetInfo)
  916. //printCodeData(jvmInjector.DebugLibNetInfo)
  917. //
  918. //// todo 效验目标函数内地址是否与预期一致
  919. //if !jvmInjector.validateAllModifyCheck() && err == nil {
  920. // return err
  921. //}
  922. //变更原指令 长跳转到新地址 保存到recode
  923. err = modifyOriginEnc(pid, uint64(debugFuncEnterAddr), originFuncEnterAddr, recodeFuncEnterAddr)
  924. //// 更新函数入口
  925. //err = modifyReleaseFuncEnter(pid, originFuncEnterAddr, debugFuncEnterAddr)
  926. //if err != nil {
  927. // fmt.Println(err)
  928. // return err
  929. //}
  930. //// 校验jmp地址修改正确
  931. //err = jvmInjector.checkReleaseFuncSymAfterChange()
  932. //if err != nil {
  933. // fmt.Println(err)
  934. // if len(jvmInjector.ReleaseLibNetInfo.FuncSymbol.OriginCode) == 5 {
  935. // err = restoreOriginalInstructions(pid, originFuncEnterAddr, jvmInjector.ReleaseLibNetInfo.FuncSymbol.OriginCode)
  936. // if err != nil {
  937. // fmt.Println(err)
  938. // return err
  939. // }
  940. // }
  941. //}
  942. //
  943. // 恢复执行
  944. if err = syscall.PtraceDetach(pid); err != nil {
  945. fmt.Printf("ptrace DETACH: %v", err)
  946. return err
  947. }
  948. return nil
  949. }