@zsa233/frida-analykit-agent 2.0.0 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/dist/api/android.d.ts +41 -0
  2. package/dist/api/android.js +1 -0
  3. package/dist/bridges.d.ts +4 -0
  4. package/dist/bridges.js +8 -0
  5. package/dist/cmodule/scan_adrp.d.ts +9 -0
  6. package/{src/cmodule/scan_adrp.ts → dist/cmodule/scan_adrp.js} +19 -30
  7. package/dist/config.d.ts +26 -0
  8. package/dist/config.js +27 -0
  9. package/dist/consts.d.ts +18 -0
  10. package/dist/consts.js +23 -0
  11. package/dist/elf/insn.d.ts +10 -0
  12. package/dist/elf/insn.js +43 -0
  13. package/dist/elf/module.d.ts +95 -0
  14. package/dist/elf/module.js +632 -0
  15. package/dist/elf/struct.d.ts +235 -0
  16. package/{src/elf/struct.ts → dist/elf/struct.js} +63 -149
  17. package/dist/elf/tools.d.ts +6 -0
  18. package/dist/elf/tools.js +25 -0
  19. package/dist/elf/verifier.d.ts +11 -0
  20. package/dist/elf/verifier.js +57 -0
  21. package/dist/elf/xref.d.ts +32 -0
  22. package/dist/elf/xref.js +271 -0
  23. package/dist/func.d.ts +7 -0
  24. package/dist/func.js +23 -0
  25. package/dist/helper.d.ts +130 -0
  26. package/dist/helper.js +527 -0
  27. package/{src/index.ts → dist/index.d.ts} +0 -1
  28. package/dist/index.js +9 -0
  29. package/dist/jni/env.d.ts +821 -0
  30. package/dist/jni/env.js +1054 -0
  31. package/{src/jni/struct.ts → dist/jni/struct.d.ts} +8 -54
  32. package/dist/jni/struct.js +173 -0
  33. package/dist/lib/libc.d.ts +68 -0
  34. package/dist/lib/libc.js +125 -0
  35. package/dist/lib/libssl.d.ts +23 -0
  36. package/dist/lib/libssl.js +60 -0
  37. package/dist/message.d.ts +18 -0
  38. package/dist/message.js +21 -0
  39. package/dist/net/ssl.d.ts +29 -0
  40. package/dist/net/ssl.js +249 -0
  41. package/dist/net/struct.d.ts +34 -0
  42. package/{src/net/struct.ts → dist/net/struct.js} +4 -18
  43. package/dist/net/tools.js +1 -0
  44. package/dist/process.d.ts +43 -0
  45. package/dist/process.js +77 -0
  46. package/dist/rpc.d.ts +1 -0
  47. package/dist/rpc.js +248 -0
  48. package/dist/utils/array_pointer.d.ts +21 -0
  49. package/dist/utils/array_pointer.js +81 -0
  50. package/dist/utils/queue.d.ts +19 -0
  51. package/dist/utils/queue.js +89 -0
  52. package/dist/utils/scan.d.ts +35 -0
  53. package/dist/utils/scan.js +72 -0
  54. package/dist/utils/std.d.ts +40 -0
  55. package/dist/utils/std.js +128 -0
  56. package/dist/utils/text_endec.d.ts +8 -0
  57. package/dist/utils/text_endec.js +29 -0
  58. package/dist/utils/utils.d.ts +28 -0
  59. package/dist/utils/utils.js +66 -0
  60. package/package.json +18 -5
  61. package/src/api/android.ts +0 -80
  62. package/src/bridges.ts +0 -18
  63. package/src/cmodule/scan_adrp.c +0 -81
  64. package/src/config.ts +0 -56
  65. package/src/consts.ts +0 -31
  66. package/src/elf/insn.ts +0 -61
  67. package/src/elf/module.ts +0 -751
  68. package/src/elf/tools.ts +0 -33
  69. package/src/elf/verifier.ts +0 -74
  70. package/src/elf/xref.ts +0 -360
  71. package/src/func.ts +0 -32
  72. package/src/helper.ts +0 -685
  73. package/src/jni/env.ts +0 -1439
  74. package/src/lib/libc.ts +0 -161
  75. package/src/lib/libssl.ts +0 -95
  76. package/src/message.ts +0 -26
  77. package/src/net/ssl.ts +0 -360
  78. package/src/process.ts +0 -137
  79. package/src/rpc.ts +0 -268
  80. package/src/runtime-globals.d.ts +0 -11
  81. package/src/utils/array_pointer.ts +0 -102
  82. package/src/utils/queue.ts +0 -102
  83. package/src/utils/scan.ts +0 -103
  84. package/src/utils/std.ts +0 -165
  85. package/src/utils/text_endec.ts +0 -35
  86. package/src/utils/utils.ts +0 -111
  87. /package/{src/net/tools.ts → dist/net/tools.d.ts} +0 -0
