about summary refs log tree commit diff
path: root/frida_mode/src/js/js.c
blob: ed378d2c11038c5441c0d1165c639462c4eabf7d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include "frida-gumjs.h"

#include "debug.h"

#include "js.h"
#include "util.h"

static char *             js_script = NULL;
gboolean                  js_done = FALSE;
js_api_stalker_callback_t js_user_callback = NULL;

static gchar *           filename = "afl.js";
static gchar *           contents;
static GumScriptBackend *backend;
static GCancellable *    cancellable = NULL;
static GError *          error = NULL;
static GumScript *       script;

static void js_msg(GumScript *script, const gchar *message, GBytes *data,
                   gpointer user_data) {

  UNUSED_PARAMETER(script);
  UNUSED_PARAMETER(data);
  UNUSED_PARAMETER(user_data);
  OKF("%s", message);

}

void js_config(void) {

  js_script = getenv("AFL_FRIDA_JS_SCRIPT");

}

static gchar *js_get_script() {

  gsize length;
  if (js_script != NULL) { filename = js_script; }

  filename = g_canonicalize_filename(filename, g_get_current_dir());

  if (!g_file_get_contents(filename, &contents, &length, NULL)) {

    if (js_script == NULL) {

      return NULL;

    } else {

      FATAL("Could not load script file: %s", filename);

    }

  } else {

    OKF("Loaded AFL script: %s, %" G_GSIZE_MODIFIER "d bytes", filename,
        length);

    gchar *source = g_malloc0(api_js_len + length + 1);
    memcpy(source, api_js, api_js_len);
    memcpy(&source[api_js_len], contents, length);

    return source;

  }

}

static void js_print_script(gchar *source) {

  gchar **split = g_strsplit(source, "\n", 0);

  for (size_t i = 0; split[i] != NULL; i++) {

    OKF("%3" G_GSIZE_MODIFIER "d. %s", i + 1, split[i]);

  }

  g_strfreev(split);

}

void js_start(void) {

  GMainContext *context;

  gchar *source = js_get_script();
  if (source == NULL) { return; }
  js_print_script(source);

  backend = gum_script_backend_obtain_qjs();

  script = gum_script_backend_create_sync(backend, "example", source,
                                          cancellable, &error);

  if (error != NULL) {

    g_printerr("%s\n", error->message);
    FATAL("Error processing script");

  }

  gum_script_set_message_handler(script, js_msg, NULL, NULL);

  gum_script_load_sync(script, cancellable);

  context = g_main_context_get_thread_default();
  while (g_main_context_pending(context))
    g_main_context_iteration(context, FALSE);

  if (!js_done) { FATAL("Script didn't call Afl.done()"); }

}

gboolean js_stalker_callback(const cs_insn *insn, gboolean begin,
                             gboolean excluded, GumStalkerOutput *output) {

  if (js_user_callback == NULL) { return TRUE; }
  return js_user_callback(insn, begin, excluded, output);

}