@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.
- package/dist/api/android.d.ts +41 -0
- package/dist/api/android.js +1 -0
- package/dist/bridges.d.ts +4 -0
- package/dist/bridges.js +8 -0
- package/dist/cmodule/scan_adrp.d.ts +9 -0
- package/{src/cmodule/scan_adrp.ts → dist/cmodule/scan_adrp.js} +19 -30
- package/dist/config.d.ts +26 -0
- package/dist/config.js +27 -0
- package/dist/consts.d.ts +18 -0
- package/dist/consts.js +23 -0
- package/dist/elf/insn.d.ts +10 -0
- package/dist/elf/insn.js +43 -0
- package/dist/elf/module.d.ts +95 -0
- package/dist/elf/module.js +632 -0
- package/dist/elf/struct.d.ts +235 -0
- package/{src/elf/struct.ts → dist/elf/struct.js} +63 -149
- package/dist/elf/tools.d.ts +6 -0
- package/dist/elf/tools.js +25 -0
- package/dist/elf/verifier.d.ts +11 -0
- package/dist/elf/verifier.js +57 -0
- package/dist/elf/xref.d.ts +32 -0
- package/dist/elf/xref.js +271 -0
- package/dist/func.d.ts +7 -0
- package/dist/func.js +23 -0
- package/dist/helper.d.ts +130 -0
- package/dist/helper.js +527 -0
- package/{src/index.ts → dist/index.d.ts} +0 -1
- package/dist/index.js +9 -0
- package/dist/jni/env.d.ts +821 -0
- package/dist/jni/env.js +1054 -0
- package/{src/jni/struct.ts → dist/jni/struct.d.ts} +8 -54
- package/dist/jni/struct.js +173 -0
- package/dist/lib/libc.d.ts +68 -0
- package/dist/lib/libc.js +125 -0
- package/dist/lib/libssl.d.ts +23 -0
- package/dist/lib/libssl.js +60 -0
- package/dist/message.d.ts +18 -0
- package/dist/message.js +21 -0
- package/dist/net/ssl.d.ts +29 -0
- package/dist/net/ssl.js +249 -0
- package/dist/net/struct.d.ts +34 -0
- package/{src/net/struct.ts → dist/net/struct.js} +4 -18
- package/dist/net/tools.js +1 -0
- package/dist/process.d.ts +43 -0
- package/dist/process.js +77 -0
- package/dist/rpc.d.ts +1 -0
- package/dist/rpc.js +248 -0
- package/dist/utils/array_pointer.d.ts +21 -0
- package/dist/utils/array_pointer.js +81 -0
- package/dist/utils/queue.d.ts +19 -0
- package/dist/utils/queue.js +89 -0
- package/dist/utils/scan.d.ts +35 -0
- package/dist/utils/scan.js +72 -0
- package/dist/utils/std.d.ts +40 -0
- package/dist/utils/std.js +128 -0
- package/dist/utils/text_endec.d.ts +8 -0
- package/dist/utils/text_endec.js +29 -0
- package/dist/utils/utils.d.ts +28 -0
- package/dist/utils/utils.js +66 -0
- package/package.json +18 -5
- package/src/api/android.ts +0 -80
- package/src/bridges.ts +0 -18
- package/src/cmodule/scan_adrp.c +0 -81
- package/src/config.ts +0 -56
- package/src/consts.ts +0 -31
- package/src/elf/insn.ts +0 -61
- package/src/elf/module.ts +0 -751
- package/src/elf/tools.ts +0 -33
- package/src/elf/verifier.ts +0 -74
- package/src/elf/xref.ts +0 -360
- package/src/func.ts +0 -32
- package/src/helper.ts +0 -685
- package/src/jni/env.ts +0 -1439
- package/src/lib/libc.ts +0 -161
- package/src/lib/libssl.ts +0 -95
- package/src/message.ts +0 -26
- package/src/net/ssl.ts +0 -360
- package/src/process.ts +0 -137
- package/src/rpc.ts +0 -268
- package/src/runtime-globals.d.ts +0 -11
- package/src/utils/array_pointer.ts +0 -102
- package/src/utils/queue.ts +0 -102
- package/src/utils/scan.ts +0 -103
- package/src/utils/std.ts +0 -165
- package/src/utils/text_endec.ts +0 -35
- package/src/utils/utils.ts +0 -111
- /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
|
-
}
|