@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
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { Java } from '../bridges.js';
|
|
2
|
+
import { help, NativePointerObject } from '../helper.js';
|
|
3
|
+
export class StdVector extends NativePointerObject {
|
|
4
|
+
constructor(handle = NULL) {
|
|
5
|
+
let shouldDelete = handle.isNull();
|
|
6
|
+
if (handle.isNull()) {
|
|
7
|
+
handle = Memory.alloc(3 * Process.pointerSize);
|
|
8
|
+
}
|
|
9
|
+
super(handle);
|
|
10
|
+
this._start = this.$handle;
|
|
11
|
+
this._finish = this.$handle.add(Process.pointerSize);
|
|
12
|
+
this._end_of_storage = this.$handle.add(Process.pointerSize * 2);
|
|
13
|
+
if (shouldDelete) {
|
|
14
|
+
const weakRef = ptr(handle.toString());
|
|
15
|
+
Script.bindWeak(this.$handle, () => {
|
|
16
|
+
Java.api.$delete(weakRef);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
static cast(handle) {
|
|
21
|
+
return new StdVector(handle);
|
|
22
|
+
}
|
|
23
|
+
get start() {
|
|
24
|
+
return this._start.readPointer();
|
|
25
|
+
}
|
|
26
|
+
set start(val) {
|
|
27
|
+
this._start.writePointer(val);
|
|
28
|
+
}
|
|
29
|
+
get finish() {
|
|
30
|
+
return this._finish.readPointer();
|
|
31
|
+
}
|
|
32
|
+
set finish(val) {
|
|
33
|
+
this._finish.writePointer(val);
|
|
34
|
+
}
|
|
35
|
+
get end_of_storage() {
|
|
36
|
+
return this._end_of_storage.readPointer();
|
|
37
|
+
}
|
|
38
|
+
set end_of_storage(val) {
|
|
39
|
+
this._end_of_storage.writePointer(val);
|
|
40
|
+
}
|
|
41
|
+
get length() {
|
|
42
|
+
return this.finish.sub(this.start).toUInt32() / Process.pointerSize;
|
|
43
|
+
}
|
|
44
|
+
get capacity() {
|
|
45
|
+
return this.end_of_storage.sub(this.start).toUInt32() / Process.pointerSize;
|
|
46
|
+
}
|
|
47
|
+
[Symbol.iterator]() {
|
|
48
|
+
let nextPtr = this.start;
|
|
49
|
+
const that = this;
|
|
50
|
+
return {
|
|
51
|
+
next() {
|
|
52
|
+
let done = false;
|
|
53
|
+
let value = nextPtr;
|
|
54
|
+
if (value >= that.finish) {
|
|
55
|
+
done = true;
|
|
56
|
+
value = NULL;
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
nextPtr = nextPtr.add(Process.pointerSize);
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
value: value,
|
|
63
|
+
done: done,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
toArray() {
|
|
69
|
+
const list = [];
|
|
70
|
+
for (let v of this) {
|
|
71
|
+
list.push(v);
|
|
72
|
+
}
|
|
73
|
+
return list;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const STD_STRING_MEM_BYTE_SIZE = Process.pointerSize === 4 ? 12 : 24;
|
|
77
|
+
const STD_STRING_CAP_LONG_MODE_CAP_MASK = help.androidGetApiLevel() <= 16
|
|
78
|
+
? (Process.pointerSize === 4 ? '0x80000000' : '0x8000000000000000')
|
|
79
|
+
: '0x1';
|
|
80
|
+
export class StdString extends NativePointerObject {
|
|
81
|
+
constructor(handle = NULL) {
|
|
82
|
+
if (handle.isNull()) {
|
|
83
|
+
handle = Memory.alloc(STD_STRING_MEM_BYTE_SIZE);
|
|
84
|
+
}
|
|
85
|
+
super(handle);
|
|
86
|
+
this._cap = this.$handle;
|
|
87
|
+
this._size = this.$handle.add(Process.pointerSize);
|
|
88
|
+
this._data = this.$handle.add(Process.pointerSize * 2);
|
|
89
|
+
}
|
|
90
|
+
static cast(handle) {
|
|
91
|
+
return new StdString(handle);
|
|
92
|
+
}
|
|
93
|
+
get size() {
|
|
94
|
+
return this.longMode ? this._size.readU64().toNumber() : this.$handle.add(STD_STRING_MEM_BYTE_SIZE - 1).and(0x7F).toUInt32();
|
|
95
|
+
}
|
|
96
|
+
get data() {
|
|
97
|
+
return this._data.readByteArray(this.size);
|
|
98
|
+
}
|
|
99
|
+
get length() {
|
|
100
|
+
return this.size;
|
|
101
|
+
}
|
|
102
|
+
get capacity() {
|
|
103
|
+
return this.longMode ? this._cap.readU64().toNumber() : this.size;
|
|
104
|
+
}
|
|
105
|
+
get longMode() {
|
|
106
|
+
return !this._cap.readU64().and(STD_STRING_CAP_LONG_MODE_CAP_MASK).equals(0);
|
|
107
|
+
}
|
|
108
|
+
get stringPtr() {
|
|
109
|
+
if (this.longMode) {
|
|
110
|
+
return this._data.readPointer();
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
return this.$handle.readPointer();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
toString() {
|
|
117
|
+
return this.stringPtr.readUtf8String(this.size) || '';
|
|
118
|
+
}
|
|
119
|
+
toCString() {
|
|
120
|
+
return this.stringPtr.readCString(this.size) || '';
|
|
121
|
+
}
|
|
122
|
+
toUtf8String() {
|
|
123
|
+
return this.stringPtr.readUtf8String(this.size) || '';
|
|
124
|
+
}
|
|
125
|
+
toUtf16String() {
|
|
126
|
+
return this.stringPtr.readUtf16String(this.size) || '';
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { setGlobalProperties } from "../config.js";
|
|
2
|
+
export class TextEncoder {
|
|
3
|
+
constructor() {
|
|
4
|
+
this.encoding = 'utf-8';
|
|
5
|
+
}
|
|
6
|
+
encode(input) {
|
|
7
|
+
const strPtr = Memory.allocUtf8String(input);
|
|
8
|
+
const eosZeros = Memory.scanSync(strPtr, input.length * 4, "00");
|
|
9
|
+
const blen = eosZeros[0].address.sub(strPtr);
|
|
10
|
+
return new Uint8Array(strPtr.readByteArray(Number(blen)));
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export class TextDecoder {
|
|
14
|
+
constructor() {
|
|
15
|
+
this.encoding = 'utf-8';
|
|
16
|
+
}
|
|
17
|
+
decode(input) {
|
|
18
|
+
if (typeof (input['unwrap']) === 'function') {
|
|
19
|
+
return input.unwrap().readUtf8String() || '';
|
|
20
|
+
}
|
|
21
|
+
const tmp = Memory.alloc(input.byteLength);
|
|
22
|
+
tmp.writeByteArray(input);
|
|
23
|
+
return tmp.readUtf8String() || '';
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
setGlobalProperties({
|
|
27
|
+
TextDecoder,
|
|
28
|
+
TextEncoder,
|
|
29
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ArrayPointer } from "./array_pointer.js";
|
|
2
|
+
export declare function mustType<T>(val: T | null | undefined): T;
|
|
3
|
+
export declare function unwrapArgs(args: InvocationArguments, n: number): (any | NativePointer)[];
|
|
4
|
+
type BianaryBaseReader<T> = (base: NativePointer | ArrayPointer) => T;
|
|
5
|
+
declare function readByteArray(offset: number, length: number): (base: NativePointer | ArrayPointer) => ArrayBuffer;
|
|
6
|
+
declare function binaryReadU8(offset: number): BianaryBaseReader<number>;
|
|
7
|
+
declare function binaryReadU16(offset: number): BianaryBaseReader<number>;
|
|
8
|
+
declare function binaryReadU32(offset: number): BianaryBaseReader<number>;
|
|
9
|
+
declare function binaryReadS32(offset: number): BianaryBaseReader<number>;
|
|
10
|
+
declare function binaryReadU64(offset: number): BianaryBaseReader<number>;
|
|
11
|
+
declare function binaryReadS64(offset: number): BianaryBaseReader<number>;
|
|
12
|
+
declare function binaryReadPointer(offset: number): BianaryBaseReader<NativePointer>;
|
|
13
|
+
declare function binaryPointer(offset: number): BianaryBaseReader<NativePointer>;
|
|
14
|
+
declare function binaryReadPointerStruct(offset: number, structOfs: {
|
|
15
|
+
B64: {
|
|
16
|
+
[key: string]: BianaryBaseReader<any>;
|
|
17
|
+
};
|
|
18
|
+
B32?: {
|
|
19
|
+
[key: string]: BianaryBaseReader<any>;
|
|
20
|
+
};
|
|
21
|
+
}): (base: NativePointer | ArrayPointer) => {
|
|
22
|
+
[key: string]: any;
|
|
23
|
+
};
|
|
24
|
+
export { readByteArray, binaryReadU8, binaryReadU16, binaryReadU32, binaryReadS32, binaryReadU64, binaryReadS64, binaryReadPointer, binaryPointer, binaryReadPointerStruct, };
|
|
25
|
+
export declare function wrapArgTypes(typ: NativeFunctionArgumentType, length: number): NativeFunctionArgumentType[];
|
|
26
|
+
export declare function arrayBuffer2Hex(buffer: ArrayBuffer, options?: {
|
|
27
|
+
uppercase?: boolean;
|
|
28
|
+
}): string;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export function mustType(val) {
|
|
2
|
+
if (!val) {
|
|
3
|
+
throw new Error(`val不能为null`);
|
|
4
|
+
}
|
|
5
|
+
return val;
|
|
6
|
+
}
|
|
7
|
+
export function unwrapArgs(args, n) {
|
|
8
|
+
const list = [];
|
|
9
|
+
for (let i = 0; i < n; i++) {
|
|
10
|
+
list.push(args[i]);
|
|
11
|
+
}
|
|
12
|
+
return list;
|
|
13
|
+
}
|
|
14
|
+
function binaryNumberReader(offset, method) {
|
|
15
|
+
return function (base) {
|
|
16
|
+
return Number(base.add(offset)[method]());
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function binaryPointerReader(offset) {
|
|
20
|
+
return function (base) {
|
|
21
|
+
return base.add(offset).readPointer();
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function binaryPointerOffset(offset) {
|
|
25
|
+
return function (base) {
|
|
26
|
+
return ptr(base.add(offset).toString());
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function readByteArray(offset, length) { return (base) => mustType(base.add(offset).readByteArray(length)); }
|
|
30
|
+
function binaryReadU8(offset) { return binaryNumberReader(offset, 'readU8'); }
|
|
31
|
+
function binaryReadU16(offset) { return binaryNumberReader(offset, 'readU16'); }
|
|
32
|
+
function binaryReadU32(offset) { return binaryNumberReader(offset, 'readU32'); }
|
|
33
|
+
function binaryReadS32(offset) { return binaryNumberReader(offset, 'readS32'); }
|
|
34
|
+
function binaryReadU64(offset) { return binaryNumberReader(offset, 'readU64'); }
|
|
35
|
+
function binaryReadS64(offset) { return binaryNumberReader(offset, 'readS64'); }
|
|
36
|
+
function binaryReadPointer(offset) { return binaryPointerReader(offset); }
|
|
37
|
+
function binaryPointer(offset) { return binaryPointerOffset(offset); }
|
|
38
|
+
function binaryReadPointerStruct(offset, structOfs) {
|
|
39
|
+
return function (base) {
|
|
40
|
+
const structOf = Process.pointerSize === 4 ? structOfs['B32'] : structOfs['B64'];
|
|
41
|
+
const structBase = binaryPointerReader(offset)(base);
|
|
42
|
+
const obj = {};
|
|
43
|
+
for (let [k, offseter] of Object.entries(structOf)) {
|
|
44
|
+
Object.defineProperty(obj, k, {
|
|
45
|
+
value: offseter(structBase),
|
|
46
|
+
writable: false,
|
|
47
|
+
enumerable: true,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return obj;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export { readByteArray, binaryReadU8, binaryReadU16, binaryReadU32, binaryReadS32, binaryReadU64, binaryReadS64, binaryReadPointer, binaryPointer, binaryReadPointerStruct, };
|
|
54
|
+
export function wrapArgTypes(typ, length) {
|
|
55
|
+
return Array.from({ length: length }, () => typ);
|
|
56
|
+
}
|
|
57
|
+
export function arrayBuffer2Hex(buffer, options = {}) {
|
|
58
|
+
const { uppercase = false } = options;
|
|
59
|
+
const bytes = new Uint8Array(buffer);
|
|
60
|
+
return Array.from(bytes)
|
|
61
|
+
.map(b => {
|
|
62
|
+
const hex = b.toString(16).padStart(2, '0');
|
|
63
|
+
return uppercase ? hex.toUpperCase() : hex;
|
|
64
|
+
})
|
|
65
|
+
.join(' ');
|
|
66
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zsa233/frida-analykit-agent",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"description": "Frida agent runtime for frida-analykit",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"frida",
|
|
@@ -18,17 +18,30 @@
|
|
|
18
18
|
"directory": "packages/frida-analykit-agent"
|
|
19
19
|
},
|
|
20
20
|
"type": "module",
|
|
21
|
+
"main": "./dist/index.js",
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
21
23
|
"files": [
|
|
22
|
-
"
|
|
24
|
+
"dist/**/*",
|
|
23
25
|
"README.md",
|
|
24
26
|
"LICENSE"
|
|
25
27
|
],
|
|
26
28
|
"exports": {
|
|
27
|
-
".":
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
".": {
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"default": "./dist/index.js"
|
|
32
|
+
},
|
|
33
|
+
"./rpc": {
|
|
34
|
+
"types": "./dist/rpc.d.ts",
|
|
35
|
+
"default": "./dist/rpc.js"
|
|
36
|
+
},
|
|
37
|
+
"./*": {
|
|
38
|
+
"types": "./dist/*.d.ts",
|
|
39
|
+
"default": "./dist/*.js"
|
|
40
|
+
}
|
|
30
41
|
},
|
|
31
42
|
"scripts": {
|
|
43
|
+
"build": "tsc -p tsconfig.build.json",
|
|
44
|
+
"prepack": "npm run build",
|
|
32
45
|
"check": "tsc -p tsconfig.json --noEmit"
|
|
33
46
|
},
|
|
34
47
|
"dependencies": {
|
package/src/api/android.ts
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export type NP = NativePointer
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export interface EnvJvmti {
|
|
8
|
-
handle: NP
|
|
9
|
-
vm: NP,
|
|
10
|
-
vtable: NP
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
// frida-java-bridge/lib/android.js
|
|
16
|
-
export interface VMApi {
|
|
17
|
-
vm: NP
|
|
18
|
-
|
|
19
|
-
module: Module
|
|
20
|
-
|
|
21
|
-
flavor: 'art' | 'dalvik'
|
|
22
|
-
|
|
23
|
-
addLocalRefrence: null
|
|
24
|
-
|
|
25
|
-
find(name: string): NativePointer, // export => symbol => null
|
|
26
|
-
|
|
27
|
-
artRuntime: NativePointer
|
|
28
|
-
|
|
29
|
-
artClassLinker: {
|
|
30
|
-
address: NativePointer,
|
|
31
|
-
quickResolutionTrampoline: NativePointer,
|
|
32
|
-
quickImtConflictTrampoline: NativePointer,
|
|
33
|
-
quickGenericJniTrampoline: NativePointer,
|
|
34
|
-
quickToInterpreterBridgeTrampoline: NativePointer,
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
jvmti: EnvJvmti
|
|
38
|
-
|
|
39
|
-
$new(size: number): NativePointer
|
|
40
|
-
$delete(pointer: NativePointer): void
|
|
41
|
-
|
|
42
|
-
// jint JNI_GetCreatedJavaVMs(JavaVM** vmBuf, jsize bufLen, jsize* nVMs);
|
|
43
|
-
JNI_GetCreateJavaVMs(vmBuf: NP, bufLen: number, nVMs: NP): number
|
|
44
|
-
|
|
45
|
-
// jobject JavaVMExt::AddGlobalRef(Thread* self, ObjPtr<mirror::Object> obj)
|
|
46
|
-
['art::JavaVMExt::AddGlobalRef']: (vm: NP, self: NP, obj: NP) => NP
|
|
47
|
-
|
|
48
|
-
// void ReaderWriterMutex::ExclusiveLock(Thread* self)
|
|
49
|
-
['art::ReaderWriterMutex::ExclusiveLock']: (lock: NP, self: NP) => void
|
|
50
|
-
|
|
51
|
-
// IndirectRef IndirectReferenceTable::Add(IRTSegmentState previous_state, ObjPtr<mirror:: Object> obj, std::string * error_msg)
|
|
52
|
-
['art::IndirectReferenceTable::Add']: (table: NP, previous_state: NP, obj: number, error_msg: NP) => NP
|
|
53
|
-
|
|
54
|
-
// ObjPtr<mirror::Object> JavaVMExt::DecodeGlobal(IndirectRef ref)
|
|
55
|
-
// thread: 7 > Android >= 6
|
|
56
|
-
['art::JavaVMExt::DecodeGlobal']: (vm: NP, thread: NP, ref: NP) => NP
|
|
57
|
-
|
|
58
|
-
// ObjPtr<mirror::Object> Thread::DecodeJObject(jobject obj) const
|
|
59
|
-
['art::Thread::DecodeJObject']: (thread: NP, obj: NP) => NP
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
// TODO:
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
declare global {
|
|
69
|
-
namespace Java {
|
|
70
|
-
const api: VMApi,
|
|
71
|
-
Env: {
|
|
72
|
-
handle: NativePointer
|
|
73
|
-
vm: Java.VM & {
|
|
74
|
-
handle: NativePointer
|
|
75
|
-
}
|
|
76
|
-
throwIfExceptionPending(): Error
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
}
|
package/src/bridges.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import JavaBridge from "frida-java-bridge";
|
|
2
|
-
|
|
3
|
-
type BridgeGlobals = typeof globalThis & {
|
|
4
|
-
Java?: typeof JavaBridge;
|
|
5
|
-
ObjC?: unknown;
|
|
6
|
-
Swift?: unknown;
|
|
7
|
-
__FRIDA_ANALYKIT_CONFIG__?: Record<string, unknown>;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
const globals = globalThis as BridgeGlobals;
|
|
11
|
-
|
|
12
|
-
export const Java = globals.Java ?? JavaBridge;
|
|
13
|
-
export const ObjC = globals.ObjC;
|
|
14
|
-
export const Swift = globals.Swift;
|
|
15
|
-
|
|
16
|
-
if (!("Java" in globals)) {
|
|
17
|
-
globals.Java = Java;
|
|
18
|
-
}
|
package/src/cmodule/scan_adrp.c
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
#include <glib.h>
|
|
2
|
-
#include <gum/gummemory.h>
|
|
3
|
-
#include <gum/gumdefs.h>
|
|
4
|
-
|
|
5
|
-
#define PAGE_SIZE 0x1000
|
|
6
|
-
#define GET_ADDR_PAGE(x) ((uintptr_t)(x) & ~(PAGE_SIZE - 1))
|
|
7
|
-
#define ADRP_IMM_LEN_MASK 0x1fffff
|
|
8
|
-
#define ADRP_FIXED28_24_BITSET_MASK (0b10000 << 24)
|
|
9
|
-
#define ADRP_PAGE_INSTR_MASK 0x9fffffe0
|
|
10
|
-
|
|
11
|
-
typedef struct _MemoryScanRes MemoryScanRes;
|
|
12
|
-
typedef struct _ScanUserData ScanUserData;
|
|
13
|
-
|
|
14
|
-
static gboolean on_match_fuzzy_adrp(GumAddress address, gsize size, gpointer user_data);
|
|
15
|
-
|
|
16
|
-
struct _ScanUserData
|
|
17
|
-
{
|
|
18
|
-
gpointer target_address;
|
|
19
|
-
gint align_offset;
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
struct _MemoryScanRes
|
|
24
|
-
{
|
|
25
|
-
GArray *results;
|
|
26
|
-
ScanUserData *user_data;
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
void _dispose(const MemoryScanRes *res)
|
|
30
|
-
{
|
|
31
|
-
g_array_free(res->results, TRUE);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
static gboolean on_match_fuzzy_adrp(GumAddress address, gsize size, gpointer user_data)
|
|
35
|
-
{
|
|
36
|
-
MemoryScanRes *scan_res = (MemoryScanRes *)user_data;
|
|
37
|
-
const guintptr target_page = (guintptr)GET_ADDR_PAGE(scan_res->user_data->target_address);
|
|
38
|
-
const guintptr align_offset = (guintptr)scan_res->user_data->align_offset;
|
|
39
|
-
const guintptr addr_val = (guintptr)address - align_offset;
|
|
40
|
-
const gpointer pc_addr = (gpointer)addr_val;
|
|
41
|
-
|
|
42
|
-
// 4字节指令对齐
|
|
43
|
-
if ((addr_val & (sizeof(guint32) - 1)) != 0)
|
|
44
|
-
return TRUE;
|
|
45
|
-
|
|
46
|
-
// 按pc页差进行匹配
|
|
47
|
-
const guintptr pc_page = (guintptr)GET_ADDR_PAGE(address);
|
|
48
|
-
const guint32 page_delta = (guint32)((target_page - pc_page) >> 12) & ADRP_IMM_LEN_MASK;
|
|
49
|
-
const guint32 immlo = page_delta & 0b11;
|
|
50
|
-
const guint32 immhi = page_delta >> 2;
|
|
51
|
-
const guint32 op = 0x1;
|
|
52
|
-
const guint32 adrp_sign =
|
|
53
|
-
(op << 31) |
|
|
54
|
-
(immlo << 29) |
|
|
55
|
-
ADRP_FIXED28_24_BITSET_MASK |
|
|
56
|
-
(immhi << 5);
|
|
57
|
-
|
|
58
|
-
if (((*(guint32 *)pc_addr) & ADRP_PAGE_INSTR_MASK) != (adrp_sign & ADRP_PAGE_INSTR_MASK))
|
|
59
|
-
return TRUE;
|
|
60
|
-
|
|
61
|
-
g_array_append_val(scan_res->results, pc_addr);
|
|
62
|
-
return TRUE;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
gpointer scan(const GumAddress base_address,
|
|
66
|
-
const gsize size,
|
|
67
|
-
const gchar *pattern_str,
|
|
68
|
-
MemoryScanRes *const scan_res)
|
|
69
|
-
{
|
|
70
|
-
if (scan_res == NULL)
|
|
71
|
-
return NULL;
|
|
72
|
-
|
|
73
|
-
scan_res->results = g_array_new(FALSE, FALSE, sizeof(gpointer));
|
|
74
|
-
|
|
75
|
-
const GumMemoryRange range = {base_address, size};
|
|
76
|
-
const GumMatchPattern *pattern = gum_match_pattern_new_from_string(pattern_str);
|
|
77
|
-
|
|
78
|
-
gum_memory_scan(&range, pattern, on_match_fuzzy_adrp, scan_res);
|
|
79
|
-
|
|
80
|
-
return scan_res->results;
|
|
81
|
-
}
|
package/src/config.ts
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
type InjectedConfig = {
|
|
2
|
-
OnRPC?: boolean
|
|
3
|
-
OutputDir?: string
|
|
4
|
-
LogLevel?: number
|
|
5
|
-
LogCollapse?: boolean
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
const injectedConfig = ((globalThis as typeof globalThis & {
|
|
9
|
-
__FRIDA_ANALYKIT_CONFIG__?: InjectedConfig
|
|
10
|
-
}).__FRIDA_ANALYKIT_CONFIG__) || {}
|
|
11
|
-
|
|
12
|
-
export function setGlobalProperties(keyValues: { [key: string]: any }): void {
|
|
13
|
-
for (let [k, v] of Object.entries(keyValues)) {
|
|
14
|
-
if (k in globalThis) {
|
|
15
|
-
throw new Error(`global property[${k}] exists already`)
|
|
16
|
-
}
|
|
17
|
-
;(globalThis as typeof globalThis & { [key: string]: unknown })[k] = v
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
export const LogLevel = {
|
|
23
|
-
DEBUG: 0,
|
|
24
|
-
INFO: 1,
|
|
25
|
-
WARN: 2,
|
|
26
|
-
ERROR: 3,
|
|
27
|
-
_MUST_LOG: 9999999,
|
|
28
|
-
} as const
|
|
29
|
-
|
|
30
|
-
export type LogLevel = (typeof LogLevel)[keyof typeof LogLevel]
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
declare global {
|
|
35
|
-
const LogLevel: {
|
|
36
|
-
DEBUG: number
|
|
37
|
-
INFO: number
|
|
38
|
-
WARN: number
|
|
39
|
-
ERROR: number
|
|
40
|
-
_MUST_LOG: number
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export class Config {
|
|
45
|
-
static OnRPC: boolean = injectedConfig.OnRPC ?? false
|
|
46
|
-
static OutputDir?: string = injectedConfig.OutputDir
|
|
47
|
-
static LogLevel: number = injectedConfig.LogLevel ?? LogLevel.INFO
|
|
48
|
-
static LogCollapse: boolean = injectedConfig.LogCollapse ?? true
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
setGlobalProperties({
|
|
54
|
-
'Config': Config,
|
|
55
|
-
'LogLevel': LogLevel,
|
|
56
|
-
})
|
package/src/consts.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export const nativeFunctionOptions: NativeABI | NativeFunctionOptions = {
|
|
6
|
-
exceptions: 'propagate',
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
export enum SYM_INFO_BIND {
|
|
13
|
-
STB_LOCAL = 0x0,
|
|
14
|
-
STB_GLOBAL = 0x1,
|
|
15
|
-
STB_WEAK = 0x2,
|
|
16
|
-
STB_GNU_UNIQUE = 0x3,
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
export enum SYM_INFO_TYPE {
|
|
21
|
-
STT_NOTYPE = 0x0,
|
|
22
|
-
STT_OBJECT = 0x1,
|
|
23
|
-
STT_FUNC = 0x2,
|
|
24
|
-
STT_SECTION = 0x3,
|
|
25
|
-
STT_FILE = 0x4,
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export enum SYM_SHNDX {
|
|
29
|
-
SHN_UNDEF = 0,
|
|
30
|
-
SHN_ABS = 0xfff1,
|
|
31
|
-
}
|
package/src/elf/insn.ts
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { setGlobalProperties } from "../config.js"
|
|
2
|
-
import { NativePointerObject } from "../helper.js"
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export class InstructionSequence extends NativePointerObject {
|
|
7
|
-
protected readonly entryInsn: Arm64Instruction
|
|
8
|
-
protected readonly insns: Arm64Instruction[] = []
|
|
9
|
-
protected eoi?: Arm64Instruction
|
|
10
|
-
|
|
11
|
-
constructor(entry: Arm64Instruction) {
|
|
12
|
-
const handle = entry.address
|
|
13
|
-
super(handle)
|
|
14
|
-
this.entryInsn = entry
|
|
15
|
-
this.insns = [entry]
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
static loadFromPointer<T extends InstructionSequence>(
|
|
19
|
-
this: new (insn: Arm64Instruction) => T,
|
|
20
|
-
handle: NativePointer
|
|
21
|
-
): T {
|
|
22
|
-
const insn = Instruction.parse(handle) as Arm64Instruction
|
|
23
|
-
return new this(insn)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
*[Symbol.iterator]() {
|
|
27
|
-
let insns = this.insns
|
|
28
|
-
let insn: Arm64Instruction = this.entryInsn
|
|
29
|
-
let inc = 0
|
|
30
|
-
const that = this
|
|
31
|
-
|
|
32
|
-
let value: Arm64Instruction | undefined
|
|
33
|
-
|
|
34
|
-
while (true) {
|
|
35
|
-
value = insns[inc]
|
|
36
|
-
if (value === undefined && that.eoi === undefined) {
|
|
37
|
-
try {
|
|
38
|
-
insn = Instruction.parse(insns[inc - 1].next) as Arm64Instruction
|
|
39
|
-
insns.push(insn)
|
|
40
|
-
} catch (error) {
|
|
41
|
-
that.eoi = insn
|
|
42
|
-
break
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
inc++
|
|
46
|
-
yield insn
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
clearCache() {
|
|
52
|
-
this.insns.length = 0
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
setGlobalProperties({
|
|
60
|
-
InstructionSequence,
|
|
61
|
-
})
|