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
|
#include "frida-gum.h"
#include "debug.h"
#include "util.h"
#define DEFAULT_MMAP_MIN_ADDR (32UL << 10)
extern struct cmp_map *__afl_cmp_map;
static GArray *cmplog_ranges = NULL;
static gboolean cmplog_range(const GumRangeDetails *details,
gpointer user_data) {
UNUSED_PARAMETER(user_data);
GumMemoryRange range = *details->range;
g_array_append_val(cmplog_ranges, range);
return TRUE;
}
static gint cmplog_sort(gconstpointer a, gconstpointer b) {
return ((GumMemoryRange *)b)->base_address -
((GumMemoryRange *)a)->base_address;
}
void cmplog_init(void) {
if (__afl_cmp_map != NULL) { OKF("CMPLOG mode enabled"); }
cmplog_ranges = g_array_sized_new(false, false, sizeof(GumMemoryRange), 100);
gum_process_enumerate_ranges(GUM_PAGE_READ, cmplog_range, NULL);
g_array_sort(cmplog_ranges, cmplog_sort);
for (guint i = 0; i < cmplog_ranges->len; i++) {
GumMemoryRange *range = &g_array_index(cmplog_ranges, GumMemoryRange, i);
OKF("CMPLOG Range - 0x%016" G_GINT64_MODIFIER "X - 0x%016" G_GINT64_MODIFIER
"X",
range->base_address, range->base_address + range->size);
}
}
static gboolean cmplog_contains(GumAddress inner_base, GumAddress inner_limit,
GumAddress outer_base, GumAddress outer_limit) {
return (inner_base >= outer_base && inner_limit <= outer_limit);
}
gboolean cmplog_is_readable(guint64 addr, size_t size) {
if (cmplog_ranges == NULL) FATAL("CMPLOG not initialized");
/*
* The Linux kernel prevents mmap from allocating from the very bottom of the
* address space to mitigate NULL pointer dereference attacks. The exact size
* is set by sysctl by setting mmap_min_addr and 64k is suggested on most
* platforms with 32k on ARM systems. We therefore fail fast if the address
* is lower than this. This should avoid some overhead when functions are
* called where one of the parameters is a size, or a some other small value.
*/
if (addr < DEFAULT_MMAP_MIN_ADDR) { return false; }
GumAddress inner_base = addr;
GumAddress inner_limit = inner_base + size;
for (guint i = 0; i < cmplog_ranges->len; i++) {
GumMemoryRange *range = &g_array_index(cmplog_ranges, GumMemoryRange, i);
GumAddress outer_base = range->base_address;
GumAddress outer_limit = outer_base + range->size;
if (cmplog_contains(inner_base, inner_limit, outer_base, outer_limit))
return true;
}
return false;
}
|