-
Notifications
You must be signed in to change notification settings - Fork 257
Expand file tree
/
Copy pathraptor_frida_linux_trace.js
More file actions
120 lines (99 loc) · 3.04 KB
/
Copy pathraptor_frida_linux_trace.js
File metadata and controls
120 lines (99 loc) · 3.04 KB
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
/*
* raptor_frida_linux_trace.js - Function tracer for Linux
* Copyright (c) 2025 Marco Ivaldi <raptor@0xdeadbeef.info>
*
* "Life is not like water. Things in life don't necessarily
* flow over the shortest possible route."
* -- Haruki Murakami, 1Q84
*
* Frida.re JS code to trace arbitrary function calls in a Linux ELF binary
* for debugging and reverse engineering. See https://www.frida.re/ and
* https://codeshare.frida.re/ for further information on this world-class
* dynamic instrumentation toolkit.
*
* Example usage:
* $ uv tool install frida-tools
* $ frida -f hello-vuln -l raptor_frida_linux_trace.js
*
* Tested with:
* Frida 17.2.1 on Ubuntu 24.0
*
* Get the latest version at:
* https://github.com/0xdea/frida-scripts/
*/
// Generic trace
function trace(pattern)
{
var type = (pattern.toString().indexOf("!") === -1) ? "function" : "module";
// Trace exported and imported functions of shared libraries
if (type === "module") {
var res = new ApiResolver("module");
var matches = res.enumerateMatches(pattern);
var targets = uniqBy(matches, JSON.stringify);
targets.forEach(function(target) {
traceFunction(target.address, target.name);
});
// Trace functions in the target binary
} else if (type === "function") {
var targets = []
for (const f of DebugSymbol.findFunctionsMatching(pattern)) {
targets.push(DebugSymbol.fromAddress(ptr(f)));
}
targets.forEach(function(target) {
traceFunction(target.address, target.name);
});
}
}
// Trace a function call
function traceFunction(impl, name)
{
console.log("Tracing " + name);
Interceptor.attach(impl, {
onEnter: function(args) {
// Trace only the intended calls
this.flag = 0;
//if (args[0].readUtf8String().match("AAA"))
this.flag = 1;
if (this.flag) {
console.warn("\n*** entered " + name);
// Print full backtrace
console.log("\nBacktrace:\n" + Thread.backtrace(this.context, Backtracer.ACCURATE)
.map(DebugSymbol.fromAddress).join("\n"));
// Print caller
//console.log("\nCaller: " + DebugSymbol.fromAddress(this.returnAddress))
// Print args (see https://frida.re/docs/javascript-api/#interceptor)
//console.log();
//console.log("arg1: " + args[0]);
//console.log("arg2: " + args[1]);
//console.log("arg3: " + args[2].readUtf8String());
//console.log("arg4: " + args[3].readUtf8String());
}
},
onLeave: function(retval) {
if (this.flag) {
// Print retval
console.log("\nretval: " + retval);
console.warn("\n*** exiting " + name);
}
}
});
}
// Remove duplicates from an array
function uniqBy(array, key)
{
var seen = {};
return array.filter(function(item) {
var k = key(item);
return seen.hasOwnProperty(k) ? false : (seen[k] = true);
});
}
// Usage examples
// Trace all imports
//trace("imports:*!*");
// Trace potential command injection sinks
//trace("imports:*!system");
//trace("imports:*!popen");
// Trace an export
//trace("exports:*!snprintf");
// Trace a function that matches a glob pattern
//trace("main")