package/src/elf/module.ts DELETED
@@ -1,751 +0,0 @@
1
-
2
- import { Ehdr, Phdr, Dyn, Shdr, Soinfo, Sym, Rela } from './struct.js'
3
- import { nativeFunctionOptions, SYM_INFO_BIND, SYM_INFO_TYPE, SYM_SHNDX } from '../consts.js'
4
- import {
5
- Elf_Dyn, Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Sym, Elf_Rela,
6
- DyntabTag
7
- } from './struct.js'
8
- import { help , downAlign, upAlign, page_end, page_start } from '../helper.js'
9
- import { ArrayPointer } from '../utils/array_pointer.js'
10
- import { setGlobalProperties } from '../config.js'
11
- import { saveFileSource } from '../message.js'
12
-
13
-
14
- interface ElfModuleX extends BaseModule {}
15
-
16
-
17
- declare global {
18
- interface BaseModule {
19
- name: string
20
- base: NativePointer
21
- size: number
22
-
23
- }
24
- }
25
-
26
-
27
- export interface ElfModuleFixer {
28
- fixShdrs(modx: ElfModuleX): boolean
29
- }
30
-
31
-
32
- class ElfModuleX {
33
- module: BaseModule
34
- ehdr: Ehdr
35
- phdrs: Phdr[]
36
- dyntabs: Dyn[] | null
37
- shdrs: Shdr[] | null = null
38
- soinfo: Soinfo | null
39
- dynSymbols: Sym[] | null
40
- rela: Rela[] | null
41
- plt_rela: Rela[] | null
42
-
43
- symtab: Sym[] | null = null
44
- strtab: { [key: number]: string } | null = null
45
-
46
- private _keepNativeCb: {[key: string]: any}
47
-
48
- constructor(module: BaseModule, fixers?: ElfModuleFixer[], { symbolScanLimit=1000 }: {symbolScanLimit?: number } = {}) {
49
- this.name = module.name
50
- this.base = module.base
51
- this.size = module.size
52
- this.module = module
53
-
54
- this.ehdr = this.readEhdr()
55
- this.phdrs = this.readPhdrs()
56
- this.dyntabs = this.readDyntabs()
57
- this.soinfo = this.prelink_image()
58
- this.dynSymbols = this.scanSymbols(0, symbolScanLimit)
59
-
60
- try {
61
- this.shdrs = this.readShdrs()
62
- }catch(e){
63
- if(fixers) {
64
- for(let fixer of fixers) {
65
- if(fixer.fixShdrs(this)) {
66
- break
67
- }
68
- }
69
- }
70
- // if(!this.shdrs) {
71
- // throw e
72
- // }
73
- }
74
-
75
-
76
- this.rela = this.readRela()
77
- this.plt_rela = this.readPltRela()
78
-
79
-
80
- // TODO: android_relocs/relocate_relr
81
-
82
- this._keepNativeCb = {}
83
-
84
- this.link_image()
85
-
86
- return new Proxy(this, {
87
- get(target: any, prop: string) {
88
- if (prop in target) {
89
- return target[prop as keyof ElfModuleX]
90
- }
91
- return target.module[prop as keyof BaseModule]
92
- }
93
- })
94
- }
95
-
96
- static loadFromModule(mod: Module) {
97
- return new ElfModuleX(mod)
98
- }
99
-
100
- readEhdr() {
101
- const base = this.module.base
102
- const magic = Array.from(new Uint8Array(Elf_Ehdr.EI_Magic(base)))
103
- const FIXED_MAGIC = [0x7f, 0x45, 0x4c, 0x46]
104
- if (!FIXED_MAGIC.every((v, i) => v == magic[i])) {
105
- throw new Error(`error magic[${magic}]`)
106
- }
107
- const ei_class = Elf_Ehdr.EI_CLASS(base)
108
- const structOf = ei_class === 1 ? Elf_Ehdr.B32 : Elf_Ehdr.B64
109
- return {
110
- ei_class: ei_class,
111
- e_type: structOf.E_Type(base),
112
- e_phoff: structOf.E_Phoff(base),
113
- e_shoff: structOf.E_Shoff(base),
114
- e_phnum: structOf.E_Phnum(base),
115
- e_shnum: structOf.E_Shnum(base),
116
- e_shstrndx: structOf.E_Shstrndx(base),
117
- }
118
- }
119
-
120
- readPhdrs() {
121
- const base = this.module.base.add(this.ehdr.e_phoff)
122
- const structOf = this.ehdr.ei_class === 1 ? Elf_Phdr.B32 : Elf_Phdr.B64
123
- const tables: Phdr[] = []
124
- for (let i = 0; i < this.ehdr.e_phnum; i++) {
125
- const cellBase = base.add(i * structOf.SIZE)
126
- tables.push({
127
- p_type: structOf.P_Type(cellBase),
128
- p_offset: structOf.P_Offset(cellBase),
129
- p_vaddr: structOf.P_Vaddr(cellBase),
130
- p_paddr: structOf.P_Paddr(cellBase),
131
- p_filesz: structOf.P_Filesz(cellBase),
132
- p_memsz: structOf.P_Memsz(cellBase),
133
- p_align: structOf.P_Align(cellBase),
134
- })
135
- }
136
- return tables
137
- }
138
-
139
- readDyntabs() {
140
- let dynPhdr: Phdr | null = null
141
- for (let phdr of this.phdrs) {
142
- if (phdr.p_type !== 0x2) {
143
- continue
144
- }
145
- dynPhdr = phdr
146
- }
147
- if (!dynPhdr) {
148
- return null
149
- }
150
-
151
- const structOf = this.ehdr.ei_class === 1 ? Elf_Dyn.B32 : Elf_Dyn.B64
152
-
153
- const base = this.module.base.add(dynPhdr.p_vaddr)
154
- const tables: Dyn[] = []
155
-
156
- for (let i = 0; i < dynPhdr.p_filesz / structOf.SIZE; i++) {
157
- const cellBase = base.add(i * structOf.SIZE)
158
- tables.push({
159
- d_tag: structOf.D_Tag(cellBase),
160
- d_un: structOf.D_Un(cellBase),
161
- })
162
- }
163
- return tables
164
- }
165
-
166
- load_bias(value: number | NativePointer) { return this.module.base.add(value) }
167
-
168
- prelink_image() {
169
- if (this.dyntabs === null) {
170
- return null
171
- }
172
- const soinfo: Soinfo = new Soinfo()
173
- const structOf = this.ehdr.ei_class === 1 ? Elf_Rela.B32 : Elf_Rela.B64
174
- for (let dyn of this.dyntabs) {
175
- switch (Number(dyn.d_tag)) {
176
- case DyntabTag.DT_STRTAB:
177
- soinfo.strtab = this.load_bias(dyn.d_un)
178
- break
179
- case DyntabTag.DT_STRSZ:
180
- soinfo.strtab_size = dyn.d_un
181
- break
182
- case DyntabTag.DT_SYMTAB:
183
- soinfo.symtab = this.load_bias(dyn.d_un)
184
- break
185
- case DyntabTag.DT_JMPREL:
186
- soinfo.plt_rela = this.load_bias(dyn.d_un)
187
- break
188
- case DyntabTag.DT_PLTRELSZ:
189
- soinfo.plt_rela_count = Math.floor(dyn.d_un / structOf.SIZE)
190
- break
191
- case DyntabTag.DT_RELA:
192
- soinfo.rela = this.load_bias(dyn.d_un)
193
- break
194
- case DyntabTag.DT_RELASZ:
195
- soinfo.rela_count = Math.floor(dyn.d_un / structOf.SIZE)
196
- break
197
- case DyntabTag.DT_RELR:
198
- soinfo.relr = this.load_bias(dyn.d_un)
199
- break
200
- case DyntabTag.DT_RELRSZ:
201
- soinfo.relr_count = dyn.d_un
202
- break
203
- case DyntabTag.DT_INIT:
204
- soinfo.init_func = this.load_bias(dyn.d_un)
205
- break
206
- case DyntabTag.DT_INIT_ARRAY:
207
- soinfo.init_array = this.load_bias(dyn.d_un)
208
- break
209
- case DyntabTag.DT_INIT_ARRAYSZ:
210
- soinfo.init_array_count = dyn.d_un
211
- break
212
- case DyntabTag.DT_FINI_ARRAY:
213
- soinfo.fini_array = this.load_bias(dyn.d_un)
214
- break
215
- case DyntabTag.DT_FINI_ARRAYSZ:
216
- soinfo.fini_array_count = dyn.d_un
217
- break
218
- case DyntabTag.DT_PLTGOT:
219
- soinfo.plt_got = this.load_bias(dyn.d_un)
220
- break
221
- }
222
- }
223
- return soinfo
224
- }
225
-
226
- link_image() {
227
- if (this.dynSymbols == null || (this.rela == null && this.plt_rela == null)) {
228
- return
229
- }
230
-
231
- const relas = (this.rela || []).concat(this.plt_rela || [])
232
- const structOf = this.ehdr.ei_class === 1 ? Elf_Rela.B32 : Elf_Rela.B64
233
- for (let rel of relas) {
234
- const type = BigInt(rel.r_info) & structOf.INFO_TYPE
235
- const sym = BigInt(rel.r_info) >> structOf.INFO_SYM
236
- const reloc = rel.r_offset
237
- if (type === 0n) {
238
- continue
239
- }
240
- const s = this.dynSymbols[Number(sym)]
241
- if (sym === 0n) {
242
- } else if (s?.name && reloc) {
243
- const relocPtr = this.module.base.add(reloc)
244
- s.relocPtr = relocPtr
245
- s.st_value = ptr(structOf.Reloc(relocPtr))
246
- }
247
- }
248
- }
249
-
250
- off2addr(offset: number) {
251
- let dstPhdr: Phdr | null = null
252
- for (let phdr of this.phdrs) {
253
- if (phdr.p_type !== 0x1) {
254
- continue
255
- }
256
- const file_page_start = page_start(phdr.p_offset)
257
- const file_length = phdr.p_offset + phdr.p_filesz - file_page_start
258
- if (!dstPhdr || phdr.p_offset + phdr.p_filesz >= dstPhdr.p_offset + dstPhdr.p_filesz) {
259
- dstPhdr = phdr
260
- }
261
- if (offset >= file_page_start && offset < file_page_start + file_length) {
262
- dstPhdr = phdr
263
- break
264
- }
265
-
266
- }
267
- if (dstPhdr) {
268
- const seg_page_start = page_start(dstPhdr.p_vaddr)
269
- const file_page_start = page_start(dstPhdr.p_offset)
270
- return seg_page_start - file_page_start + offset
271
- }
272
- return null
273
- }
274
-
275
- readShdrs() {
276
- const addr = this.off2addr(this.ehdr.e_shoff)
277
- if (!addr) {
278
- return null
279
- }
280
- const base = this.module.base.add(addr)
281
- if(!this.isMyAddr(base)) {
282
- throw new Error(`shdrs not found in ${base}`)
283
- }
284
- const structOf = this.ehdr.ei_class === 1 ? Elf_Shdr.B32 : Elf_Shdr.B64
285
- const tables: Shdr[] = []
286
- for (let i = 0; i < this.ehdr.e_shnum; i++) {
287
- const cellBase = base.add(i * structOf.SIZE)
288
- const sh_addr = structOf.Sh_Addr(cellBase)
289
- const sh_size = structOf.Sh_Size(cellBase)
290
- tables.push({
291
- name: null,
292
- base: this.module.base.add(sh_addr),
293
- size: sh_size,
294
-
295
- sh_name: structOf.Sh_Name(cellBase),
296
- sh_type: structOf.Sh_Type(cellBase),
297
- sh_addr: sh_addr,
298
- sh_offset: structOf.Sh_Offset(cellBase),
299
- sh_size: sh_size,
300
- sh_link: structOf.Sh_Link(cellBase),
301
- sh_info: structOf.Sh_Info(cellBase),
302
- sh_addralign: structOf.Sh_Addralign(cellBase),
303
- sh_entsize: structOf.Sh_Entsize(cellBase),
304
- })
305
- }
306
-
307
- // fill name
308
- const shstrndxShdr = tables[this.ehdr.e_shstrndx]
309
- const shstrBase = this.base.add(shstrndxShdr.sh_offset)
310
- for(let v of tables) {
311
- v.name = shstrBase.add(v.sh_name).readCString()
312
- }
313
- return tables
314
- }
315
-
316
- getSymString(index: number) {
317
- if (this.soinfo == null || index >= this.soinfo.strtab_size) {
318
- return null
319
- }
320
- const p = this.soinfo.strtab.add(index)
321
- return p.readCString()
322
- }
323
-
324
- scanSymbols(cursor: number, limit: number): Sym[] | null {
325
- if(this.soinfo == null) {
326
- return null
327
- }
328
- const base = this.soinfo.symtab
329
- const structOf = this.ehdr.ei_class === 1 ? Elf_Sym.B32 : Elf_Sym.B64
330
- const symbols: Sym[] = []
331
- for (let i = cursor; i < cursor + limit; i++) {
332
- const cellBase = base.add(i * structOf.SIZE)
333
- const nameIDX = structOf.St_Name(cellBase)
334
- const name = this.getSymString(nameIDX)
335
- if (name == null) {
336
- break
337
- }
338
- let implPtr = ptr(structOf.St_Value(cellBase))
339
- const st_info = structOf.St_Info(cellBase)
340
- const st_shndx = structOf.St_Shndx(cellBase)
341
- const st_other = structOf.St_Other(cellBase)
342
-
343
- if ([SYM_SHNDX.SHN_UNDEF, SYM_SHNDX.SHN_ABS].indexOf(st_shndx) === -1) {
344
- if ([SYM_INFO_TYPE.STT_FUNC, SYM_INFO_TYPE.STT_OBJECT].indexOf(st_info & 0xF) !== -1) {
345
- if (!this.isMyAddr(implPtr)) {
346
- implPtr = this.module.base.add(implPtr)
347
- }
348
- }
349
- }
350
-
351
- const sym: Sym = {
352
- name: name,
353
- relocPtr: null,
354
- hook: null,
355
- implPtr: implPtr,
356
- linked: true,
357
-
358
- st_name: nameIDX,
359
- st_info: st_info,
360
- st_other: st_other,
361
- st_shndx: st_shndx,
362
- st_value: implPtr,
363
- st_size: structOf.St_Size(cellBase),
364
- }
365
- symbols.push(sym)
366
- }
367
- return symbols
368
- }
369
-
370
- readRela() {
371
- if(this.soinfo == null) {
372
- return null
373
- }
374
- const structOf = this.ehdr.ei_class === 1 ? Elf_Rela.B32 : Elf_Rela.B64
375
- // DT_RELA
376
- const base = this.soinfo.rela
377
- const tables: Rela[] = []
378
- for (let i = 0; i < (this.soinfo.rela_count || 0); i++) {
379
- const cellBase = base.add(i * structOf.SIZE)
380
- const rela: Rela = {
381
- r_offset: structOf.R_Offset(cellBase),
382
- r_info: structOf.R_Info(cellBase),
383
- r_addend: structOf.R_Addend(cellBase),
384
- }
385
- tables.push(rela)
386
- }
387
- return tables
388
- }
389
-
390
- readPltRela() {
391
- if (this.soinfo == null) {
392
- return null
393
- }
394
- const structOf = this.ehdr.ei_class === 1 ? Elf_Rela.B32 : Elf_Rela.B64
395
- // DT_JMPREL
396
- const base = this.soinfo.plt_rela
397
- const tables: Rela[] = []
398
- for (let i = 0; i < (this.soinfo.plt_rela_count || 0); i++) {
399
- const cellBase = base.add(i * structOf.SIZE)
400
- const rela: Rela = {
401
- r_offset: structOf.R_Offset(cellBase),
402
- r_info: structOf.R_Info(cellBase),
403
- r_addend: structOf.R_Addend(cellBase),
404
- }
405
- tables.push(rela)
406
- }
407
- return tables
408
- }
409
-
410
- attachSymbol<RetType extends NativeFunctionReturnType, ArgTypes extends any[]>(
411
- symName: string, fn: AnyFunction, retType: RetType, argTypes: ArgTypes, abi = undefined,
412
- ) {
413
- if(this.dynSymbols == null) {
414
- return false
415
- }
416
- const sym = this.dynSymbols.find(sym => sym.name == symName)
417
- if (!sym || sym.st_value == null || sym.relocPtr == null) {
418
- return false
419
- }
420
- const impl = new NativeFunction(sym.st_value, retType, argTypes, nativeFunctionOptions)
421
- const wrapper = function () {
422
- const args = [impl, ...Array.from(arguments)]
423
- return fn(...args)
424
- }
425
- const cb = new NativeCallback(wrapper, retType, argTypes, abi)
426
- let isWritten = false
427
-
428
- const doWrite = () => {
429
- isWritten = true
430
- this._keepNativeCb[symName] = cb
431
- sym.relocPtr!.writePointer(cb)
432
- sym.hook = cb
433
- help.$info(`[attachSymbol] ${symName} [${impl}] => [${cb}]`)
434
- }
435
-
436
- const rangeDetail = Process.findRangeByAddress(sym.relocPtr)
437
- if (rangeDetail) {
438
- if(rangeDetail.protection.indexOf('w') === -1) {
439
- const prots = rangeDetail.protection[0] + 'w' + rangeDetail.protection[2]
440
- Memory.protect(sym.relocPtr, Process.pointerSize, prots)
441
- }
442
- doWrite()
443
- // FIXME: changeback
444
- }
445
- // fallback
446
- if(!isWritten) {
447
- for (let prot of ['rwx', 'rw', 'rx']) {
448
- if (Memory.protect(sym.relocPtr, Process.pointerSize, prot)) {
449
- doWrite()
450
- break
451
- }
452
- }
453
- }
454
- return isWritten
455
- }
456
-
457
- findSymbol(symName: string): Sym | undefined {
458
- let sym
459
- if(this.dynSymbols !== null) {
460
- sym = this.dynSymbols.find(sym => sym.name === symName)
461
- }
462
- if (!sym && this.symtab !== null) {
463
- return this.symtab.find(sym => sym.name === symName)
464
- }
465
- return sym
466
- }
467
-
468
- fromAddress(addr: NativePointer) {
469
- if(this.base == null) {
470
- return null
471
- }
472
- const base = this.module.base
473
- const endAddr = this.base.add(this.module.size)
474
- if (this.isMyAddr(addr)) {
475
- return `${addr} ${this.module.name}!${addr.sub(base)}`
476
- }
477
- return addr
478
- }
479
-
480
- isMyAddr(addr: NativePointer) {
481
- return addr >= this.base && addr < this.base.add(this.size)
482
- }
483
-
484
- getSegment(seg: string): Shdr | null {
485
- if (this.shdrs) {
486
- return this.shdrs.find(shdr => shdr.name === seg) || null
487
- }
488
- return null
489
- }
490
-
491
- dump(tag: string) {
492
- let buff: ArrayBuffer | null = null
493
- help.memoryReadDo(this.base, this.size, (makeReadable, makeRecovery) => {
494
- makeReadable()
495
- buff = this.base.readByteArray(this.size)
496
- makeRecovery()
497
- })
498
- if (buff) {
499
- help.saveFile(tag, buff, 'wb', saveFileSource.elfModule)
500
- }
501
- }
502
-
503
- }
504
-
505
-
506
- export { ElfModuleX }
507
-
508
-
509
- export class ElfFileFixer implements ElfModuleFixer {
510
- path: string
511
-
512
- private modx?: ElfModuleX
513
- private fileBytes?: ArrayBuffer
514
- private ehdr?: Ehdr
515
- private phdrs?: Phdr[]
516
- private shdrs?: Shdr[]
517
- private strtab?: { [key: number]: string }
518
-
519
- private shstrtabShdr?: Shdr
520
-
521
- constructor(path: string) {
522
- this.path = path
523
- }
524
-
525
- getFilePtr(): ArrayPointer {
526
- if(!this.fileBytes) {
527
- this.fileBytes = help.readFile(this.path)
528
- }
529
- return new ArrayPointer(0, this.fileBytes!)
530
- }
531
-
532
- ensureEhdr() {
533
- if(!this.ehdr) {
534
- this.ehdr = this.readEhdr()
535
- }
536
- help.assert(this.ehdr)
537
- }
538
-
539
- ensurePhdrs() {
540
- if (!this.phdrs) {
541
- this.phdrs = this.readPhdrs()
542
- }
543
- help.assert(this.phdrs)
544
- }
545
-
546
- ensureShdrs(){
547
- if (!this.shdrs) {
548
- this.shdrs = this.readShdrs()
549
- }
550
- help.assert(this.shdrs)
551
- }
552
-
553
- ensureStrtab() {
554
- if (!this.strtab) {
555
- this.strtab = this.readStrtab()
556
- }
557
- help.assert(this.shdrs)
558
- }
559
-
560
- readEhdr() {
561
- const base = this.getFilePtr()
562
- const magic = Array.from(new Uint8Array(Elf_Ehdr.EI_Magic(base)))
563
- const FIXED_MAGIC = [0x7f, 0x45, 0x4c, 0x46]
564
- if (!FIXED_MAGIC.every((v, i) => v == magic[i])) {
565
- throw new Error(`error magic[${magic}]`)
566
- }
567
- const ei_class = Elf_Ehdr.EI_CLASS(base)
568
- const structOf = ei_class === 1 ? Elf_Ehdr.B32 : Elf_Ehdr.B64
569
- return {
570
- ei_class: ei_class,
571
- e_type: structOf.E_Type(base),
572
- e_phoff: structOf.E_Phoff(base),
573
- e_shoff: structOf.E_Shoff(base),
574
- e_phnum: structOf.E_Phnum(base),
575
- e_shnum: structOf.E_Shnum(base),
576
- e_shstrndx: structOf.E_Shstrndx(base),
577
- }
578
- }
579
-
580
- readPhdrs(): Phdr[] {
581
- this.ensureEhdr()
582
-
583
- const fileBase = this.getFilePtr()
584
- const ehdr = this.ehdr!
585
- const base = fileBase.add(ehdr.e_phoff)
586
- const structOf = ehdr.ei_class === 1 ? Elf_Phdr.B32 : Elf_Phdr.B64
587
- const tables: Phdr[] = []
588
- for (let i = 0; i < ehdr.e_phnum; i++) {
589
- const cellBase = base.add(i * structOf.SIZE)
590
- tables.push({
591
- p_type: structOf.P_Type(cellBase),
592
- p_offset: structOf.P_Offset(cellBase),
593
- p_vaddr: structOf.P_Vaddr(cellBase),
594
- p_paddr: structOf.P_Paddr(cellBase),
595
- p_filesz: structOf.P_Filesz(cellBase),
596
- p_memsz: structOf.P_Memsz(cellBase),
597
- p_align: structOf.P_Align(cellBase),
598
- })
599
- }
600
- return tables
601
- }
602
-
603
- readShdrs() {
604
- this.ensureEhdr()
605
- this.ensurePhdrs()
606
-
607
- const fileBase = this.getFilePtr()
608
- const ehdr = this.ehdr!
609
- const base = fileBase.add(ehdr.e_shoff)
610
-
611
- const structOf = ehdr.ei_class === 1 ? Elf_Shdr.B32 : Elf_Shdr.B64
612
- const tables: Shdr[] = []
613
- for (let i = 0; i < ehdr.e_shnum; i++) {
614
- const cellBase = base.add(i * structOf.SIZE)
615
- const sh_addr = structOf.Sh_Addr(cellBase)
616
- const sh_size = structOf.Sh_Size(cellBase)
617
- tables.push({
618
- name: null,
619
- base: this.modx!.base.add(sh_addr),
620
- size: sh_size,
621
-
622
- sh_name: structOf.Sh_Name(cellBase),
623
- sh_type: structOf.Sh_Type(cellBase),
624
- sh_addr: structOf.Sh_Addr(cellBase),
625
- sh_offset: structOf.Sh_Offset(cellBase),
626
- sh_size: structOf.Sh_Size(cellBase),
627
- sh_link: structOf.Sh_Link(cellBase),
628
- sh_info: structOf.Sh_Info(cellBase),
629
- sh_addralign: structOf.Sh_Addralign(cellBase),
630
- sh_entsize: structOf.Sh_Entsize(cellBase),
631
- })
632
- }
633
- this.shdrs = tables
634
- // fill name
635
- for(let v of tables) {
636
- v.name = this.getShstrtabString(v.sh_name)
637
- }
638
-
639
- return tables
640
- }
641
-
642
- readStrtab(): { [key: number]: string } | undefined {
643
- this.ensureEhdr()
644
- this.ensurePhdrs()
645
- this.ensureShdrs()
646
-
647
- const shdr = this.shdrs!.find(shdr => this.getShstrtabString(shdr.sh_name) === '.strtab')
648
- if (!shdr) {
649
- return
650
- }
651
- const fileBase = this.getFilePtr()
652
- const strbase = fileBase.add(shdr.sh_offset)
653
- const strend = strbase.add(shdr.sh_size)
654
- const strtabs: { [key: number]: string } = {}
655
- let next = strbase
656
- while (next < strend) {
657
- const off = Number(next.sub(strbase))
658
- const cstr = next.readCString()
659
- next = next.add(cstr.length + 1)
660
- strtabs[off] = cstr
661
- }
662
- return strtabs
663
- }
664
-
665
- getShstrtabString(nameOff: number): string {
666
- if (!this.shstrtabShdr) {
667
- const shdr = this.shdrs![this.ehdr!.e_shstrndx]
668
- this.shstrtabShdr = shdr
669
- }
670
- const fileBase = this.getFilePtr()
671
- return fileBase.add(this.shstrtabShdr.sh_offset).add(nameOff).readCString()
672
- }
673
-
674
- getSymString(nameIDX: number): string {
675
- return this.strtab![nameIDX]
676
- }
677
-
678
-
679
- readSymtab(): Sym[] | null{
680
- this.ensureEhdr()
681
- this.ensurePhdrs()
682
- this.ensureShdrs()
683
- this.ensureStrtab()
684
-
685
- const shdr = this.shdrs!.find(shdr => this.getShstrtabString(shdr.sh_name) === '.symtab')
686
- if(!shdr) {
687
- return null
688
- }
689
- const fileBase = this.getFilePtr()
690
- const ehdr = this.ehdr!
691
- const structOf = ehdr.ei_class === 1 ? Elf_Sym.B32 : Elf_Sym.B64
692
-
693
- const base = fileBase.add(shdr.sh_offset)
694
- const num = shdr.sh_size / structOf.SIZE
695
- const symbols: Sym[] = []
696
- for (let i = 0; i < num; i++) {
697
- const cellBase = base.add(i * structOf.SIZE)
698
- const nameIDX = structOf.St_Name(cellBase)
699
- const name = this.getSymString(nameIDX)
700
- let implPtr = ptr(structOf.St_Value(cellBase))
701
- const st_info = structOf.St_Info(cellBase)
702
- const st_shndx = structOf.St_Shndx(cellBase)
703
- const st_other = structOf.St_Other(cellBase)
704
-
705
- if ([SYM_SHNDX.SHN_UNDEF, SYM_SHNDX.SHN_ABS].indexOf(st_shndx) === -1) {
706
- if ([SYM_INFO_TYPE.STT_FUNC, SYM_INFO_TYPE.STT_OBJECT].indexOf(st_info & 0xF) !== -1) {
707
- if (!this.modx?.isMyAddr(implPtr)) {
708
- implPtr = this.modx!.module.base.add(implPtr)
709
- }
710
- }
711
- }
712
- const sym: Sym = {
713
- name: name,
714
- relocPtr: null,
715
- hook: null,
716
- implPtr: implPtr,
717
- linked: true,
718
-
719
- st_name: nameIDX,
720
- st_info: st_info,
721
- st_other: st_other,
722
- st_shndx: st_shndx,
723
- st_value: implPtr,
724
- st_size: structOf.St_Size(cellBase),
725
- }
726
- symbols.push(sym)
727
- }
728
- return symbols
729
- }
730
-
731
- fixShdrs(modx: ElfModuleX): boolean {
732
- this.modx = modx
733
- try {
734
- const shdrs = this.readShdrs()
735
- if(shdrs){
736
- this.strtab = this.readStrtab()
737
- const symtab = this.readSymtab()
738
-
739
- modx.shdrs = shdrs
740
- modx.strtab = this.strtab || null
741
- modx.symtab = symtab
742
- return true
743
- }
744
- }catch(e) {
745
- console.error(`[ElfFileFixer]fixShdrs name[${modx.name}] e[${e}]`)
746
- }
747
-
748
- return false
749
- }
750
-
751
- }