@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/lib/libc.ts
DELETED
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
import { mustType } from "../utils/utils.js"
|
|
2
|
-
import { nativeFunctionOptions } from "../consts.js"
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const PROP_VALUE_MAX = 92
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export class Libc {
|
|
9
|
-
constructor() {
|
|
10
|
-
return new Proxy(this, {
|
|
11
|
-
get(target: any, prop: string) {
|
|
12
|
-
if (prop in target) {
|
|
13
|
-
return target[prop];
|
|
14
|
-
}
|
|
15
|
-
if (prop[0] !== '$') {
|
|
16
|
-
return target['$' + prop]
|
|
17
|
-
} else {
|
|
18
|
-
return target[prop.substring(1)]
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
})
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
static readonly $libc = Process.findModuleByName('libc.so') || Module.load('libc.so')
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
$lazyLoadFunc<RetType extends NativeFunctionReturnType, ArgTypes extends NativeFunctionArgumentType[] | []>(
|
|
28
|
-
symName: string, retType: RetType, argTypes: ArgTypes,
|
|
29
|
-
): NativeFunction<GetNativeFunctionReturnValue<RetType>, ResolveVariadic<Extract<GetNativeFunctionArgumentValue<ArgTypes>, unknown[]>>> & { $handle: NativePointer | undefined } {
|
|
30
|
-
let func: any = null
|
|
31
|
-
const wrapper = ((...args: any) => {
|
|
32
|
-
if (func === null) {
|
|
33
|
-
func = this.$nativeFunc(symName, retType, argTypes)
|
|
34
|
-
}
|
|
35
|
-
const ret = func(...args)
|
|
36
|
-
return ret
|
|
37
|
-
}) as any
|
|
38
|
-
|
|
39
|
-
Object.defineProperty(wrapper, '$handle', {
|
|
40
|
-
get() {
|
|
41
|
-
if (func === null) {
|
|
42
|
-
func = this.$nativeFunc(symName, retType, argTypes)
|
|
43
|
-
}
|
|
44
|
-
return func.$handle
|
|
45
|
-
},
|
|
46
|
-
enumerable: true,
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
return wrapper
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
$nativeFunc<RetType extends NativeFunctionReturnType, ArgTypes extends NativeFunctionArgumentType[] | []>(
|
|
55
|
-
symName: string, retType: RetType, argTypes: ArgTypes,
|
|
56
|
-
): NativeFunction<GetNativeFunctionReturnValue<RetType>, ResolveVariadic<Extract<GetNativeFunctionArgumentValue<ArgTypes>, unknown[]>>> & { $handle: NativePointer | undefined } {
|
|
57
|
-
const handle = mustType(Libc.$libc.findExportByName(symName))
|
|
58
|
-
const fn: any = new NativeFunction(
|
|
59
|
-
handle,
|
|
60
|
-
retType, argTypes, nativeFunctionOptions,
|
|
61
|
-
)
|
|
62
|
-
fn.$handle = handle
|
|
63
|
-
return fn
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// ssize_t readlink(const char *pathname, char *buf, size_t bufsiz);
|
|
67
|
-
readonly $readlink = this.$lazyLoadFunc('readlink', 'int', ['pointer', 'pointer', 'size_t'])
|
|
68
|
-
readlink(pathname: string, bufsize: number = 256): string | null {
|
|
69
|
-
const cfdPath = Memory.allocUtf8String(pathname)
|
|
70
|
-
const resolvedPath = Memory.alloc(bufsize)
|
|
71
|
-
const result = this.$readlink(cfdPath, resolvedPath, bufsize)
|
|
72
|
-
let link: string | null = null
|
|
73
|
-
if (result !== -1) {
|
|
74
|
-
link = resolvedPath.readCString()
|
|
75
|
-
}
|
|
76
|
-
return link
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// DIR *opendir(const char *name);
|
|
80
|
-
readonly $opendir = this.$lazyLoadFunc('opendir', 'pointer', ['pointer'])
|
|
81
|
-
opendir(path: string) {
|
|
82
|
-
const cpath = Memory.allocUtf8String(path)
|
|
83
|
-
const dir = this.$opendir(cpath)
|
|
84
|
-
return dir
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// FILE *fopen(const char *pathname, const char *mode);
|
|
88
|
-
readonly $fopen = this.$lazyLoadFunc('fopen', 'pointer', ['pointer', 'pointer'])
|
|
89
|
-
fopen(pathname: string, mode: string): NativePointer {
|
|
90
|
-
return this.$fopen(Memory.allocUtf8String(pathname), Memory.allocUtf8String(mode))
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// int fclose(FILE *stream);
|
|
94
|
-
readonly fclose = this.$lazyLoadFunc('fclose', 'int', ['pointer'])
|
|
95
|
-
|
|
96
|
-
// int fputs(const char *str, FILE *stream);
|
|
97
|
-
readonly $fputs = this.$lazyLoadFunc('fputs', 'int', ['pointer', 'pointer'])
|
|
98
|
-
fputs(str: string, file: NativePointer) {
|
|
99
|
-
return this.$fputs(Memory.allocUtf8String(str), file)
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// int fflush(FILE *stream);
|
|
103
|
-
readonly fflush = this.$lazyLoadFunc('fflush', 'int', ['pointer'])
|
|
104
|
-
|
|
105
|
-
// struct dirent *readdir(DIR *dirp);
|
|
106
|
-
readonly readdir = this.$lazyLoadFunc('readdir', 'pointer', ['pointer'])
|
|
107
|
-
|
|
108
|
-
// int closedir(DIR *dirp);
|
|
109
|
-
readonly closedir = this.$lazyLoadFunc('closedir', 'int', ['pointer'])
|
|
110
|
-
|
|
111
|
-
// int fileno(FILE *stream);
|
|
112
|
-
readonly fileno = this.$lazyLoadFunc('fileno', 'int', ['pointer'])
|
|
113
|
-
|
|
114
|
-
// pthread_t pthread_self(void);
|
|
115
|
-
readonly pthread_self = this.$lazyLoadFunc('pthread_self', 'int64', [])
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
// pid_t getpid(void);
|
|
119
|
-
readonly getpid = this.$lazyLoadFunc('getpid', 'uint', [])
|
|
120
|
-
|
|
121
|
-
// uid_t getuid(void);
|
|
122
|
-
readonly getuid = this.$lazyLoadFunc('getuid', 'uint', [])
|
|
123
|
-
|
|
124
|
-
// pid_t gettid(void);
|
|
125
|
-
readonly gettid = this.$lazyLoadFunc('gettid', 'uint', [])
|
|
126
|
-
|
|
127
|
-
// int clock_gettime(clockid_t clk_id, struct timespec *tp);
|
|
128
|
-
readonly $clock_gettime = this.$lazyLoadFunc('clock_gettime', 'int', ['int', 'pointer'])
|
|
129
|
-
clock_gettime(clk_id: number): {tv_sec: number, tv_nsec: number } | null {
|
|
130
|
-
const ps = Process.pointerSize
|
|
131
|
-
const tv = Memory.alloc(ps * 2)
|
|
132
|
-
const ret = this.$clock_gettime(clk_id, tv)
|
|
133
|
-
if(ret != 0) {
|
|
134
|
-
return null
|
|
135
|
-
}
|
|
136
|
-
return {
|
|
137
|
-
tv_sec: Number(tv[ps === 8 ? 'readU64' : 'readU32']()),
|
|
138
|
-
tv_nsec: Number(tv.add(ps)[ps === 8 ? 'readU64' : 'readU32']()),
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// int __system_property_get(const char *name, char *value);
|
|
143
|
-
readonly $__system_property_get = this.$lazyLoadFunc('__system_property_get', 'int', ['pointer', 'pointer'])
|
|
144
|
-
__system_property_get(name: string): string {
|
|
145
|
-
const sdk_version_value = Memory.alloc(PROP_VALUE_MAX)
|
|
146
|
-
const ret = this.$__system_property_get(Memory.allocUtf8String(name), sdk_version_value)
|
|
147
|
-
if(ret < 0) {
|
|
148
|
-
console.error(`[__system_property_get] name[${name}] error[${ret}]`)
|
|
149
|
-
}
|
|
150
|
-
return sdk_version_value.readCString(ret) || ''
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// char *getcwd(char *buf, size_t size);
|
|
154
|
-
readonly $getcwd = this.$lazyLoadFunc('getcwd', 'pointer', ['pointer', 'size_t'])
|
|
155
|
-
getcwd(): string | null {
|
|
156
|
-
const buff_size = 256
|
|
157
|
-
const buff = Memory.alloc(buff_size)
|
|
158
|
-
return this.$getcwd(buff, buff_size).readCString()
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
}
|
package/src/lib/libssl.ts
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import { ElfModuleX, ElfFileFixer } from "../elf/module.js"
|
|
3
|
-
import { nativeFunctionOptions } from "../consts.js"
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export class Libssl {
|
|
7
|
-
static $modx?: ElfModuleX
|
|
8
|
-
|
|
9
|
-
static $getModule(): ElfModuleX {
|
|
10
|
-
if (!this.$modx) {
|
|
11
|
-
let isNewLoad = false
|
|
12
|
-
const libsslModule = Process.findModuleByName('libssl.so') || (isNewLoad = true, Module.load('libssl.so'))
|
|
13
|
-
if (isNewLoad) {
|
|
14
|
-
console.error(`[libssl.so]为新加载module.`)
|
|
15
|
-
}
|
|
16
|
-
this.$modx = new ElfModuleX(
|
|
17
|
-
libsslModule,
|
|
18
|
-
[new ElfFileFixer(libsslModule.path)],
|
|
19
|
-
{ symbolScanLimit: 50000 },
|
|
20
|
-
)
|
|
21
|
-
}
|
|
22
|
-
return this.$modx
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
static $nativeFunc<RetType extends NativeFunctionReturnType, ArgTypes extends NativeFunctionArgumentType[] | []>(
|
|
27
|
-
symName: string, retType: RetType, argTypes: ArgTypes,
|
|
28
|
-
): NativeFunction<GetNativeFunctionReturnValue<RetType>, ResolveVariadic<Extract<GetNativeFunctionArgumentValue<ArgTypes>, unknown[]>>> & { $handle: NativePointer | undefined } {
|
|
29
|
-
const sym = this.$getModule().findSymbol(symName)
|
|
30
|
-
if (!sym || !sym.implPtr) {
|
|
31
|
-
// throw error if call
|
|
32
|
-
const throwFunc = function () {
|
|
33
|
-
throw new Error(`[Libssl] symbol[${symName}] Not Found!`)
|
|
34
|
-
} as any
|
|
35
|
-
throwFunc.$handle = null
|
|
36
|
-
return throwFunc
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const handle = sym.implPtr
|
|
40
|
-
|
|
41
|
-
const fn: any = new NativeFunction(
|
|
42
|
-
handle,
|
|
43
|
-
retType, argTypes, nativeFunctionOptions,
|
|
44
|
-
)
|
|
45
|
-
fn.$handle = handle
|
|
46
|
-
return fn
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
static $lazyLoadFunc<RetType extends NativeFunctionReturnType, ArgTypes extends NativeFunctionArgumentType[] | []>(
|
|
50
|
-
symName: string, retType: RetType, argTypes: ArgTypes,
|
|
51
|
-
): NativeFunction<GetNativeFunctionReturnValue<RetType>, ResolveVariadic<Extract<GetNativeFunctionArgumentValue<ArgTypes>, unknown[]>>> & { $handle: NativePointer | undefined } {
|
|
52
|
-
let func: any = null
|
|
53
|
-
const getFunc = () => {
|
|
54
|
-
if (func === null) { func = this.$nativeFunc(symName, retType, argTypes) }
|
|
55
|
-
return func
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const wrapper = ((...args: any) => {
|
|
59
|
-
return getFunc()(...args)
|
|
60
|
-
}) as any
|
|
61
|
-
|
|
62
|
-
Object.defineProperty(wrapper, '$handle', {
|
|
63
|
-
get() { return getFunc().$handle },
|
|
64
|
-
})
|
|
65
|
-
return wrapper
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
// // int bssl::ssl_log_secret(const SSL *ssl, const char *label, const uint8_t *secret, size_t secret_len)
|
|
71
|
-
// static readonly ssl_log_secret = this.$lazyLoadFunc(
|
|
72
|
-
// '_ZN4bssl14ssl_log_secretEPK6ssl_stPKcPKhm', 'bool', ['pointer', 'pointer', 'pointer', 'size_t']
|
|
73
|
-
// )
|
|
74
|
-
|
|
75
|
-
// void SSL_CTX_set_keylog_callback(SSL_CTX *ctx, void(*cb)(const SSL *ssl, const char *line))
|
|
76
|
-
static readonly SSL_CTX_set_keylog_callback = this.$lazyLoadFunc(
|
|
77
|
-
'SSL_CTX_set_keylog_callback', 'void', ['pointer', 'pointer']
|
|
78
|
-
)
|
|
79
|
-
|
|
80
|
-
// void (*SSL_CTX_get_keylog_callback(const SSL_CTX *ctx))(const SSL *ssl, const char *line)
|
|
81
|
-
static readonly SSL_CTX_get_keylog_callback = this.$lazyLoadFunc(
|
|
82
|
-
'SSL_CTX_get_keylog_callback', 'pointer', ['pointer']
|
|
83
|
-
)
|
|
84
|
-
|
|
85
|
-
// int SSL_connect(SSL *ssl)
|
|
86
|
-
static readonly SSL_connect = this.$lazyLoadFunc(
|
|
87
|
-
'SSL_connect', 'int', ['pointer']
|
|
88
|
-
)
|
|
89
|
-
|
|
90
|
-
// SSL *SSL_new(SSL_CTX *ctx)
|
|
91
|
-
static readonly SSL_new = this.$lazyLoadFunc(
|
|
92
|
-
'SSL_new', 'pointer', ['pointer']
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
}
|
package/src/message.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export enum RPCMsgType {
|
|
6
|
-
BATCH = 'BATCH',
|
|
7
|
-
SCOPE_CALL = 'SCOPE_CALL',
|
|
8
|
-
SCOPE_EVAL = 'SCOPE_EVAL',
|
|
9
|
-
SCOPE_GET = 'SCOPE_GET',
|
|
10
|
-
ENUMERATE_OBJ_PROPS = 'ENUMERATE_OBJ_PROPS',
|
|
11
|
-
INIT_CONFIG = 'INIT_CONFIG',
|
|
12
|
-
SAVE_FILE = 'SAVE_FILE',
|
|
13
|
-
SSL_SECRET = 'SSL_SECRET',
|
|
14
|
-
PROGRESSING = 'PROGRESSING',
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
export enum batchSendSource {
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
export enum saveFileSource {
|
|
23
|
-
procMaps = 'procMaps',
|
|
24
|
-
textFile = 'textFile',
|
|
25
|
-
elfModule = 'elfModule',
|
|
26
|
-
}
|
package/src/net/ssl.ts
DELETED
|
@@ -1,360 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import { Config, setGlobalProperties } from "../config.js"
|
|
3
|
-
import { RPCMsgType } from "../message.js"
|
|
4
|
-
import { arrayBuffer2Hex, unwrapArgs } from "../utils/utils.js"
|
|
5
|
-
import { ssl_st_structOf, SSL3_RANDOM_SIZE } from "./struct.js"
|
|
6
|
-
import { help, NativePointerObject, ProgressNotify } from "../helper.js"
|
|
7
|
-
import { Libssl } from "../lib/libssl.js"
|
|
8
|
-
import { FuncHelper } from "../func.js"
|
|
9
|
-
import { ElfModuleX } from "../elf/module.js"
|
|
10
|
-
import { AdrlXref } from "../elf/xref.js"
|
|
11
|
-
import { TextEncoder } from "../utils/text_endec.js"
|
|
12
|
-
import { Subroutine } from "../elf/verifier.js"
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
type SSL3_STATE = {
|
|
16
|
-
read_sequence: ArrayBuffer
|
|
17
|
-
cwrite_sequence: ArrayBuffer
|
|
18
|
-
server_random: ArrayBuffer
|
|
19
|
-
client_random: ArrayBuffer
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
interface SSLField {
|
|
24
|
-
method: NativePointer
|
|
25
|
-
config: NativePointer
|
|
26
|
-
version: number
|
|
27
|
-
max_send_fragment: number
|
|
28
|
-
rbio: NativePointer
|
|
29
|
-
wbio: NativePointer
|
|
30
|
-
do_handshake: NativePointer
|
|
31
|
-
s3: SSL3_STATE
|
|
32
|
-
d1: NativePointer
|
|
33
|
-
msg_callback: NativePointer
|
|
34
|
-
msg_callback_arg: NativePointer
|
|
35
|
-
initial_timeout_duration_ms: number
|
|
36
|
-
session: NativePointer
|
|
37
|
-
info_callback: NativePointer
|
|
38
|
-
ctx: NativePointer
|
|
39
|
-
session_ctx: NativePointer
|
|
40
|
-
ex_data: NativePointer
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
interface SSL extends SSLField { }
|
|
45
|
-
|
|
46
|
-
const HEX_TABLE = '0123456789abcdef'
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
export type SSLSecretLog = {
|
|
51
|
-
label: string
|
|
52
|
-
client_random: string
|
|
53
|
-
secret: string
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
class SSL extends NativePointerObject {
|
|
57
|
-
constructor(handle: NativePointer) {
|
|
58
|
-
super(handle)
|
|
59
|
-
for (let [field, offseter] of Object.entries(Process.pointerSize === 8 ? ssl_st_structOf.B64 : {})) {
|
|
60
|
-
Object.defineProperty(this, field, {
|
|
61
|
-
value: offseter(this.$handle),
|
|
62
|
-
writable: false,
|
|
63
|
-
enumerable: true,
|
|
64
|
-
})
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
static cbb_hex(bytes: ArrayBuffer, in_len: number): string {
|
|
70
|
-
const bs = new Uint8Array(bytes)
|
|
71
|
-
const hex_list: string[] = []
|
|
72
|
-
for (let i = 0; i < in_len; i++) {
|
|
73
|
-
hex_list.push(HEX_TABLE[bs[i] >> 4] + HEX_TABLE[bs[i] & 0xf])
|
|
74
|
-
}
|
|
75
|
-
return hex_list.join('')
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
secretlog(label: string, secret: ArrayBuffer, secret_len: number): SSLSecretLog {
|
|
79
|
-
return {
|
|
80
|
-
label,
|
|
81
|
-
client_random: SSL.cbb_hex(this.s3.client_random, SSL3_RANDOM_SIZE),
|
|
82
|
-
secret: SSL.cbb_hex(secret, secret_len),
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
function sendSSLSecret(tag: string, data: { label: string, client_random: string, secret: string }){
|
|
91
|
-
if (Config.OnRPC) {
|
|
92
|
-
help.$send({
|
|
93
|
-
type: RPCMsgType.SSL_SECRET,
|
|
94
|
-
data: {
|
|
95
|
-
tag: tag,
|
|
96
|
-
...data
|
|
97
|
-
}
|
|
98
|
-
})
|
|
99
|
-
} else {
|
|
100
|
-
const file = help.getLogfile(tag, 'a')
|
|
101
|
-
file.writeLine(`${data.label} ${data.client_random} ${data.secret}`)
|
|
102
|
-
file.flush()
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
export class BoringSSL {
|
|
112
|
-
private mod: ElfModuleX | Module
|
|
113
|
-
constructor(mod: ElfModuleX | Module) {
|
|
114
|
-
this.mod = mod
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
static loadFromModule(mod: ElfModuleX | Module){
|
|
119
|
-
return new BoringSSL(mod)
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
scanKeylogFunc(
|
|
123
|
-
fullScan: boolean = false,
|
|
124
|
-
verifier: (p: NativePointer) => NativePointer | null = this.verifyKeylogFunc,
|
|
125
|
-
): NativePointer[] {
|
|
126
|
-
const prog = new ProgressNotify('BoringSSL::scanKeylogFunc')
|
|
127
|
-
|
|
128
|
-
const mod = this.mod
|
|
129
|
-
const tryGetSegment = (name: string) => {
|
|
130
|
-
if (mod instanceof ElfModuleX) {
|
|
131
|
-
return mod.getSegment(name)
|
|
132
|
-
}
|
|
133
|
-
return null
|
|
134
|
-
}
|
|
135
|
-
const targetString = 'CLIENT_RANDOM'
|
|
136
|
-
const enc = new TextEncoder()
|
|
137
|
-
const strBuff = enc.encode(targetString).buffer as ArrayBuffer
|
|
138
|
-
const scanPattern = arrayBuffer2Hex(strBuff) + " 00"
|
|
139
|
-
const targetScanRange = fullScan ? mod : (tryGetSegment('.rodata') || mod)
|
|
140
|
-
|
|
141
|
-
prog.notify({
|
|
142
|
-
intro: `开始扫描特征[${targetString}]`,
|
|
143
|
-
modx_name: mod.name,
|
|
144
|
-
modx_base: mod.base,
|
|
145
|
-
modx_size: mod.size,
|
|
146
|
-
|
|
147
|
-
scan_base: (targetScanRange ? targetScanRange : mod).base,
|
|
148
|
-
scan_size: (targetScanRange ? targetScanRange : mod).size,
|
|
149
|
-
scan_string: targetString,
|
|
150
|
-
scan_pattern: scanPattern,
|
|
151
|
-
|
|
152
|
-
next: 'help.scanMemory'
|
|
153
|
-
})
|
|
154
|
-
|
|
155
|
-
// 特征string 扫描
|
|
156
|
-
const stringTargets = help.scanMemory(
|
|
157
|
-
targetScanRange ? targetScanRange : mod,
|
|
158
|
-
scanPattern,
|
|
159
|
-
{ limit: 0x10000 }
|
|
160
|
-
)
|
|
161
|
-
|
|
162
|
-
prog.notify({
|
|
163
|
-
intro: `捕获目标数[${stringTargets.length}]`,
|
|
164
|
-
|
|
165
|
-
targets: stringTargets.map(v => v.address),
|
|
166
|
-
})
|
|
167
|
-
if (!stringTargets.length) {
|
|
168
|
-
return []
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
prog.notify({
|
|
172
|
-
targets: stringTargets.map(v => v.address),
|
|
173
|
-
})
|
|
174
|
-
|
|
175
|
-
const guessBLs = []
|
|
176
|
-
|
|
177
|
-
for (const target of stringTargets) {
|
|
178
|
-
const adrlScanRange = fullScan ? mod : (tryGetSegment('.text') || mod)
|
|
179
|
-
prog.notify({
|
|
180
|
-
target: target.address,
|
|
181
|
-
scan_base: adrlScanRange.base,
|
|
182
|
-
scan_size: adrlScanRange.size,
|
|
183
|
-
|
|
184
|
-
next: 'AdrlXref::scanAdrl'
|
|
185
|
-
})
|
|
186
|
-
|
|
187
|
-
// adrl 目标引用扫描
|
|
188
|
-
const xref = new AdrlXref(target.address)
|
|
189
|
-
const adrlResults = xref.scanAdrl(adrlScanRange)
|
|
190
|
-
|
|
191
|
-
prog.notify({
|
|
192
|
-
intro: `特征[${target.address.sub(mod.base)}]引用关联数[${adrlResults.length}]`,
|
|
193
|
-
|
|
194
|
-
results: adrlResults,
|
|
195
|
-
})
|
|
196
|
-
|
|
197
|
-
for(const adrl of adrlResults) {
|
|
198
|
-
const bls = []
|
|
199
|
-
// bl 函数调用(只考虑第一次bl
|
|
200
|
-
const bl = adrl.scanBL()
|
|
201
|
-
if(bl) {
|
|
202
|
-
guessBLs.push(bl)
|
|
203
|
-
bls.push(bl)
|
|
204
|
-
}
|
|
205
|
-
prog.notify({
|
|
206
|
-
adrl: adrl,
|
|
207
|
-
bls: bls,
|
|
208
|
-
})
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
const guessFuncs = []
|
|
213
|
-
for(const target of guessBLs) {
|
|
214
|
-
const funcPtr = ptr(target.insn.operands[0].value.toString())
|
|
215
|
-
guessFuncs.push(funcPtr)
|
|
216
|
-
prog.notify({
|
|
217
|
-
intro: `从[${target.src.$handle.sub(mod.base)}]猜测目标函数[${funcPtr.sub(mod.base)}]`,
|
|
218
|
-
|
|
219
|
-
bl: target,
|
|
220
|
-
func_ptr: funcPtr,
|
|
221
|
-
})
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
// 进一步验证目标函数
|
|
225
|
-
return guessFuncs.reduce<NativePointer[]>((acc, v) => {
|
|
226
|
-
const p = verifier(v)
|
|
227
|
-
if(p) {
|
|
228
|
-
acc.push(p)
|
|
229
|
-
}
|
|
230
|
-
return acc
|
|
231
|
-
}, [])
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
verifyKeylogFunc(p: NativePointer): NativePointer | null {
|
|
235
|
-
const subroutine = Subroutine.loadFromPointer(p)
|
|
236
|
-
// thunk/tail call
|
|
237
|
-
const verifyResult = subroutine.scoreThunk()
|
|
238
|
-
if (verifyResult.score > 50 && verifyResult.eoi) {
|
|
239
|
-
const bInstr = verifyResult.eoi
|
|
240
|
-
switch (bInstr.mnemonic) {
|
|
241
|
-
case 'b':
|
|
242
|
-
const target = bInstr.operands[0]
|
|
243
|
-
return ptr(target.value.toString())
|
|
244
|
-
case 'br':
|
|
245
|
-
// TODO:
|
|
246
|
-
break
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
return p
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
class SSLTools extends NativePointerObject {
|
|
258
|
-
private static _libssl_hook: boolean = false
|
|
259
|
-
|
|
260
|
-
static newConsumer(tag: string = 'sslkey.log'): SSLSecretCallbackConsumer {
|
|
261
|
-
return new SSLSecretCallbackConsumer(tag)
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
static attachLibsslKeylogFunc(tag: string = 'sslkey.log'){
|
|
265
|
-
if (this._libssl_hook) {
|
|
266
|
-
return true
|
|
267
|
-
}
|
|
268
|
-
const handle = Libssl.SSL_new.$handle
|
|
269
|
-
if (!handle || handle.isNull()) {
|
|
270
|
-
return false
|
|
271
|
-
}
|
|
272
|
-
this._libssl_hook = true
|
|
273
|
-
Interceptor.attach(handle,{
|
|
274
|
-
onEnter(args) {
|
|
275
|
-
const [ctx] = unwrapArgs(args, 1)
|
|
276
|
-
this.ssl_ctx = ctx
|
|
277
|
-
},
|
|
278
|
-
onLeave(retval){
|
|
279
|
-
const ctx = this.ssl_ctx
|
|
280
|
-
Libssl.SSL_CTX_set_keylog_callback(ctx, FuncHelper.SSL_CTX_keylog_callback(
|
|
281
|
-
Libssl.SSL_CTX_get_keylog_callback(ctx),
|
|
282
|
-
(impl: NativeFunction<NativePointer, Array<NativePointer>>, ssl: NativePointer, line: NativePointer) => {
|
|
283
|
-
const str = line.readCString()
|
|
284
|
-
if (str !== null) {
|
|
285
|
-
const sep_list = str.split(' ')
|
|
286
|
-
if(sep_list.length !== 3) {
|
|
287
|
-
printErr(`[attachLogSecret] error to parse secret_log[${str}]`)
|
|
288
|
-
}else{
|
|
289
|
-
const [label, client_random, secret] = sep_list
|
|
290
|
-
sendSSLSecret(tag, { label, client_random, secret })
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
if(!impl.isNull()) {
|
|
294
|
-
impl(ssl, line)
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
))
|
|
298
|
-
}
|
|
299
|
-
})
|
|
300
|
-
return true
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
static attachBoringsslKeylogFunc(options: { mod?: ElfModuleX | Module, libname?: string }){
|
|
304
|
-
let { mod, libname } = options
|
|
305
|
-
if(!mod && !libname) {
|
|
306
|
-
throw new Error(`[attachBoringssl] mod和libname必须要指定一个`)
|
|
307
|
-
}
|
|
308
|
-
const prog = new ProgressNotify('SSLTools::attachBoringsslKeylogFunc')
|
|
309
|
-
if(!mod) {
|
|
310
|
-
mod = Process.getModuleByName(libname!)
|
|
311
|
-
}
|
|
312
|
-
const bor = new BoringSSL(mod)
|
|
313
|
-
const guessList = bor.scanKeylogFunc()
|
|
314
|
-
if(guessList.length != 1) {
|
|
315
|
-
throw new Error(`[attachBoringssl] 扫到的目标不存在或多个[${guessList.length}], 不执行attach。`)
|
|
316
|
-
}
|
|
317
|
-
Interceptor.attach(guessList[0], SSLTools.newConsumer('sslkey.log').Handler())
|
|
318
|
-
prog.log(mod!.name, `ssl_log_secret: ${guessList[0].sub(mod!.base)}`)
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
export class SSLSecretCallbackConsumer {
|
|
326
|
-
private tag: string
|
|
327
|
-
|
|
328
|
-
constructor(tag: string) {
|
|
329
|
-
this.tag = tag
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
Handler(): ScriptInvocationListenerCallbacks {
|
|
333
|
-
const that = this
|
|
334
|
-
return {
|
|
335
|
-
onEnter(args: InvocationArguments): void {
|
|
336
|
-
const [ssl, label, secret, secret_len] = unwrapArgs(args, 4)
|
|
337
|
-
const handle = new SSL(ssl)
|
|
338
|
-
const len = secret_len.toUInt32()
|
|
339
|
-
const data = handle.secretlog(label.readCString(), secret.readByteArray(len), len)
|
|
340
|
-
sendSSLSecret(that.tag, data)
|
|
341
|
-
},
|
|
342
|
-
onLeave(retval: InvocationReturnValue): void {
|
|
343
|
-
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
export { SSLTools }
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
setGlobalProperties({
|
|
358
|
-
'SSLTools': SSLTools,
|
|
359
|
-
'BoringSSL': BoringSSL,
|
|
360
|
-
})
|