frida 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/CODE_OF_CONDUCT.md +84 -0
  3. data/Gemfile +12 -0
  4. data/Gemfile.lock +25 -0
  5. data/LICENSE.txt +21 -0
  6. data/README.md +64 -0
  7. data/Rakefile +20 -0
  8. data/exe/frida +3 -0
  9. data/ext/c_frida/Application.c +79 -0
  10. data/ext/c_frida/Bus.c +91 -0
  11. data/ext/c_frida/Child.c +134 -0
  12. data/ext/c_frida/Compiler.c +208 -0
  13. data/ext/c_frida/Crash.c +92 -0
  14. data/ext/c_frida/Device.c +955 -0
  15. data/ext/c_frida/DeviceManager.c +260 -0
  16. data/ext/c_frida/EndpointParameters.c +189 -0
  17. data/ext/c_frida/FileMonitor.c +67 -0
  18. data/ext/c_frida/GObject.c +138 -0
  19. data/ext/c_frida/IOStream.c +228 -0
  20. data/ext/c_frida/PortalMembership.c +43 -0
  21. data/ext/c_frida/PortalService.c +413 -0
  22. data/ext/c_frida/Process.c +67 -0
  23. data/ext/c_frida/Relay.c +121 -0
  24. data/ext/c_frida/Script.c +221 -0
  25. data/ext/c_frida/Session.c +626 -0
  26. data/ext/c_frida/Spawn.c +53 -0
  27. data/ext/c_frida/c_frida.c +68 -0
  28. data/ext/c_frida/extconf.rb +26 -25
  29. data/ext/c_frida/gutils.c +498 -0
  30. data/ext/c_frida/gvl_bridge.c +131 -0
  31. data/ext/c_frida/inc/Application.h +9 -0
  32. data/ext/c_frida/inc/Bus.h +15 -0
  33. data/ext/c_frida/inc/Child.h +9 -0
  34. data/ext/c_frida/inc/Compiler.h +21 -0
  35. data/ext/c_frida/inc/Crash.h +9 -0
  36. data/ext/c_frida/inc/Device.h +71 -0
  37. data/ext/c_frida/inc/DeviceManager.h +20 -0
  38. data/ext/c_frida/inc/EndpointParameters.h +15 -0
  39. data/ext/c_frida/inc/FileMonitor.h +9 -0
  40. data/ext/c_frida/inc/GObject.h +10 -0
  41. data/ext/c_frida/inc/IOStream.h +29 -0
  42. data/ext/c_frida/inc/PortalMembership.h +9 -0
  43. data/ext/c_frida/inc/PortalService.h +47 -0
  44. data/ext/c_frida/inc/Process.h +9 -0
  45. data/ext/c_frida/inc/Relay.h +9 -0
  46. data/ext/c_frida/inc/Script.h +21 -0
  47. data/ext/c_frida/inc/Session.h +40 -0
  48. data/ext/c_frida/inc/Spawn.h +9 -0
  49. data/ext/c_frida/inc/c_frida.h +129 -0
  50. data/ext/c_frida/inc/gutils.h +21 -0
  51. data/ext/c_frida/inc/gvl_bridge.h +42 -0
  52. data/frida.gemspec +39 -0
  53. data/lib/frida/version.rb +5 -0
  54. data/lib/frida.rb +8 -0
  55. 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
+ }
@@ -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
+ }