frida 0.1.0 → 0.1.1
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.
- checksums.yaml +4 -4
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +25 -0
- data/LICENSE.txt +21 -0
- data/README.md +64 -0
- data/Rakefile +20 -0
- data/exe/frida +3 -0
- data/ext/c_frida/Application.c +79 -0
- data/ext/c_frida/Bus.c +91 -0
- data/ext/c_frida/Child.c +134 -0
- data/ext/c_frida/Compiler.c +208 -0
- data/ext/c_frida/Crash.c +92 -0
- data/ext/c_frida/Device.c +955 -0
- data/ext/c_frida/DeviceManager.c +260 -0
- data/ext/c_frida/EndpointParameters.c +189 -0
- data/ext/c_frida/FileMonitor.c +67 -0
- data/ext/c_frida/GObject.c +138 -0
- data/ext/c_frida/IOStream.c +228 -0
- data/ext/c_frida/PortalMembership.c +43 -0
- data/ext/c_frida/PortalService.c +413 -0
- data/ext/c_frida/Process.c +67 -0
- data/ext/c_frida/Relay.c +121 -0
- data/ext/c_frida/Script.c +221 -0
- data/ext/c_frida/Session.c +626 -0
- data/ext/c_frida/Spawn.c +53 -0
- data/ext/c_frida/c_frida.c +68 -0
- data/ext/c_frida/extconf.rb +26 -25
- data/ext/c_frida/gutils.c +498 -0
- data/ext/c_frida/gvl_bridge.c +131 -0
- data/ext/c_frida/inc/Application.h +9 -0
- data/ext/c_frida/inc/Bus.h +15 -0
- data/ext/c_frida/inc/Child.h +9 -0
- data/ext/c_frida/inc/Compiler.h +21 -0
- data/ext/c_frida/inc/Crash.h +9 -0
- data/ext/c_frida/inc/Device.h +71 -0
- data/ext/c_frida/inc/DeviceManager.h +20 -0
- data/ext/c_frida/inc/EndpointParameters.h +15 -0
- data/ext/c_frida/inc/FileMonitor.h +9 -0
- data/ext/c_frida/inc/GObject.h +10 -0
- data/ext/c_frida/inc/IOStream.h +29 -0
- data/ext/c_frida/inc/PortalMembership.h +9 -0
- data/ext/c_frida/inc/PortalService.h +47 -0
- data/ext/c_frida/inc/Process.h +9 -0
- data/ext/c_frida/inc/Relay.h +9 -0
- data/ext/c_frida/inc/Script.h +21 -0
- data/ext/c_frida/inc/Session.h +40 -0
- data/ext/c_frida/inc/Spawn.h +9 -0
- data/ext/c_frida/inc/c_frida.h +129 -0
- data/ext/c_frida/inc/gutils.h +21 -0
- data/ext/c_frida/inc/gvl_bridge.h +42 -0
- data/frida.gemspec +39 -0
- data/lib/frida/version.rb +5 -0
- data/lib/frida.rb +8 -0
- metadata +55 -3
@@ -0,0 +1,626 @@
|
|
1
|
+
#include "Session.h"
|
2
|
+
|
3
|
+
VALUE Session_from_FridaSession(FridaSession *handle)
|
4
|
+
{
|
5
|
+
VALUE self;
|
6
|
+
|
7
|
+
if (!handle)
|
8
|
+
return (Qnil);
|
9
|
+
self = rb_class_new_instance(0, NULL, cSession);
|
10
|
+
GET_GOBJECT_DATA();
|
11
|
+
d->handle = handle;
|
12
|
+
d->destroy = frida_unref;
|
13
|
+
rb_ivar_set(self, rb_intern("pid"), UINT2NUM(frida_session_get_pid(d->handle)));
|
14
|
+
return (self);
|
15
|
+
}
|
16
|
+
|
17
|
+
static VALUE Session_inspect(VALUE self)
|
18
|
+
{
|
19
|
+
VALUE s;
|
20
|
+
|
21
|
+
s = rb_sprintf("#<Session: pid=%+"PRIsVALUE">", rb_funcall(self, rb_intern("pid"), 0, NULL));
|
22
|
+
return (s);
|
23
|
+
}
|
24
|
+
|
25
|
+
/*
|
26
|
+
call-seq:
|
27
|
+
#pid() -> Fixnum
|
28
|
+
*/
|
29
|
+
static VALUE Session_pid(VALUE self)
|
30
|
+
{
|
31
|
+
return (rb_ivar_get(self, rb_intern("pid")));
|
32
|
+
}
|
33
|
+
|
34
|
+
GVL_FREE_PROXY_FUNC(detach_sync, void *handle)
|
35
|
+
{
|
36
|
+
GError *gerr = NULL;
|
37
|
+
|
38
|
+
frida_session_detach_sync(handle, NULL, &gerr);
|
39
|
+
RETURN_GVL_FREE_RESULT(NULL);
|
40
|
+
}
|
41
|
+
|
42
|
+
/*
|
43
|
+
call-seq:
|
44
|
+
#detach() -> nil
|
45
|
+
*/
|
46
|
+
static VALUE Session_detach(VALUE self)
|
47
|
+
{
|
48
|
+
GET_GOBJECT_DATA();
|
49
|
+
REQUIRE_GOBJECT_HANDLE();
|
50
|
+
|
51
|
+
CALL_GVL_FREE_WITH_RET(void *dummy, detach_sync, d->handle);
|
52
|
+
goto done;
|
53
|
+
|
54
|
+
gerror:
|
55
|
+
raise_rerror(NULL, _gerr);
|
56
|
+
done:
|
57
|
+
return (Qnil);
|
58
|
+
}
|
59
|
+
|
60
|
+
GVL_FREE_PROXY_FUNC(resume_sync, void *handle)
|
61
|
+
{
|
62
|
+
GError *gerr = NULL;
|
63
|
+
|
64
|
+
frida_session_resume_sync(handle, NULL, &gerr);
|
65
|
+
RETURN_GVL_FREE_RESULT(NULL);
|
66
|
+
}
|
67
|
+
|
68
|
+
/*
|
69
|
+
call-seq:
|
70
|
+
#resume() -> nil
|
71
|
+
*/
|
72
|
+
static VALUE Session_resume(VALUE self)
|
73
|
+
{
|
74
|
+
GET_GOBJECT_DATA();
|
75
|
+
REQUIRE_GOBJECT_HANDLE();
|
76
|
+
|
77
|
+
CALL_GVL_FREE_WITH_RET(void *dummy, resume_sync, d->handle);
|
78
|
+
goto done;
|
79
|
+
|
80
|
+
gerror:
|
81
|
+
raise_rerror(NULL, _gerr);
|
82
|
+
done:
|
83
|
+
return (Qnil);
|
84
|
+
}
|
85
|
+
|
86
|
+
/*
|
87
|
+
call-seq:
|
88
|
+
#is_detached() -> [TrueClass, FalseClass]
|
89
|
+
*/
|
90
|
+
static VALUE Session_is_detached(VALUE self)
|
91
|
+
{
|
92
|
+
GET_GOBJECT_DATA();
|
93
|
+
REQUIRE_GOBJECT_HANDLE();
|
94
|
+
void *is_detached;
|
95
|
+
|
96
|
+
is_detached = rb_thread_call_without_gvl((void_fp)frida_session_is_detached, d->handle, NULL, NULL);
|
97
|
+
return (is_detached ? Qtrue : Qfalse);
|
98
|
+
}
|
99
|
+
|
100
|
+
GVL_FREE_PROXY_FUNC(enable_child_gating_sync, void *handle)
|
101
|
+
{
|
102
|
+
GError *gerr = NULL;
|
103
|
+
|
104
|
+
frida_session_enable_child_gating_sync(handle, NULL, &gerr);
|
105
|
+
RETURN_GVL_FREE_RESULT(NULL);
|
106
|
+
}
|
107
|
+
|
108
|
+
/*
|
109
|
+
call-seq:
|
110
|
+
#enable_child_gating() -> nil
|
111
|
+
*/
|
112
|
+
static VALUE Session_enable_child_gating(VALUE self)
|
113
|
+
{
|
114
|
+
GET_GOBJECT_DATA();
|
115
|
+
REQUIRE_GOBJECT_HANDLE();
|
116
|
+
|
117
|
+
CALL_GVL_FREE_WITH_RET(void *dummy, enable_child_gating_sync, d->handle);
|
118
|
+
goto done;
|
119
|
+
|
120
|
+
gerror:
|
121
|
+
raise_rerror(NULL, _gerr);
|
122
|
+
done:
|
123
|
+
return (Qnil);
|
124
|
+
}
|
125
|
+
|
126
|
+
GVL_FREE_PROXY_FUNC(disable_child_gating_sync, void *handle)
|
127
|
+
{
|
128
|
+
GError *gerr = NULL;
|
129
|
+
|
130
|
+
frida_session_disable_child_gating_sync(handle, NULL, &gerr);
|
131
|
+
RETURN_GVL_FREE_RESULT(NULL);
|
132
|
+
}
|
133
|
+
|
134
|
+
/*
|
135
|
+
call-seq:
|
136
|
+
#disable_child_gating() -> nil
|
137
|
+
*/
|
138
|
+
static VALUE Session_disable_child_gating(VALUE self)
|
139
|
+
{
|
140
|
+
GET_GOBJECT_DATA();
|
141
|
+
REQUIRE_GOBJECT_HANDLE();
|
142
|
+
|
143
|
+
CALL_GVL_FREE_WITH_RET(void *dummy, disable_child_gating_sync, d->handle);
|
144
|
+
goto done;
|
145
|
+
|
146
|
+
gerror:
|
147
|
+
raise_rerror(NULL, _gerr);
|
148
|
+
done:
|
149
|
+
return (Qnil);
|
150
|
+
}
|
151
|
+
|
152
|
+
GVL_FREE_PROXY_FUNC(create_script_sync, create_script_sync_proxy_args *args)
|
153
|
+
{
|
154
|
+
GError *gerr = NULL;
|
155
|
+
FridaScript *handle;
|
156
|
+
|
157
|
+
handle = frida_session_create_script_sync(args->handle, args->source, args->options, NULL, &gerr);
|
158
|
+
RETURN_GVL_FREE_RESULT(handle);
|
159
|
+
}
|
160
|
+
|
161
|
+
/*
|
162
|
+
call-seq:
|
163
|
+
#create_script(source, name:, snapshot:, runtime:) -> Script
|
164
|
+
*/
|
165
|
+
static VALUE Session_create_script(int argc, VALUE *argv, VALUE self)
|
166
|
+
{
|
167
|
+
GET_GOBJECT_DATA();
|
168
|
+
REQUIRE_GOBJECT_HANDLE();
|
169
|
+
VALUE source, kws;
|
170
|
+
|
171
|
+
rb_scan_args(argc, argv, "1:", &source, &kws);
|
172
|
+
if (!RB_TYPE_P(source, T_STRING)) {
|
173
|
+
raise_argerror("source must be a string.");
|
174
|
+
return (Qnil);
|
175
|
+
}
|
176
|
+
FridaScriptOptions *options = frida_script_options_new();
|
177
|
+
if (!NIL_P(kws)) {
|
178
|
+
VALUE name = rb_hash_aref(kws, ID2SYM(rb_intern("name")));
|
179
|
+
if (!NIL_P(name)) {
|
180
|
+
if (!RB_TYPE_P(name, T_STRING)) {
|
181
|
+
raise_argerror("name must be a string.");
|
182
|
+
return (Qnil);
|
183
|
+
}
|
184
|
+
frida_script_options_set_name(options, StringValueCStr(name));
|
185
|
+
}
|
186
|
+
VALUE snapshot = rb_hash_aref(kws, ID2SYM(rb_intern("snapshot")));
|
187
|
+
if (!NIL_P(snapshot)) {
|
188
|
+
if (!RB_TYPE_P(snapshot, T_STRING)) {
|
189
|
+
raise_argerror("snapshot must be a string.");
|
190
|
+
return (g_object_unref(options), Qnil);
|
191
|
+
}
|
192
|
+
GBytes *gsnapshot = g_bytes_new(RSTRING_PTR(snapshot), RSTRING_LEN(snapshot));
|
193
|
+
frida_script_options_set_snapshot(options, gsnapshot);
|
194
|
+
}
|
195
|
+
VALUE runtime = rb_hash_aref(kws, ID2SYM(rb_intern("runtime")));
|
196
|
+
if (!NIL_P(runtime)) {
|
197
|
+
if (!RB_TYPE_P(runtime, T_STRING)) {
|
198
|
+
raise_argerror("runtime must be a string.");
|
199
|
+
return (g_object_unref(options), Qnil);
|
200
|
+
}
|
201
|
+
FridaScriptRuntime gruntime;
|
202
|
+
if (!rbGObject_unmarshal_enum(StringValueCStr(runtime), FRIDA_TYPE_SCRIPT_RUNTIME, &gruntime)) {
|
203
|
+
raise_argerror("invalid runtime.");
|
204
|
+
return (g_object_unref(options), Qnil);
|
205
|
+
}
|
206
|
+
frida_script_options_set_runtime(options, gruntime);
|
207
|
+
}
|
208
|
+
}
|
209
|
+
create_script_sync_proxy_args args = {
|
210
|
+
.handle = d->handle,
|
211
|
+
.source = StringValueCStr(source),
|
212
|
+
.options = options
|
213
|
+
};
|
214
|
+
CALL_GVL_FREE_WITH_RET(FridaScript *script, create_script_sync, &args);
|
215
|
+
g_clear_object(&options);
|
216
|
+
return (Script_from_FridaScript(script));
|
217
|
+
|
218
|
+
gerror:
|
219
|
+
g_clear_object(&options);
|
220
|
+
raise_rerror(NULL, _gerr);
|
221
|
+
return (Qnil);
|
222
|
+
}
|
223
|
+
|
224
|
+
GVL_FREE_PROXY_FUNC(create_script_from_bytes_sync, create_script_from_bytes_sync_proxy_args *args)
|
225
|
+
{
|
226
|
+
GError *gerr = NULL;
|
227
|
+
FridaScript *handle;
|
228
|
+
|
229
|
+
handle = frida_session_create_script_from_bytes_sync(args->handle, args->bytes, args->options, NULL, &gerr);
|
230
|
+
RETURN_GVL_FREE_RESULT(handle);
|
231
|
+
}
|
232
|
+
|
233
|
+
/*
|
234
|
+
call-seq:
|
235
|
+
#create_script_from_bytes(data, name:, snapshot:, runtime:) -> Script
|
236
|
+
*/
|
237
|
+
static VALUE Session_create_script_from_bytes(int argc, VALUE *argv, VALUE self)
|
238
|
+
{
|
239
|
+
GET_GOBJECT_DATA();
|
240
|
+
REQUIRE_GOBJECT_HANDLE();
|
241
|
+
FridaScriptOptions *options;
|
242
|
+
GBytes *cdata;
|
243
|
+
VALUE data, kws;
|
244
|
+
|
245
|
+
rb_scan_args(argc, argv, "1:", &data, &kws);
|
246
|
+
if (!RB_TYPE_P(data, T_STRING)) {
|
247
|
+
raise_argerror("data must be a string.");
|
248
|
+
return (Qnil);
|
249
|
+
}
|
250
|
+
cdata = g_bytes_new(RSTRING_PTR(data), RSTRING_LEN(data));
|
251
|
+
options = frida_script_options_new();
|
252
|
+
if (!NIL_P(kws)) {
|
253
|
+
VALUE name = rb_hash_aref(kws, ID2SYM(rb_intern("name")));
|
254
|
+
if (!NIL_P(name)) {
|
255
|
+
if (!RB_TYPE_P(name, T_STRING)) {
|
256
|
+
raise_argerror("name must be a string.");
|
257
|
+
goto invalid_arg;
|
258
|
+
}
|
259
|
+
frida_script_options_set_name(options, StringValueCStr(name));
|
260
|
+
}
|
261
|
+
VALUE snapshot = rb_hash_aref(kws, ID2SYM(rb_intern("snapshot")));
|
262
|
+
if (!NIL_P(snapshot)) {
|
263
|
+
if (!RB_TYPE_P(snapshot, T_STRING)) {
|
264
|
+
raise_argerror("snapshot must be a string.");
|
265
|
+
goto invalid_arg;
|
266
|
+
}
|
267
|
+
GBytes *csnapshot = g_bytes_new(RSTRING_PTR(snapshot), RSTRING_LEN(snapshot));
|
268
|
+
frida_script_options_set_snapshot(options, csnapshot);
|
269
|
+
g_bytes_unref(csnapshot);
|
270
|
+
}
|
271
|
+
VALUE rruntime = rb_hash_aref(kws, ID2SYM(rb_intern("runtime")));
|
272
|
+
if (!NIL_P(rruntime)) {
|
273
|
+
if (!RB_TYPE_P(rruntime, T_STRING)) {
|
274
|
+
raise_argerror("runtime must be a string.");
|
275
|
+
goto invalid_arg;
|
276
|
+
}
|
277
|
+
FridaScriptRuntime runtime;
|
278
|
+
if (!rbGObject_unmarshal_enum(StringValueCStr(rruntime), FRIDA_TYPE_SCRIPT_RUNTIME, &runtime)) {
|
279
|
+
raise_argerror("runtime is invalid.");
|
280
|
+
goto invalid_arg;
|
281
|
+
}
|
282
|
+
frida_script_options_set_runtime(options, runtime);
|
283
|
+
}
|
284
|
+
}
|
285
|
+
create_script_from_bytes_sync_proxy_args args = {
|
286
|
+
.handle = d->handle,
|
287
|
+
.bytes = cdata,
|
288
|
+
.options = options
|
289
|
+
};
|
290
|
+
CALL_GVL_FREE_WITH_RET(FridaScript *script, create_script_from_bytes_sync, &args);
|
291
|
+
g_bytes_unref(cdata);
|
292
|
+
g_clear_object(&options);
|
293
|
+
return (Script_from_FridaScript(script));
|
294
|
+
|
295
|
+
gerror:
|
296
|
+
g_clear_object(&options);
|
297
|
+
raise_rerror(NULL, _gerr);
|
298
|
+
return (Qnil);
|
299
|
+
invalid_arg:
|
300
|
+
g_object_unref(options);
|
301
|
+
g_bytes_unref(cdata);
|
302
|
+
return (Qnil);
|
303
|
+
}
|
304
|
+
|
305
|
+
GVL_FREE_PROXY_FUNC(compile_script_sync, compile_script_sync_proxy_args *args)
|
306
|
+
{
|
307
|
+
GError *gerr = NULL;
|
308
|
+
GBytes *result_bytes;
|
309
|
+
|
310
|
+
result_bytes = frida_session_compile_script_sync(args->handle, args->source, args->options, NULL, &gerr);
|
311
|
+
RETURN_GVL_FREE_RESULT(result_bytes);
|
312
|
+
}
|
313
|
+
|
314
|
+
/*
|
315
|
+
call-seq:
|
316
|
+
#compile_script(source, name:, runtime:) -> String
|
317
|
+
*/
|
318
|
+
static VALUE Session_compile_script(int argc, VALUE *argv, VALUE self)
|
319
|
+
{
|
320
|
+
GET_GOBJECT_DATA();
|
321
|
+
REQUIRE_GOBJECT_HANDLE();
|
322
|
+
FridaScriptOptions *options;
|
323
|
+
VALUE source, kws;
|
324
|
+
|
325
|
+
rb_scan_args(argc, argv, "1:", &source, &kws);
|
326
|
+
if (!RB_TYPE_P(source, T_STRING)) {
|
327
|
+
raise_argerror("source must be a string.");
|
328
|
+
return (Qnil);
|
329
|
+
}
|
330
|
+
options = frida_script_options_new();
|
331
|
+
if (!NIL_P(kws)) {
|
332
|
+
VALUE name = rb_hash_aref(kws, ID2SYM(rb_intern("name")));
|
333
|
+
if (!NIL_P(name)) {
|
334
|
+
if (!RB_TYPE_P(name, T_STRING)) {
|
335
|
+
raise_argerror("name must be a string.");
|
336
|
+
goto invalid_arg;
|
337
|
+
}
|
338
|
+
frida_script_options_set_name(options, StringValueCStr(name));
|
339
|
+
}
|
340
|
+
VALUE rruntime = rb_hash_aref(kws, ID2SYM(rb_intern("runtime")));
|
341
|
+
if (!NIL_P(rruntime)) {
|
342
|
+
if (!RB_TYPE_P(rruntime, T_STRING)) {
|
343
|
+
raise_argerror("runtime must be a string.");
|
344
|
+
goto invalid_arg;
|
345
|
+
}
|
346
|
+
FridaScriptRuntime runtime;
|
347
|
+
if (!rbGObject_unmarshal_enum(StringValueCStr(rruntime), FRIDA_TYPE_SCRIPT_RUNTIME, &runtime)) {
|
348
|
+
raise_argerror("runtime is invalid.");
|
349
|
+
goto invalid_arg;
|
350
|
+
}
|
351
|
+
frida_script_options_set_runtime(options, runtime);
|
352
|
+
}
|
353
|
+
}
|
354
|
+
compile_script_sync_proxy_args args = {
|
355
|
+
.handle = d->handle,
|
356
|
+
.source = StringValueCStr(source),
|
357
|
+
.options = options
|
358
|
+
};
|
359
|
+
CALL_GVL_FREE_WITH_RET(GBytes *result_bytes, compile_script_sync, &args);
|
360
|
+
g_clear_object(&options);
|
361
|
+
VALUE rresult = rbGObject_marshal_bytes(result_bytes);
|
362
|
+
g_bytes_unref(result_bytes);
|
363
|
+
return (rresult);
|
364
|
+
|
365
|
+
gerror:
|
366
|
+
g_clear_object(&options);
|
367
|
+
raise_rerror(NULL, _gerr);
|
368
|
+
return (Qnil);
|
369
|
+
invalid_arg:
|
370
|
+
g_object_unref(options);
|
371
|
+
return (Qnil);
|
372
|
+
}
|
373
|
+
|
374
|
+
GVL_FREE_PROXY_FUNC(snapshot_script_sync, snapshot_script_sync_proxy_args *args)
|
375
|
+
{
|
376
|
+
GError *gerr = NULL;
|
377
|
+
GBytes *result_bytes;
|
378
|
+
|
379
|
+
result_bytes = frida_session_snapshot_script_sync(args->handle, args->embed_script, args->options, NULL, &gerr);
|
380
|
+
RETURN_GVL_FREE_RESULT(result_bytes);
|
381
|
+
}
|
382
|
+
|
383
|
+
/*
|
384
|
+
call-seq:
|
385
|
+
#snapshot_script(embed_script, warmup_script:, runtime:) -> String
|
386
|
+
*/
|
387
|
+
static VALUE Session_snapshot_script(int argc, VALUE *argv, VALUE self)
|
388
|
+
{
|
389
|
+
GET_GOBJECT_DATA();
|
390
|
+
REQUIRE_GOBJECT_HANDLE();
|
391
|
+
FridaSnapshotOptions *options;
|
392
|
+
VALUE embed_script, kws;
|
393
|
+
|
394
|
+
rb_scan_args(argc, argv, "1:", &embed_script, &kws);
|
395
|
+
if (!RB_TYPE_P(embed_script, T_STRING)) {
|
396
|
+
raise_argerror("embed_script must be a string.");
|
397
|
+
return (Qnil);
|
398
|
+
}
|
399
|
+
options = frida_snapshot_options_new();
|
400
|
+
if (!NIL_P(kws)) {
|
401
|
+
VALUE warmup_script = rb_hash_aref(kws, ID2SYM(rb_intern("warmup_script")));
|
402
|
+
if (!NIL_P(warmup_script)) {
|
403
|
+
if (!RB_TYPE_P(warmup_script, T_STRING)) {
|
404
|
+
raise_argerror("warmup_script must be a string.");
|
405
|
+
goto invalid_arg;
|
406
|
+
}
|
407
|
+
frida_snapshot_options_set_warmup_script(options, StringValueCStr(warmup_script));
|
408
|
+
}
|
409
|
+
VALUE rruntime = rb_hash_aref(kws, ID2SYM(rb_intern("runtime")));
|
410
|
+
if (!NIL_P(rruntime)) {
|
411
|
+
if (!RB_TYPE_P(rruntime, T_STRING)) {
|
412
|
+
raise_argerror("runtime must be a string.");
|
413
|
+
goto invalid_arg;
|
414
|
+
}
|
415
|
+
FridaScriptRuntime runtime;
|
416
|
+
if (!rbGObject_unmarshal_enum(StringValueCStr(rruntime), FRIDA_TYPE_SCRIPT_RUNTIME, &runtime)) {
|
417
|
+
raise_argerror("runtime is invalid.");
|
418
|
+
goto invalid_arg;
|
419
|
+
}
|
420
|
+
frida_snapshot_options_set_runtime(options, runtime);
|
421
|
+
}
|
422
|
+
}
|
423
|
+
snapshot_script_sync_proxy_args args = {
|
424
|
+
.handle = d->handle,
|
425
|
+
.embed_script = StringValueCStr(embed_script),
|
426
|
+
.options = options
|
427
|
+
};
|
428
|
+
CALL_GVL_FREE_WITH_RET(GBytes *result_bytes, snapshot_script_sync, &args);
|
429
|
+
g_clear_object(&options);
|
430
|
+
VALUE rresult = rbGObject_marshal_bytes(result_bytes);
|
431
|
+
g_bytes_unref(result_bytes);
|
432
|
+
return (rresult);
|
433
|
+
|
434
|
+
gerror:
|
435
|
+
g_clear_object(&options);
|
436
|
+
raise_rerror(NULL, _gerr);
|
437
|
+
return (Qnil);
|
438
|
+
invalid_arg:
|
439
|
+
g_object_unref(options);
|
440
|
+
return (Qnil);
|
441
|
+
}
|
442
|
+
|
443
|
+
static int array_all_instance_of(VALUE arr, VALUE rtype)
|
444
|
+
{
|
445
|
+
long len = RARRAY_LEN(arr);
|
446
|
+
|
447
|
+
for (uint i = 0; i < len; i++) {
|
448
|
+
if (!rb_obj_is_instance_of(RARRAY_AREF(arr, i), rtype))
|
449
|
+
return (0);
|
450
|
+
}
|
451
|
+
return (1);
|
452
|
+
}
|
453
|
+
|
454
|
+
GVL_FREE_PROXY_FUNC(setup_peer_connection_sync, setup_peer_connection_sync_proxy_args *args)
|
455
|
+
{
|
456
|
+
GError *gerr = NULL;
|
457
|
+
|
458
|
+
frida_session_setup_peer_connection_sync(args->handle, args->options, NULL, &gerr);
|
459
|
+
RETURN_GVL_FREE_RESULT(NULL);
|
460
|
+
}
|
461
|
+
|
462
|
+
/*
|
463
|
+
call-seq:
|
464
|
+
#setup_peer_connection(stun_server:, relays:) -> nil
|
465
|
+
*/
|
466
|
+
static VALUE Session_setup_peer_connection(int argc, VALUE *argv, VALUE self)
|
467
|
+
{
|
468
|
+
GET_GOBJECT_DATA();
|
469
|
+
REQUIRE_GOBJECT_HANDLE();
|
470
|
+
FridaPeerOptions *options;
|
471
|
+
VALUE kws, stun_server, relays;
|
472
|
+
|
473
|
+
options = frida_peer_options_new();
|
474
|
+
rb_scan_args(argc, argv, ":", &kws);
|
475
|
+
if (!NIL_P(kws)) {
|
476
|
+
stun_server = rb_hash_aref(kws, ID2SYM(rb_intern("stun_server")));
|
477
|
+
if (!NIL_P(stun_server)) {
|
478
|
+
if (!RB_TYPE_P(stun_server, T_STRING)) {
|
479
|
+
raise_argerror("stun_server must be a string.");
|
480
|
+
goto invalid_arg;
|
481
|
+
}
|
482
|
+
frida_peer_options_set_stun_server(options, StringValueCStr(stun_server));
|
483
|
+
} else {
|
484
|
+
raise_argerror("expected stun_server.");
|
485
|
+
goto invalid_arg;
|
486
|
+
}
|
487
|
+
relays = rb_hash_aref(kws, ID2SYM(rb_intern("relays")));
|
488
|
+
if (!NIL_P(relays)) {
|
489
|
+
if (!RB_TYPE_P(relays, T_ARRAY) || !array_all_instance_of(relays, cRelay)) {
|
490
|
+
raise_argerror("relays must be an array of Relay.");
|
491
|
+
goto invalid_arg;
|
492
|
+
}
|
493
|
+
GObject_d *relay_data;
|
494
|
+
uint relays_count = RARRAY_LEN(relays);
|
495
|
+
for (uint i = 0; i < relays_count; i++) {
|
496
|
+
TypedData_Get_Struct(RARRAY_AREF(relays, i), GObject_d, &GObject_dt, relay_data);
|
497
|
+
if (!relay_data->handle) {
|
498
|
+
raise_argerror("provided an invalid Relay object.");
|
499
|
+
goto invalid_arg;
|
500
|
+
}
|
501
|
+
frida_peer_options_add_relay(options, relay_data->handle);
|
502
|
+
}
|
503
|
+
} else {
|
504
|
+
raise_argerror("expected relays array.");
|
505
|
+
goto invalid_arg;
|
506
|
+
}
|
507
|
+
} else {
|
508
|
+
raise_argerror("expected stun_server and relays.");
|
509
|
+
goto invalid_arg;
|
510
|
+
}
|
511
|
+
setup_peer_connection_sync_proxy_args args = {
|
512
|
+
.handle = d->handle,
|
513
|
+
.options = options
|
514
|
+
};
|
515
|
+
CALL_GVL_FREE_WITH_RET(void *dummy, setup_peer_connection_sync, &args);
|
516
|
+
g_clear_object(&options);
|
517
|
+
return (Qnil);
|
518
|
+
|
519
|
+
gerror:
|
520
|
+
g_clear_object(&options);
|
521
|
+
raise_rerror(NULL, _gerr);
|
522
|
+
return (Qnil);
|
523
|
+
invalid_arg:
|
524
|
+
g_object_unref(options);
|
525
|
+
return (Qnil);
|
526
|
+
}
|
527
|
+
|
528
|
+
GVL_FREE_PROXY_FUNC(join_portal_sync, join_portal_sync_proxy_args *args)
|
529
|
+
{
|
530
|
+
GError *gerr = NULL;
|
531
|
+
|
532
|
+
FridaPortalMembership *handle = frida_session_join_portal_sync(args->handle, args->address, args->options, NULL, &gerr);
|
533
|
+
RETURN_GVL_FREE_RESULT(handle);
|
534
|
+
}
|
535
|
+
|
536
|
+
/*
|
537
|
+
call-seq:
|
538
|
+
#join_portal(address, certificate:, token:, acl:) -> PortalMembership
|
539
|
+
*/
|
540
|
+
static VALUE Session_join_portal(int argc, VALUE *argv, VALUE self)
|
541
|
+
{
|
542
|
+
GET_GOBJECT_DATA();
|
543
|
+
REQUIRE_GOBJECT_HANDLE();
|
544
|
+
FridaPortalOptions *options;
|
545
|
+
VALUE kws, address, certificate, token, acl;
|
546
|
+
|
547
|
+
rb_scan_args(argc, argv, "1:", &address, &kws);
|
548
|
+
if (!RB_TYPE_P(address, T_STRING)) {
|
549
|
+
raise_argerror("address must be a string.");
|
550
|
+
return (Qnil);
|
551
|
+
}
|
552
|
+
options = frida_portal_options_new();
|
553
|
+
if (!NIL_P(kws)) {
|
554
|
+
certificate = rb_hash_aref(kws, ID2SYM(rb_intern("certificate")));
|
555
|
+
if (!NIL_P(certificate)) {
|
556
|
+
if (!RB_TYPE_P(certificate, T_STRING)) {
|
557
|
+
raise_argerror("certificate must be a string.");
|
558
|
+
goto invalid_arg;
|
559
|
+
}
|
560
|
+
GTlsCertificate *gcertificate;
|
561
|
+
if (!rbGObject_unmarshal_certificate(StringValueCStr(certificate), &gcertificate)) {
|
562
|
+
raise_argerror("invalid certificate.");
|
563
|
+
goto invalid_arg;
|
564
|
+
}
|
565
|
+
frida_portal_options_set_certificate(options, gcertificate);
|
566
|
+
g_object_unref(gcertificate);
|
567
|
+
}
|
568
|
+
token = rb_hash_aref(kws, ID2SYM(rb_intern("token")));
|
569
|
+
if (!NIL_P(token)) {
|
570
|
+
if (!RB_TYPE_P(token, T_STRING)) {
|
571
|
+
raise_argerror("token must be a string.");
|
572
|
+
goto invalid_arg;
|
573
|
+
}
|
574
|
+
frida_portal_options_set_token(options, StringValueCStr(token));
|
575
|
+
}
|
576
|
+
acl = rb_hash_aref(kws, ID2SYM(rb_intern("acl")));
|
577
|
+
if (!NIL_P(acl)) {
|
578
|
+
if (!RB_TYPE_P(acl, T_ARRAY) || !array_all_type(acl, T_STRING)) {
|
579
|
+
raise_argerror("acl must be an array of strings.");
|
580
|
+
goto invalid_arg;
|
581
|
+
}
|
582
|
+
gchar **c_acl;
|
583
|
+
gint acl_count;
|
584
|
+
rbGObject_unmarshal_strv(acl, &c_acl, &acl_count);
|
585
|
+
frida_portal_options_set_acl(options, c_acl, acl_count);
|
586
|
+
g_strfreev(c_acl);
|
587
|
+
}
|
588
|
+
}
|
589
|
+
join_portal_sync_proxy_args args = {
|
590
|
+
.handle = d->handle,
|
591
|
+
.address = StringValueCStr(address),
|
592
|
+
.options = options
|
593
|
+
};
|
594
|
+
CALL_GVL_FREE_WITH_RET(FridaPortalMembership *handle, join_portal_sync, &args);
|
595
|
+
g_object_unref(options);
|
596
|
+
return (PortalMembership_from_FridaPortalMembership(handle));
|
597
|
+
|
598
|
+
gerror:
|
599
|
+
g_clear_object(&options);
|
600
|
+
raise_rerror(NULL, _gerr);
|
601
|
+
return (Qnil);
|
602
|
+
invalid_arg:
|
603
|
+
g_object_unref(options);
|
604
|
+
return (Qnil);
|
605
|
+
}
|
606
|
+
|
607
|
+
void define_Session()
|
608
|
+
{
|
609
|
+
cSession = rb_define_class_under(mCFrida, "Session", cGObject);
|
610
|
+
|
611
|
+
rb_define_method(cSession, "inspect", Session_inspect, 0);
|
612
|
+
rb_define_alias(cSession, "to_s", "inspect");
|
613
|
+
|
614
|
+
rb_define_method(cSession, "pid", Session_pid, 0);
|
615
|
+
rb_define_method(cSession, "is_detached", Session_is_detached, 0);
|
616
|
+
rb_define_method(cSession, "detach", Session_detach, 0);
|
617
|
+
rb_define_method(cSession, "resume", Session_resume, 0);
|
618
|
+
rb_define_method(cSession, "enable_child_gating", Session_enable_child_gating, 0);
|
619
|
+
rb_define_method(cSession, "disable_child_gating", Session_disable_child_gating, 0);
|
620
|
+
rb_define_method(cSession, "create_script", Session_create_script, -1);
|
621
|
+
rb_define_method(cSession, "create_script_from_bytes", Session_create_script_from_bytes, -1);
|
622
|
+
rb_define_method(cSession, "compile_script", Session_compile_script, -1);
|
623
|
+
rb_define_method(cSession, "snapshot_script", Session_snapshot_script, -1);
|
624
|
+
rb_define_method(cSession, "setup_peer_connection", Session_setup_peer_connection, -1);
|
625
|
+
rb_define_method(cSession, "join_portal", Session_join_portal, -1);
|
626
|
+
}
|
data/ext/c_frida/Spawn.c
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
#include "Spawn.h"
|
2
|
+
|
3
|
+
VALUE Spawn_from_FridaSpawn(FridaSpawn *handle)
|
4
|
+
{
|
5
|
+
VALUE self;
|
6
|
+
|
7
|
+
if (!handle)
|
8
|
+
return (Qnil);
|
9
|
+
self = rb_class_new_instance(0, NULL, cSpawn);
|
10
|
+
GET_GOBJECT_DATA();
|
11
|
+
d->handle = handle;
|
12
|
+
d->destroy = g_object_unref;
|
13
|
+
rb_ivar_set(self, rb_intern("pid"), UINT2NUM(frida_spawn_get_pid(d->handle)));
|
14
|
+
rb_ivar_set(self, rb_intern("identifier"), rbGObject_marshal_string(frida_spawn_get_identifier(d->handle)));
|
15
|
+
return (self);
|
16
|
+
}
|
17
|
+
|
18
|
+
static VALUE Spawn_inspect(VALUE self)
|
19
|
+
{
|
20
|
+
VALUE s;
|
21
|
+
|
22
|
+
s = rb_sprintf("#<Spawn: pid=%+"PRIsVALUE", identifier=%+"PRIsVALUE">", \
|
23
|
+
rb_funcall(self, rb_intern("pid"), 0, NULL), rb_funcall(self, rb_intern("identifier"), 0, NULL));
|
24
|
+
return (s);
|
25
|
+
}
|
26
|
+
|
27
|
+
/*
|
28
|
+
call-seq:
|
29
|
+
#pid() -> Fixnum
|
30
|
+
*/
|
31
|
+
static VALUE Spawn_pid(VALUE self)
|
32
|
+
{
|
33
|
+
return (rb_ivar_get(self, rb_intern("pid")));
|
34
|
+
}
|
35
|
+
|
36
|
+
/*
|
37
|
+
call-seq:
|
38
|
+
#identifier() -> String
|
39
|
+
*/
|
40
|
+
static VALUE Spawn_identifier(VALUE self)
|
41
|
+
{
|
42
|
+
return (rb_ivar_get(self, rb_intern("identifier")));
|
43
|
+
}
|
44
|
+
|
45
|
+
void define_Spawn()
|
46
|
+
{
|
47
|
+
cSpawn = rb_define_class_under(mCFrida, "Spawn", cGObject);
|
48
|
+
|
49
|
+
rb_define_method(cSpawn, "inspect", Spawn_inspect, 0);
|
50
|
+
rb_define_alias(cSpawn, "to_s", "inspect");
|
51
|
+
rb_define_method(cSpawn, "pid", Spawn_pid, 0);
|
52
|
+
rb_define_method(cSpawn, "identifier", Spawn_identifier, 0);
|
53
|
+
}
|