@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/tools.ts DELETED
@@ -1,33 +0,0 @@
1
- import { setGlobalProperties } from "../config.js"
2
- import { ElfFileFixer, ElfModuleX } from "./module.js"
3
-
4
-
5
-
6
- export class ElfTools {
7
-
8
- static findModuleByName(name: string, tryFix: boolean = false): ElfModuleX | null {
9
- const mod = Process.findModuleByName(name)
10
- if (mod === null) {
11
- return null
12
- }
13
- return this.loadFromModule(mod, tryFix)
14
- }
15
-
16
- static getModuleByName(name: string, tryFix: boolean = false): ElfModuleX {
17
- const modx = this.findModuleByName(name, tryFix)
18
- if (modx === null) {
19
- throw new Error(`[getModuleByName] ${name} module not found.`)
20
- }
21
- return modx
22
- }
23
-
24
- static loadFromModule(mod: Module, tryFix: boolean = false): ElfModuleX {
25
- const fixers = tryFix ? [new ElfFileFixer(mod.path)] : undefined
26
- return new ElfModuleX(mod, fixers)
27
- }
28
- }
29
-
30
-
31
- setGlobalProperties({
32
- ElfTools,
33
- })
@@ -1,74 +0,0 @@
1
- import { setGlobalProperties } from "../config.js"
2
- import { InstructionSequence } from "./insn.js"
3
-
4
-
5
-
6
- type ScoreResult = {
7
- instructions: Arm64Instruction[],
8
- eoi?: Arm64Instruction,
9
- score: number
10
- }
11
-
12
-
13
- export class Subroutine extends InstructionSequence {
14
-
15
- constructor(entry: Arm64Instruction) {
16
- super(entry)
17
- }
18
-
19
- scoreThunk(): ScoreResult {
20
- const MAX_INSTR = 20
21
- let score: number = 0
22
-
23
- let i: number = 0
24
- const insns: Arm64Instruction[] = []
25
- loop: for (const insn of this) {
26
- insns.push(insn)
27
- const ops = insn.operands
28
- switch (insn.mnemonic) {
29
- case 'br':
30
- case 'b':
31
- this.eoi = insn
32
- score += 100
33
- break loop
34
- case 'stp':
35
- case 'ldp':
36
- if (ops[2].type === 'mem' && ops[2].value.base === 'sp') {
37
- score -= 20
38
- break
39
- }
40
- case 'ret':
41
- score = 0
42
- this.eoi = insn
43
- break
44
- case 'sub':
45
- case 'add':
46
- if (ops[0].value as string === 'sp') {
47
- score -= 20
48
- break
49
- }
50
- break
51
- }
52
- if (i >= 5) {
53
- // 指令越多分数越低
54
- score -= 5
55
- }
56
- i++
57
- if (i >= MAX_INSTR) {
58
- break
59
- }
60
- }
61
-
62
- return {
63
- instructions: insns,
64
- eoi: this.eoi,
65
- score: score,
66
- }
67
- }
68
-
69
- }
70
-
71
-
72
- setGlobalProperties({
73
- Subroutine,
74
- })
package/src/elf/xref.ts DELETED
@@ -1,360 +0,0 @@
1
-
2
-
3
- import { help, MemoryPage, NativePointerObject } from "../helper.js"
4
- import { ScanAdrpCMod } from "../cmodule/scan_adrp.js"
5
- import { setGlobalProperties } from "../config.js";
6
- import { InstructionSequence } from "./insn.js";
7
-
8
-
9
-
10
- function countLeadingSignBits(input: number | bigint, width: number): number {
11
- if(width < 1 || width > 64) {
12
- throw new RangeError('width must be between 1 and 64');
13
- }
14
- const mask = (1n << BigInt(width)) - 1n
15
- let value = BigInt(input) & mask
16
-
17
- const signBit = (value >> BigInt(width - 1)) & 1n
18
- let count = 0
19
- for(let i = width - 1; i >= 0; i--) {
20
- const bit = (value >> BigInt(i)) & 1n
21
- if(bit === signBit) {
22
- count ++
23
- }else{
24
- break
25
- }
26
- }
27
- return count
28
- }
29
-
30
-
31
- function choiceMatchPattern(p: NativePointer, byteNum: number): string {
32
- return p.toMatchPattern().split(/\s+/).slice(0, byteNum).join(' ')
33
- }
34
-
35
-
36
- function stripLeadingZeros(hexDump: string): { count: number, stripped: string}{
37
- const parts = hexDump.trim().split(/\s+/)
38
- let count = 0
39
- for(const part of parts) {
40
- if(part.toLowerCase() === '00') {
41
- count++
42
- }else{
43
- break
44
- }
45
- }
46
- const strippedParts = parts.slice(count)
47
- return {
48
- count,
49
- stripped: strippedParts.join(' ')
50
- }
51
- }
52
-
53
-
54
-
55
-
56
- export class AdrlXref {
57
- /* adr/adrp Xi, #{imm1}
58
- ------------------------------------------------------------------
59
- | 31 | 30 ─ 29 | 28 27 26 25 24 | 23 ──────────────── 5 | 4 ─ 0 |
60
- | op | immlo | 1 0 0 0 0 | immhi (19b) | Rd |
61
- ------------------------------------------------------------------
62
- adr : op=0
63
- adrp: op=1
64
- */
65
-
66
- /* add Xm, Xn, #{imm2}
67
- ----------------------------------------------------------------------
68
- | 31 | 30 | 29 | 28 27 26 25 24 | 23 ─ 22 | 21 ─ 10 | 9 ─ 5 | 4 ─ 0 |
69
- | sf | op | S | 1 0 0 0 1 | sh | imm12 | Rn | Rd |
70
- ----------------------------------------------------------------------
71
- */
72
-
73
- static readonly ADRP_FIXED28_24_BITSET_MASK = ptr(0b10000).shl(24)
74
-
75
- target: NativePointer
76
-
77
- constructor(target: NativePointer) {
78
- this.target = target
79
- }
80
-
81
- get targetPage(): NativePointer{
82
- return this.target.and(ptr('0xfff').not())
83
- }
84
-
85
- get targetPageOffset(): NativePointer {
86
- return this.target.and('0xfff')
87
- }
88
-
89
-
90
- scanAdrl(
91
- scanRange: { base: NativePointer, size: number },
92
- maxGapToAdd: number = 16,
93
- ): Adrl[] {
94
- const { base, size } = scanRange
95
-
96
- const targetPage = this.targetPage
97
- // adrp
98
- const op = ptr(0b1)
99
-
100
- const adrpMatches: NativePointer[] = []
101
-
102
- const pageMask = ptr(Process.pageSize - 1).not()
103
- const adrpImmLenMask = ptr(0x1FFFFF)
104
-
105
- type ScanTargetRange = {
106
- base: NativePointer
107
- size: number
108
- high: boolean
109
- }
110
-
111
- help.memoryReadDo(base, size, (makeReadable, makeRecovery): void => {
112
- makeReadable()
113
- const ranges: ScanTargetRange[] = []
114
- if (this.target <= base) {
115
- ranges.push({ base, size, high: true })
116
- } else if (this.target >= base.add(size)) {
117
- ranges.push({ base, size, high: false })
118
- } else {
119
- ranges.push({ base, size: Number(this.target.sub(base)), high: false })
120
- ranges.push({ base: this.target, size: size - Number(this.target.sub(base)), high: true })
121
- }
122
-
123
- for (let range of ranges) {
124
- const minPage = range.base.and(pageMask)
125
- const maxPage = range.base.add(range.size).and(pageMask)
126
-
127
- const maxPageDelta = targetPage.sub(minPage).shr(12).and(adrpImmLenMask)
128
- const minPageDelta = targetPage.sub(maxPage).shr(12).and(adrpImmLenMask)
129
-
130
- let immVal: NativePointer
131
- let leadingCount: number
132
- if(range.high) {
133
- leadingCount = countLeadingSignBits(BigInt(minPageDelta.toString()), 21)
134
- immVal = adrpImmLenMask
135
- }else{
136
- leadingCount = countLeadingSignBits(BigInt(maxPageDelta.toString()), 21)
137
- immVal = NULL
138
- }
139
- const immMask: NativePointer = ptr((((1n << BigInt(leadingCount)) - 1n) << BigInt(21 - leadingCount)).toString())
140
-
141
- const B = ptr(1)
142
- const immloMask = immMask.and(0b11)
143
- const immhiMask = immMask.shr(2)
144
- const anyRdMask = NULL
145
- const adrpMask = choiceMatchPattern(
146
- NULL.or(B.shl(31))
147
- .or(immloMask.shl(29))
148
- .or(AdrlXref.ADRP_FIXED28_24_BITSET_MASK)
149
- .or(immhiMask.shl(5))
150
- .or(anyRdMask),
151
- 4,
152
- )
153
- const { stripped: adrpMaskStripped, count: alignOffset } = stripLeadingZeros(adrpMask)
154
-
155
- const immlo = immVal.and(0b11)
156
- const immhi = immVal.shr(2)
157
- const anyRd = NULL
158
- const adrpSign = choiceMatchPattern(
159
- NULL.or(op.shl(31))
160
- .or(immlo.shl(29))
161
- .or(AdrlXref.ADRP_FIXED28_24_BITSET_MASK)
162
- .or(immhi.shl(5))
163
- .or(anyRd),
164
- 4,
165
- )
166
- const adrpSignStripped = adrpSign.split(/\s+/).slice(alignOffset).join(' ')
167
-
168
- const scanPattern = `${adrpSignStripped} : ${adrpMaskStripped}`
169
-
170
- const scanRes = ScanAdrpCMod.scan(
171
- range, scanPattern, this.target, alignOffset,
172
- )
173
- if(scanRes.length) {
174
- adrpMatches.push(...scanRes)
175
- }
176
- }
177
-
178
- makeRecovery()
179
- })
180
-
181
- const adrpInstructions = adrpMatches.reduce<Adrl[]>((acc, v) => {
182
- const adrl = this.verify(v, maxGapToAdd)
183
- if (adrl) {
184
- acc.push(adrl)
185
- }
186
- return acc
187
- }, [])
188
- return adrpInstructions
189
- }
190
-
191
- // adrp + add
192
- scanAdrlSlow(
193
- scanRange: { base: NativePointer, size: number},
194
- maxGapToAdd: number = 16,
195
- ): Adrl[] {
196
- const { base, size } = scanRange
197
-
198
- const targetPage = this.targetPage
199
- // adrp
200
- const op = ptr(0b1)
201
-
202
- const adrpPageMask = choiceMatchPattern(ptr(0x9fffffe0), 4)
203
-
204
- const adrpMatches: MemoryScanMatch[] = []
205
-
206
- help.memoryReadPageDo(base, size, (page: MemoryPage): boolean => {
207
- const { readable } = page
208
- const range = { base: page.base, size: page.size}
209
- if(!range) {
210
- return false
211
- }else if (!readable) {
212
- console.error(`[AdrlXref] scanAdrp base[${range.base} => ${range.base.add(range.size)}] is unreadable.`)
213
- return false
214
- }
215
-
216
- const pcPage = range.base
217
- const pageDelta = targetPage.sub(pcPage).shr(3*4).and(0x1FFFFF) // immhi:immlo = 21位
218
- const immlo = pageDelta.and(0b11)
219
- const immhi = pageDelta.shr(2)
220
- const anyRd = NULL
221
- const adrpSign = choiceMatchPattern(
222
- NULL.or(op.shl(31))
223
- .or(immlo.shl(29))
224
- .or(AdrlXref.ADRP_FIXED28_24_BITSET_MASK)
225
- .or(immhi.shl(5))
226
- .or(anyRd),
227
- 4,
228
- )
229
-
230
- const scanPattern = `${adrpSign} : ${adrpPageMask}`
231
- const scanResults = Memory.scanSync(range.base, range.size, scanPattern).filter(v => {
232
- return v.address.and(0x3).isNull()
233
- })
234
- adrpMatches.push(...scanResults)
235
- return false
236
- })
237
-
238
- const adrpInstructions = adrpMatches.reduce<Adrl[]>((acc, v) => {
239
- const adrl = this.verify(v.address, maxGapToAdd)
240
- if(adrl) {
241
- acc.push(adrl)
242
- }
243
- return acc
244
- }, [])
245
-
246
- return adrpInstructions
247
- }
248
-
249
-
250
- verify(p: NativePointer, maxGapToAdd: number = 16): Adrl | null {
251
- try {
252
- const maybeAdrl = Adrl.loadFromPointer(p)
253
- const adrpInsn = maybeAdrl.adrpInsn
254
- if (adrpInsn.mnemonic !== 'adrp') {
255
- return null
256
- }
257
-
258
- if (maybeAdrl.getTarget(false, maxGapToAdd)?.equals(this.target)) {
259
- return maybeAdrl
260
- }
261
- return null
262
- } catch (error) {
263
-
264
- }
265
- return null
266
- }
267
-
268
-
269
- scanAdr(): Adrl[] {
270
- // TODO:
271
- return []
272
- }
273
-
274
- }
275
-
276
-
277
- type JumpScanRes = {
278
- src: InstructionSequence
279
- insn: Arm64Instruction
280
- next: NativePointer
281
- }
282
-
283
-
284
-
285
- export class Adrl extends InstructionSequence {
286
- readonly adrpInsn: Arm64Instruction
287
- private addInsn?: Arm64Instruction
288
-
289
- constructor(adrp: Arm64Instruction, add?: Arm64Instruction) {
290
- super(adrp)
291
- this.adrpInsn = adrp
292
- this.addInsn = add
293
- }
294
-
295
- get instruction(): Arm64Instruction {
296
- return Instruction.parse(this.$handle) as Arm64Instruction
297
- }
298
-
299
- scanBL(base?: NativePointer, maxGap: number = 16): JumpScanRes | null {
300
- if(!base) {
301
- base = this.$handle
302
- }
303
-
304
- let inc = 0
305
- for (const insn of this) {
306
- switch (insn.mnemonic) {
307
- case 'bl':
308
- return {
309
- src: this,
310
- insn: insn,
311
- next: insn.next,
312
- }
313
- }
314
- inc++
315
- if(inc >= maxGap) return null
316
- }
317
- return null
318
- }
319
-
320
- getTarget(mustFoundAdd: boolean = false, maxGapToAdd: number = 16): NativePointer | null {
321
- const [op1, op2] = this.adrpInsn.operands
322
- const target = ptr(op2.value.toString())
323
- if (!this.addInsn) {
324
- let inc = 0
325
- verifyLoop: for (const insn of this) {
326
- switch (insn.mnemonic) {
327
- case 'add':
328
- if (insn.operands.length !== 3) {
329
- break
330
- }
331
- const [addOp1, addOp2, addOp3] = insn.operands
332
- if (addOp1.value !== op1.value) {
333
- break
334
- }
335
- if (addOp2.value !== addOp1.value) {
336
- console.error(`[Adrl] findAdd [${insn}] op2,来源于另一个寄存器,无法预估目标地址。`)
337
- break
338
- }
339
- this.addInsn = insn
340
- break verifyLoop
341
- }
342
- inc++
343
- if (inc >= maxGapToAdd) return mustFoundAdd ? null : target
344
- }
345
-
346
- }
347
- if(!this.addInsn) {
348
- return target
349
- }
350
- return target.add(this.addInsn.operands[2].value.toString())
351
-
352
- }
353
-
354
- }
355
-
356
-
357
- setGlobalProperties({
358
- AdrlXref,
359
-
360
- })
package/src/func.ts DELETED
@@ -1,32 +0,0 @@
1
-
2
- import { nativeFunctionOptions } from "./consts.js"
3
-
4
-
5
- export class FuncHelper {
6
- static list: any[] = []
7
-
8
- static $nativeWrapper<RetType extends NativeFunctionReturnType>(
9
- retType: RetType, argTypes: any[],
10
- ) {
11
- return function (f: NativePointer, wrapFunc: AnyFunction) {
12
- const impl = f.isNull() ? NULL : new NativeFunction(f, retType, argTypes, nativeFunctionOptions)
13
- const wrapper = function () {
14
- return wrapFunc(impl, ...Array.from(arguments))
15
- }
16
- const cb = new NativeCallback(wrapper, retType, argTypes)
17
- FuncHelper.list.push(cb)
18
- return cb
19
- }
20
- }
21
-
22
- // int __cxa_atexit(void (*f)(void *), void *objptr, void *dso);
23
- static atexit = this.$nativeWrapper('void', ['pointer'])
24
-
25
- // int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
26
- static pthread_start_routine = this.$nativeWrapper('pointer', ['pointer'])
27
-
28
- // void (*keylog_callback)(const SSL *ssl, const char *line)
29
- static SSL_CTX_keylog_callback = this.$nativeWrapper('void', ['pointer', 'pointer'])
30
-
31
-
32
- }