Last active
December 14, 2021 11:44
-
-
Save trufae/cbe5086c64c58eda453620b0bf31a2f6 to your computer and use it in GitHub Desktop.
r2frida-agent.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ | |
| "use strict"; | |
| exports.byteLength = u, exports.toByteArray = i, exports.fromByteArray = d; | |
| for (var r = [], t = [], e = "undefined" != typeof Uint8Array ? Uint8Array : Array, n = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", o = 0, a = n.length; o < a; ++o) r[o] = n[o], | |
| t[n.charCodeAt(o)] = o; | |
| function h(r) { | |
| var t = r.length; | |
| if (t % 4 > 0) throw new Error("Invalid string. Length must be a multiple of 4"); | |
| var e = r.indexOf("="); | |
| return -1 === e && (e = t), [ e, e === t ? 0 : 4 - e % 4 ]; | |
| } | |
| function u(r) { | |
| var t = h(r), e = t[0], n = t[1]; | |
| return 3 * (e + n) / 4 - n; | |
| } | |
| function c(r, t, e) { | |
| return 3 * (t + e) / 4 - e; | |
| } | |
| function i(r) { | |
| var n, o, a = h(r), u = a[0], i = a[1], f = new e(c(r, u, i)), A = 0, d = i > 0 ? u - 4 : u; | |
| for (o = 0; o < d; o += 4) n = t[r.charCodeAt(o)] << 18 | t[r.charCodeAt(o + 1)] << 12 | t[r.charCodeAt(o + 2)] << 6 | t[r.charCodeAt(o + 3)], | |
| f[A++] = n >> 16 & 255, f[A++] = n >> 8 & 255, f[A++] = 255 & n; | |
| return 2 === i && (n = t[r.charCodeAt(o)] << 2 | t[r.charCodeAt(o + 1)] >> 4, f[A++] = 255 & n), | |
| 1 === i && (n = t[r.charCodeAt(o)] << 10 | t[r.charCodeAt(o + 1)] << 4 | t[r.charCodeAt(o + 2)] >> 2, | |
| f[A++] = n >> 8 & 255, f[A++] = 255 & n), f; | |
| } | |
| function f(t) { | |
| return r[t >> 18 & 63] + r[t >> 12 & 63] + r[t >> 6 & 63] + r[63 & t]; | |
| } | |
| function A(r, t, e) { | |
| for (var n, o = [], a = t; a < e; a += 3) n = (r[a] << 16 & 16711680) + (r[a + 1] << 8 & 65280) + (255 & r[a + 2]), | |
| o.push(f(n)); | |
| return o.join(""); | |
| } | |
| function d(t) { | |
| for (var e, n = t.length, o = n % 3, a = [], h = 16383, u = 0, c = n - o; u < c; u += h) a.push(A(t, u, u + h > c ? c : u + h)); | |
| return 1 === o ? (e = t[n - 1], a.push(r[e >> 2] + r[e << 4 & 63] + "==")) : 2 === o && (e = (t[n - 2] << 8) + t[n - 1], | |
| a.push(r[e >> 10] + r[e >> 4 & 63] + r[e << 2 & 63] + "=")), a.join(""); | |
| } | |
| t["-".charCodeAt(0)] = 62, t["_".charCodeAt(0)] = 63; | |
| },{}],2:[function(require,module,exports){ | |
| "use strict"; | |
| var e, t = "object" == typeof Reflect ? Reflect : null, n = t && "function" == typeof t.apply ? t.apply : function(e, t, n) { | |
| return Function.prototype.apply.call(e, t, n); | |
| }; | |
| function r(e) { | |
| console && console.warn && console.warn(e); | |
| } | |
| e = t && "function" == typeof t.ownKeys ? t.ownKeys : Object.getOwnPropertySymbols ? function(e) { | |
| return Object.getOwnPropertyNames(e).concat(Object.getOwnPropertySymbols(e)); | |
| } : function(e) { | |
| return Object.getOwnPropertyNames(e); | |
| }; | |
| var i = Number.isNaN || function(e) { | |
| return e != e; | |
| }; | |
| function o() { | |
| o.init.call(this); | |
| } | |
| module.exports = o, module.exports.once = m, o.EventEmitter = o, o.prototype._events = void 0, | |
| o.prototype._eventsCount = 0, o.prototype._maxListeners = void 0; | |
| var s = 10; | |
| function u(e) { | |
| if ("function" != typeof e) throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof e); | |
| } | |
| function f(e) { | |
| return void 0 === e._maxListeners ? o.defaultMaxListeners : e._maxListeners; | |
| } | |
| function c(e, t, n, i) { | |
| var o, s, c; | |
| if (u(n), void 0 === (s = e._events) ? (s = e._events = Object.create(null), e._eventsCount = 0) : (void 0 !== s.newListener && (e.emit("newListener", t, n.listener ? n.listener : n), | |
| s = e._events), c = s[t]), void 0 === c) c = s[t] = n, ++e._eventsCount; else if ("function" == typeof c ? c = s[t] = i ? [ n, c ] : [ c, n ] : i ? c.unshift(n) : c.push(n), | |
| (o = f(e)) > 0 && c.length > o && !c.warned) { | |
| c.warned = !0; | |
| var v = new Error("Possible EventEmitter memory leak detected. " + c.length + " " + String(t) + " listeners added. Use emitter.setMaxListeners() to increase limit"); | |
| v.name = "MaxListenersExceededWarning", v.emitter = e, v.type = t, v.count = c.length, | |
| r(v); | |
| } | |
| return e; | |
| } | |
| function v() { | |
| if (!this.fired) return this.target.removeListener(this.type, this.wrapFn), this.fired = !0, | |
| 0 === arguments.length ? this.listener.call(this.target) : this.listener.apply(this.target, arguments); | |
| } | |
| function l(e, t, n) { | |
| var r = { | |
| fired: !1, | |
| wrapFn: void 0, | |
| target: e, | |
| type: t, | |
| listener: n | |
| }, i = v.bind(r); | |
| return i.listener = n, r.wrapFn = i, i; | |
| } | |
| function p(e, t, n) { | |
| var r = e._events; | |
| if (void 0 === r) return []; | |
| var i = r[t]; | |
| return void 0 === i ? [] : "function" == typeof i ? n ? [ i.listener || i ] : [ i ] : n ? d(i) : h(i, i.length); | |
| } | |
| function a(e) { | |
| var t = this._events; | |
| if (void 0 !== t) { | |
| var n = t[e]; | |
| if ("function" == typeof n) return 1; | |
| if (void 0 !== n) return n.length; | |
| } | |
| return 0; | |
| } | |
| function h(e, t) { | |
| for (var n = new Array(t), r = 0; r < t; ++r) n[r] = e[r]; | |
| return n; | |
| } | |
| function y(e, t) { | |
| for (;t + 1 < e.length; t++) e[t] = e[t + 1]; | |
| e.pop(); | |
| } | |
| function d(e) { | |
| for (var t = new Array(e.length), n = 0; n < t.length; ++n) t[n] = e[n].listener || e[n]; | |
| return t; | |
| } | |
| function m(e, t) { | |
| return new Promise((function(n, r) { | |
| function i(n) { | |
| e.removeListener(t, o), r(n); | |
| } | |
| function o() { | |
| "function" == typeof e.removeListener && e.removeListener("error", i), n([].slice.call(arguments)); | |
| } | |
| g(e, t, o, { | |
| once: !0 | |
| }), "error" !== t && L(e, i, { | |
| once: !0 | |
| }); | |
| })); | |
| } | |
| function L(e, t, n) { | |
| "function" == typeof e.on && g(e, "error", t, n); | |
| } | |
| function g(e, t, n, r) { | |
| if ("function" == typeof e.on) r.once ? e.once(t, n) : e.on(t, n); else { | |
| if ("function" != typeof e.addEventListener) throw new TypeError('The "emitter" argument must be of type EventEmitter. Received type ' + typeof e); | |
| e.addEventListener(t, (function i(o) { | |
| r.once && e.removeEventListener(t, i), n(o); | |
| })); | |
| } | |
| } | |
| Object.defineProperty(o, "defaultMaxListeners", { | |
| enumerable: !0, | |
| get: function() { | |
| return s; | |
| }, | |
| set: function(e) { | |
| if ("number" != typeof e || e < 0 || i(e)) throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received ' + e + "."); | |
| s = e; | |
| } | |
| }), o.init = function() { | |
| void 0 !== this._events && this._events !== Object.getPrototypeOf(this)._events || (this._events = Object.create(null), | |
| this._eventsCount = 0), this._maxListeners = this._maxListeners || void 0; | |
| }, o.prototype.setMaxListeners = function(e) { | |
| if ("number" != typeof e || e < 0 || i(e)) throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + e + "."); | |
| return this._maxListeners = e, this; | |
| }, o.prototype.getMaxListeners = function() { | |
| return f(this); | |
| }, o.prototype.emit = function(e) { | |
| for (var t = [], r = 1; r < arguments.length; r++) t.push(arguments[r]); | |
| var i = "error" === e, o = this._events; | |
| if (void 0 !== o) i = i && void 0 === o.error; else if (!i) return !1; | |
| if (i) { | |
| var s; | |
| if (t.length > 0 && (s = t[0]), s instanceof Error) throw s; | |
| var u = new Error("Unhandled error." + (s ? " (" + s.message + ")" : "")); | |
| throw u.context = s, u; | |
| } | |
| var f = o[e]; | |
| if (void 0 === f) return !1; | |
| if ("function" == typeof f) n(f, this, t); else { | |
| var c = f.length, v = h(f, c); | |
| for (r = 0; r < c; ++r) n(v[r], this, t); | |
| } | |
| return !0; | |
| }, o.prototype.addListener = function(e, t) { | |
| return c(this, e, t, !1); | |
| }, o.prototype.on = o.prototype.addListener, o.prototype.prependListener = function(e, t) { | |
| return c(this, e, t, !0); | |
| }, o.prototype.once = function(e, t) { | |
| return u(t), this.on(e, l(this, e, t)), this; | |
| }, o.prototype.prependOnceListener = function(e, t) { | |
| return u(t), this.prependListener(e, l(this, e, t)), this; | |
| }, o.prototype.removeListener = function(e, t) { | |
| var n, r, i, o, s; | |
| if (u(t), void 0 === (r = this._events)) return this; | |
| if (void 0 === (n = r[e])) return this; | |
| if (n === t || n.listener === t) 0 == --this._eventsCount ? this._events = Object.create(null) : (delete r[e], | |
| r.removeListener && this.emit("removeListener", e, n.listener || t)); else if ("function" != typeof n) { | |
| for (i = -1, o = n.length - 1; o >= 0; o--) if (n[o] === t || n[o].listener === t) { | |
| s = n[o].listener, i = o; | |
| break; | |
| } | |
| if (i < 0) return this; | |
| 0 === i ? n.shift() : y(n, i), 1 === n.length && (r[e] = n[0]), void 0 !== r.removeListener && this.emit("removeListener", e, s || t); | |
| } | |
| return this; | |
| }, o.prototype.off = o.prototype.removeListener, o.prototype.removeAllListeners = function(e) { | |
| var t, n, r; | |
| if (void 0 === (n = this._events)) return this; | |
| if (void 0 === n.removeListener) return 0 === arguments.length ? (this._events = Object.create(null), | |
| this._eventsCount = 0) : void 0 !== n[e] && (0 == --this._eventsCount ? this._events = Object.create(null) : delete n[e]), | |
| this; | |
| if (0 === arguments.length) { | |
| var i, o = Object.keys(n); | |
| for (r = 0; r < o.length; ++r) "removeListener" !== (i = o[r]) && this.removeAllListeners(i); | |
| return this.removeAllListeners("removeListener"), this._events = Object.create(null), | |
| this._eventsCount = 0, this; | |
| } | |
| if ("function" == typeof (t = n[e])) this.removeListener(e, t); else if (void 0 !== t) for (r = t.length - 1; r >= 0; r--) this.removeListener(e, t[r]); | |
| return this; | |
| }, o.prototype.listeners = function(e) { | |
| return p(this, e, !0); | |
| }, o.prototype.rawListeners = function(e) { | |
| return p(this, e, !1); | |
| }, o.listenerCount = function(e, t) { | |
| return "function" == typeof e.listenerCount ? e.listenerCount(t) : a.call(e, t); | |
| }, o.prototype.listenerCount = a, o.prototype.eventNames = function() { | |
| return this._eventsCount > 0 ? e(this._events) : []; | |
| }; | |
| },{}],3:[function(require,module,exports){ | |
| (function (global){(function (){ | |
| global.TYPED_ARRAY_SUPPORT = !0, module.exports = require("buffer/"); | |
| }).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) | |
| },{"buffer/":4}],4:[function(require,module,exports){ | |
| /*! | |
| * The buffer module from node.js, for the browser. | |
| * | |
| * @author Feross Aboukhadijeh <https://feross.org> | |
| * @license MIT | |
| */ | |
| "use strict"; | |
| var t = require("base64-js"), r = require("ieee754"), e = "function" == typeof Symbol && "function" == typeof Symbol.for ? Symbol.for("nodejs.util.inspect.custom") : null; | |
| exports.Buffer = f, exports.SlowBuffer = d, exports.INSPECT_MAX_BYTES = 50; | |
| var n = 2147483647; | |
| function i() { | |
| try { | |
| var t = new Uint8Array(1), r = { | |
| foo: function() { | |
| return 42; | |
| } | |
| }; | |
| return Object.setPrototypeOf(r, Uint8Array.prototype), Object.setPrototypeOf(t, r), | |
| 42 === t.foo(); | |
| } catch (t) { | |
| return !1; | |
| } | |
| } | |
| function o(t) { | |
| if (t > n) throw new RangeError('The value "' + t + '" is invalid for option "size"'); | |
| var r = new Uint8Array(t); | |
| return Object.setPrototypeOf(r, f.prototype), r; | |
| } | |
| function f(t, r, e) { | |
| if ("number" == typeof t) { | |
| if ("string" == typeof r) throw new TypeError('The "string" argument must be of type string. Received type number'); | |
| return a(t); | |
| } | |
| return u(t, r, e); | |
| } | |
| function u(t, r, e) { | |
| if ("string" == typeof t) return p(t, r); | |
| if (ArrayBuffer.isView(t)) return l(t); | |
| if (null == t) throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type " + typeof t); | |
| if (Z(t, ArrayBuffer) || t && Z(t.buffer, ArrayBuffer)) return y(t, r, e); | |
| if ("undefined" != typeof SharedArrayBuffer && (Z(t, SharedArrayBuffer) || t && Z(t.buffer, SharedArrayBuffer))) return y(t, r, e); | |
| if ("number" == typeof t) throw new TypeError('The "value" argument must not be of type number. Received type number'); | |
| var n = t.valueOf && t.valueOf(); | |
| if (null != n && n !== t) return f.from(n, r, e); | |
| var i = g(t); | |
| if (i) return i; | |
| if ("undefined" != typeof Symbol && null != Symbol.toPrimitive && "function" == typeof t[Symbol.toPrimitive]) return f.from(t[Symbol.toPrimitive]("string"), r, e); | |
| throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type " + typeof t); | |
| } | |
| function s(t) { | |
| if ("number" != typeof t) throw new TypeError('"size" argument must be of type number'); | |
| if (t < 0) throw new RangeError('The value "' + t + '" is invalid for option "size"'); | |
| } | |
| function h(t, r, e) { | |
| return s(t), t <= 0 ? o(t) : void 0 !== r ? "string" == typeof e ? o(t).fill(r, e) : o(t).fill(r) : o(t); | |
| } | |
| function a(t) { | |
| return s(t), o(t < 0 ? 0 : 0 | w(t)); | |
| } | |
| function p(t, r) { | |
| if ("string" == typeof r && "" !== r || (r = "utf8"), !f.isEncoding(r)) throw new TypeError("Unknown encoding: " + r); | |
| var e = 0 | v(t, r), n = o(e), i = n.write(t, r); | |
| return i !== e && (n = n.slice(0, i)), n; | |
| } | |
| function c(t) { | |
| for (var r = t.length < 0 ? 0 : 0 | w(t.length), e = o(r), n = 0; n < r; n += 1) e[n] = 255 & t[n]; | |
| return e; | |
| } | |
| function l(t) { | |
| if (Z(t, Uint8Array)) { | |
| var r = new Uint8Array(t); | |
| return y(r.buffer, r.byteOffset, r.byteLength); | |
| } | |
| return c(t); | |
| } | |
| function y(t, r, e) { | |
| if (r < 0 || t.byteLength < r) throw new RangeError('"offset" is outside of buffer bounds'); | |
| if (t.byteLength < r + (e || 0)) throw new RangeError('"length" is outside of buffer bounds'); | |
| var n; | |
| return n = void 0 === r && void 0 === e ? new Uint8Array(t) : void 0 === e ? new Uint8Array(t, r) : new Uint8Array(t, r, e), | |
| Object.setPrototypeOf(n, f.prototype), n; | |
| } | |
| function g(t) { | |
| if (f.isBuffer(t)) { | |
| var r = 0 | w(t.length), e = o(r); | |
| return 0 === e.length || t.copy(e, 0, 0, r), e; | |
| } | |
| return void 0 !== t.length ? "number" != typeof t.length || $(t.length) ? o(0) : c(t) : "Buffer" === t.type && Array.isArray(t.data) ? c(t.data) : void 0; | |
| } | |
| function w(t) { | |
| if (t >= n) throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x" + n.toString(16) + " bytes"); | |
| return 0 | t; | |
| } | |
| function d(t) { | |
| return +t != t && (t = 0), f.alloc(+t); | |
| } | |
| function v(t, r) { | |
| if (f.isBuffer(t)) return t.length; | |
| if (ArrayBuffer.isView(t) || Z(t, ArrayBuffer)) return t.byteLength; | |
| if ("string" != typeof t) throw new TypeError('The "string" argument must be one of type string, Buffer, or ArrayBuffer. Received type ' + typeof t); | |
| var e = t.length, n = arguments.length > 2 && !0 === arguments[2]; | |
| if (!n && 0 === e) return 0; | |
| for (var i = !1; ;) switch (r) { | |
| case "ascii": | |
| case "latin1": | |
| case "binary": | |
| return e; | |
| case "utf8": | |
| case "utf-8": | |
| return q(t).length; | |
| case "ucs2": | |
| case "ucs-2": | |
| case "utf16le": | |
| case "utf-16le": | |
| return 2 * e; | |
| case "hex": | |
| return e >>> 1; | |
| case "base64": | |
| return X(t).length; | |
| default: | |
| if (i) return n ? -1 : q(t).length; | |
| r = ("" + r).toLowerCase(), i = !0; | |
| } | |
| } | |
| function b(t, r, e) { | |
| var n = !1; | |
| if ((void 0 === r || r < 0) && (r = 0), r > this.length) return ""; | |
| if ((void 0 === e || e > this.length) && (e = this.length), e <= 0) return ""; | |
| if ((e >>>= 0) <= (r >>>= 0)) return ""; | |
| for (t || (t = "utf8"); ;) switch (t) { | |
| case "hex": | |
| return k(this, r, e); | |
| case "utf8": | |
| case "utf-8": | |
| return O(this, r, e); | |
| case "ascii": | |
| return C(this, r, e); | |
| case "latin1": | |
| case "binary": | |
| return P(this, r, e); | |
| case "base64": | |
| return S(this, r, e); | |
| case "ucs2": | |
| case "ucs-2": | |
| case "utf16le": | |
| case "utf-16le": | |
| return M(this, r, e); | |
| default: | |
| if (n) throw new TypeError("Unknown encoding: " + t); | |
| t = (t + "").toLowerCase(), n = !0; | |
| } | |
| } | |
| function m(t, r, e) { | |
| var n = t[r]; | |
| t[r] = t[e], t[e] = n; | |
| } | |
| function E(t, r, e, n, i) { | |
| if (0 === t.length) return -1; | |
| if ("string" == typeof e ? (n = e, e = 0) : e > 2147483647 ? e = 2147483647 : e < -2147483648 && (e = -2147483648), | |
| $(e = +e) && (e = i ? 0 : t.length - 1), e < 0 && (e = t.length + e), e >= t.length) { | |
| if (i) return -1; | |
| e = t.length - 1; | |
| } else if (e < 0) { | |
| if (!i) return -1; | |
| e = 0; | |
| } | |
| if ("string" == typeof r && (r = f.from(r, n)), f.isBuffer(r)) return 0 === r.length ? -1 : B(t, r, e, n, i); | |
| if ("number" == typeof r) return r &= 255, "function" == typeof Uint8Array.prototype.indexOf ? i ? Uint8Array.prototype.indexOf.call(t, r, e) : Uint8Array.prototype.lastIndexOf.call(t, r, e) : B(t, [ r ], e, n, i); | |
| throw new TypeError("val must be string, number or Buffer"); | |
| } | |
| function B(t, r, e, n, i) { | |
| var o, f = 1, u = t.length, s = r.length; | |
| if (void 0 !== n && ("ucs2" === (n = String(n).toLowerCase()) || "ucs-2" === n || "utf16le" === n || "utf-16le" === n)) { | |
| if (t.length < 2 || r.length < 2) return -1; | |
| f = 2, u /= 2, s /= 2, e /= 2; | |
| } | |
| function h(t, r) { | |
| return 1 === f ? t[r] : t.readUInt16BE(r * f); | |
| } | |
| if (i) { | |
| var a = -1; | |
| for (o = e; o < u; o++) if (h(t, o) === h(r, -1 === a ? 0 : o - a)) { | |
| if (-1 === a && (a = o), o - a + 1 === s) return a * f; | |
| } else -1 !== a && (o -= o - a), a = -1; | |
| } else for (e + s > u && (e = u - s), o = e; o >= 0; o--) { | |
| for (var p = !0, c = 0; c < s; c++) if (h(t, o + c) !== h(r, c)) { | |
| p = !1; | |
| break; | |
| } | |
| if (p) return o; | |
| } | |
| return -1; | |
| } | |
| function A(t, r, e, n) { | |
| e = Number(e) || 0; | |
| var i = t.length - e; | |
| n ? (n = Number(n)) > i && (n = i) : n = i; | |
| var o = r.length; | |
| n > o / 2 && (n = o / 2); | |
| for (var f = 0; f < n; ++f) { | |
| var u = parseInt(r.substr(2 * f, 2), 16); | |
| if ($(u)) return f; | |
| t[e + f] = u; | |
| } | |
| return f; | |
| } | |
| function U(t, r, e, n) { | |
| return J(q(r, t.length - e), t, e, n); | |
| } | |
| function T(t, r, e, n) { | |
| return J(V(r), t, e, n); | |
| } | |
| function I(t, r, e, n) { | |
| return J(X(r), t, e, n); | |
| } | |
| function L(t, r, e, n) { | |
| return J(W(r, t.length - e), t, e, n); | |
| } | |
| function S(r, e, n) { | |
| return 0 === e && n === r.length ? t.fromByteArray(r) : t.fromByteArray(r.slice(e, n)); | |
| } | |
| function O(t, r, e) { | |
| e = Math.min(t.length, e); | |
| for (var n = [], i = r; i < e; ) { | |
| var o, f, u, s, h = t[i], a = null, p = h > 239 ? 4 : h > 223 ? 3 : h > 191 ? 2 : 1; | |
| if (i + p <= e) switch (p) { | |
| case 1: | |
| h < 128 && (a = h); | |
| break; | |
| case 2: | |
| 128 == (192 & (o = t[i + 1])) && (s = (31 & h) << 6 | 63 & o) > 127 && (a = s); | |
| break; | |
| case 3: | |
| o = t[i + 1], f = t[i + 2], 128 == (192 & o) && 128 == (192 & f) && (s = (15 & h) << 12 | (63 & o) << 6 | 63 & f) > 2047 && (s < 55296 || s > 57343) && (a = s); | |
| break; | |
| case 4: | |
| o = t[i + 1], f = t[i + 2], u = t[i + 3], 128 == (192 & o) && 128 == (192 & f) && 128 == (192 & u) && (s = (15 & h) << 18 | (63 & o) << 12 | (63 & f) << 6 | 63 & u) > 65535 && s < 1114112 && (a = s); | |
| } | |
| null === a ? (a = 65533, p = 1) : a > 65535 && (a -= 65536, n.push(a >>> 10 & 1023 | 55296), | |
| a = 56320 | 1023 & a), n.push(a), i += p; | |
| } | |
| return x(n); | |
| } | |
| exports.kMaxLength = n, f.TYPED_ARRAY_SUPPORT = i(), f.TYPED_ARRAY_SUPPORT || "undefined" == typeof console || "function" != typeof console.error || console.error("This browser lacks typed array (Uint8Array) support which is required by `buffer` v5.x. Use `buffer` v4.x if you require old browser support."), | |
| Object.defineProperty(f.prototype, "parent", { | |
| enumerable: !0, | |
| get: function() { | |
| if (f.isBuffer(this)) return this.buffer; | |
| } | |
| }), Object.defineProperty(f.prototype, "offset", { | |
| enumerable: !0, | |
| get: function() { | |
| if (f.isBuffer(this)) return this.byteOffset; | |
| } | |
| }), f.poolSize = 8192, f.from = function(t, r, e) { | |
| return u(t, r, e); | |
| }, Object.setPrototypeOf(f.prototype, Uint8Array.prototype), Object.setPrototypeOf(f, Uint8Array), | |
| f.alloc = function(t, r, e) { | |
| return h(t, r, e); | |
| }, f.allocUnsafe = function(t) { | |
| return a(t); | |
| }, f.allocUnsafeSlow = function(t) { | |
| return a(t); | |
| }, f.isBuffer = function(t) { | |
| return null != t && !0 === t._isBuffer && t !== f.prototype; | |
| }, f.compare = function(t, r) { | |
| if (Z(t, Uint8Array) && (t = f.from(t, t.offset, t.byteLength)), Z(r, Uint8Array) && (r = f.from(r, r.offset, r.byteLength)), | |
| !f.isBuffer(t) || !f.isBuffer(r)) throw new TypeError('The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array'); | |
| if (t === r) return 0; | |
| for (var e = t.length, n = r.length, i = 0, o = Math.min(e, n); i < o; ++i) if (t[i] !== r[i]) { | |
| e = t[i], n = r[i]; | |
| break; | |
| } | |
| return e < n ? -1 : n < e ? 1 : 0; | |
| }, f.isEncoding = function(t) { | |
| switch (String(t).toLowerCase()) { | |
| case "hex": | |
| case "utf8": | |
| case "utf-8": | |
| case "ascii": | |
| case "latin1": | |
| case "binary": | |
| case "base64": | |
| case "ucs2": | |
| case "ucs-2": | |
| case "utf16le": | |
| case "utf-16le": | |
| return !0; | |
| default: | |
| return !1; | |
| } | |
| }, f.concat = function(t, r) { | |
| if (!Array.isArray(t)) throw new TypeError('"list" argument must be an Array of Buffers'); | |
| if (0 === t.length) return f.alloc(0); | |
| var e; | |
| if (void 0 === r) for (r = 0, e = 0; e < t.length; ++e) r += t[e].length; | |
| var n = f.allocUnsafe(r), i = 0; | |
| for (e = 0; e < t.length; ++e) { | |
| var o = t[e]; | |
| if (Z(o, Uint8Array)) i + o.length > n.length ? f.from(o).copy(n, i) : Uint8Array.prototype.set.call(n, o, i); else { | |
| if (!f.isBuffer(o)) throw new TypeError('"list" argument must be an Array of Buffers'); | |
| o.copy(n, i); | |
| } | |
| i += o.length; | |
| } | |
| return n; | |
| }, f.byteLength = v, f.prototype._isBuffer = !0, f.prototype.swap16 = function() { | |
| var t = this.length; | |
| if (t % 2 != 0) throw new RangeError("Buffer size must be a multiple of 16-bits"); | |
| for (var r = 0; r < t; r += 2) m(this, r, r + 1); | |
| return this; | |
| }, f.prototype.swap32 = function() { | |
| var t = this.length; | |
| if (t % 4 != 0) throw new RangeError("Buffer size must be a multiple of 32-bits"); | |
| for (var r = 0; r < t; r += 4) m(this, r, r + 3), m(this, r + 1, r + 2); | |
| return this; | |
| }, f.prototype.swap64 = function() { | |
| var t = this.length; | |
| if (t % 8 != 0) throw new RangeError("Buffer size must be a multiple of 64-bits"); | |
| for (var r = 0; r < t; r += 8) m(this, r, r + 7), m(this, r + 1, r + 6), m(this, r + 2, r + 5), | |
| m(this, r + 3, r + 4); | |
| return this; | |
| }, f.prototype.toString = function() { | |
| var t = this.length; | |
| return 0 === t ? "" : 0 === arguments.length ? O(this, 0, t) : b.apply(this, arguments); | |
| }, f.prototype.toLocaleString = f.prototype.toString, f.prototype.equals = function(t) { | |
| if (!f.isBuffer(t)) throw new TypeError("Argument must be a Buffer"); | |
| return this === t || 0 === f.compare(this, t); | |
| }, f.prototype.inspect = function() { | |
| var t = "", r = exports.INSPECT_MAX_BYTES; | |
| return t = this.toString("hex", 0, r).replace(/(.{2})/g, "$1 ").trim(), this.length > r && (t += " ... "), | |
| "<Buffer " + t + ">"; | |
| }, e && (f.prototype[e] = f.prototype.inspect), f.prototype.compare = function(t, r, e, n, i) { | |
| if (Z(t, Uint8Array) && (t = f.from(t, t.offset, t.byteLength)), !f.isBuffer(t)) throw new TypeError('The "target" argument must be one of type Buffer or Uint8Array. Received type ' + typeof t); | |
| if (void 0 === r && (r = 0), void 0 === e && (e = t ? t.length : 0), void 0 === n && (n = 0), | |
| void 0 === i && (i = this.length), r < 0 || e > t.length || n < 0 || i > this.length) throw new RangeError("out of range index"); | |
| if (n >= i && r >= e) return 0; | |
| if (n >= i) return -1; | |
| if (r >= e) return 1; | |
| if (this === t) return 0; | |
| for (var o = (i >>>= 0) - (n >>>= 0), u = (e >>>= 0) - (r >>>= 0), s = Math.min(o, u), h = this.slice(n, i), a = t.slice(r, e), p = 0; p < s; ++p) if (h[p] !== a[p]) { | |
| o = h[p], u = a[p]; | |
| break; | |
| } | |
| return o < u ? -1 : u < o ? 1 : 0; | |
| }, f.prototype.includes = function(t, r, e) { | |
| return -1 !== this.indexOf(t, r, e); | |
| }, f.prototype.indexOf = function(t, r, e) { | |
| return E(this, t, r, e, !0); | |
| }, f.prototype.lastIndexOf = function(t, r, e) { | |
| return E(this, t, r, e, !1); | |
| }, f.prototype.write = function(t, r, e, n) { | |
| if (void 0 === r) n = "utf8", e = this.length, r = 0; else if (void 0 === e && "string" == typeof r) n = r, | |
| e = this.length, r = 0; else { | |
| if (!isFinite(r)) throw new Error("Buffer.write(string, encoding, offset[, length]) is no longer supported"); | |
| r >>>= 0, isFinite(e) ? (e >>>= 0, void 0 === n && (n = "utf8")) : (n = e, e = void 0); | |
| } | |
| var i = this.length - r; | |
| if ((void 0 === e || e > i) && (e = i), t.length > 0 && (e < 0 || r < 0) || r > this.length) throw new RangeError("Attempt to write outside buffer bounds"); | |
| n || (n = "utf8"); | |
| for (var o = !1; ;) switch (n) { | |
| case "hex": | |
| return A(this, t, r, e); | |
| case "utf8": | |
| case "utf-8": | |
| return U(this, t, r, e); | |
| case "ascii": | |
| case "latin1": | |
| case "binary": | |
| return T(this, t, r, e); | |
| case "base64": | |
| return I(this, t, r, e); | |
| case "ucs2": | |
| case "ucs-2": | |
| case "utf16le": | |
| case "utf-16le": | |
| return L(this, t, r, e); | |
| default: | |
| if (o) throw new TypeError("Unknown encoding: " + n); | |
| n = ("" + n).toLowerCase(), o = !0; | |
| } | |
| }, f.prototype.toJSON = function() { | |
| return { | |
| type: "Buffer", | |
| data: Array.prototype.slice.call(this._arr || this, 0) | |
| }; | |
| }; | |
| var R = 4096; | |
| function x(t) { | |
| var r = t.length; | |
| if (r <= R) return String.fromCharCode.apply(String, t); | |
| for (var e = "", n = 0; n < r; ) e += String.fromCharCode.apply(String, t.slice(n, n += R)); | |
| return e; | |
| } | |
| function C(t, r, e) { | |
| var n = ""; | |
| e = Math.min(t.length, e); | |
| for (var i = r; i < e; ++i) n += String.fromCharCode(127 & t[i]); | |
| return n; | |
| } | |
| function P(t, r, e) { | |
| var n = ""; | |
| e = Math.min(t.length, e); | |
| for (var i = r; i < e; ++i) n += String.fromCharCode(t[i]); | |
| return n; | |
| } | |
| function k(t, r, e) { | |
| var n = t.length; | |
| (!r || r < 0) && (r = 0), (!e || e < 0 || e > n) && (e = n); | |
| for (var i = "", o = r; o < e; ++o) i += G[t[o]]; | |
| return i; | |
| } | |
| function M(t, r, e) { | |
| for (var n = t.slice(r, e), i = "", o = 0; o < n.length - 1; o += 2) i += String.fromCharCode(n[o] + 256 * n[o + 1]); | |
| return i; | |
| } | |
| function j(t, r, e) { | |
| if (t % 1 != 0 || t < 0) throw new RangeError("offset is not uint"); | |
| if (t + r > e) throw new RangeError("Trying to access beyond buffer length"); | |
| } | |
| function _(t, r, e, n, i, o) { | |
| if (!f.isBuffer(t)) throw new TypeError('"buffer" argument must be a Buffer instance'); | |
| if (r > i || r < o) throw new RangeError('"value" argument is out of bounds'); | |
| if (e + n > t.length) throw new RangeError("Index out of range"); | |
| } | |
| function z(t, r, e, n, i, o) { | |
| if (e + n > t.length) throw new RangeError("Index out of range"); | |
| if (e < 0) throw new RangeError("Index out of range"); | |
| } | |
| function D(t, e, n, i, o) { | |
| return e = +e, n >>>= 0, o || z(t, e, n, 4, 34028234663852886e22, -34028234663852886e22), | |
| r.write(t, e, n, i, 23, 4), n + 4; | |
| } | |
| function F(t, e, n, i, o) { | |
| return e = +e, n >>>= 0, o || z(t, e, n, 8, 17976931348623157e292, -17976931348623157e292), | |
| r.write(t, e, n, i, 52, 8), n + 8; | |
| } | |
| f.prototype.slice = function(t, r) { | |
| var e = this.length; | |
| (t = ~~t) < 0 ? (t += e) < 0 && (t = 0) : t > e && (t = e), (r = void 0 === r ? e : ~~r) < 0 ? (r += e) < 0 && (r = 0) : r > e && (r = e), | |
| r < t && (r = t); | |
| var n = this.subarray(t, r); | |
| return Object.setPrototypeOf(n, f.prototype), n; | |
| }, f.prototype.readUintLE = f.prototype.readUIntLE = function(t, r, e) { | |
| t >>>= 0, r >>>= 0, e || j(t, r, this.length); | |
| for (var n = this[t], i = 1, o = 0; ++o < r && (i *= 256); ) n += this[t + o] * i; | |
| return n; | |
| }, f.prototype.readUintBE = f.prototype.readUIntBE = function(t, r, e) { | |
| t >>>= 0, r >>>= 0, e || j(t, r, this.length); | |
| for (var n = this[t + --r], i = 1; r > 0 && (i *= 256); ) n += this[t + --r] * i; | |
| return n; | |
| }, f.prototype.readUint8 = f.prototype.readUInt8 = function(t, r) { | |
| return t >>>= 0, r || j(t, 1, this.length), this[t]; | |
| }, f.prototype.readUint16LE = f.prototype.readUInt16LE = function(t, r) { | |
| return t >>>= 0, r || j(t, 2, this.length), this[t] | this[t + 1] << 8; | |
| }, f.prototype.readUint16BE = f.prototype.readUInt16BE = function(t, r) { | |
| return t >>>= 0, r || j(t, 2, this.length), this[t] << 8 | this[t + 1]; | |
| }, f.prototype.readUint32LE = f.prototype.readUInt32LE = function(t, r) { | |
| return t >>>= 0, r || j(t, 4, this.length), (this[t] | this[t + 1] << 8 | this[t + 2] << 16) + 16777216 * this[t + 3]; | |
| }, f.prototype.readUint32BE = f.prototype.readUInt32BE = function(t, r) { | |
| return t >>>= 0, r || j(t, 4, this.length), 16777216 * this[t] + (this[t + 1] << 16 | this[t + 2] << 8 | this[t + 3]); | |
| }, f.prototype.readIntLE = function(t, r, e) { | |
| t >>>= 0, r >>>= 0, e || j(t, r, this.length); | |
| for (var n = this[t], i = 1, o = 0; ++o < r && (i *= 256); ) n += this[t + o] * i; | |
| return n >= (i *= 128) && (n -= Math.pow(2, 8 * r)), n; | |
| }, f.prototype.readIntBE = function(t, r, e) { | |
| t >>>= 0, r >>>= 0, e || j(t, r, this.length); | |
| for (var n = r, i = 1, o = this[t + --n]; n > 0 && (i *= 256); ) o += this[t + --n] * i; | |
| return o >= (i *= 128) && (o -= Math.pow(2, 8 * r)), o; | |
| }, f.prototype.readInt8 = function(t, r) { | |
| return t >>>= 0, r || j(t, 1, this.length), 128 & this[t] ? -1 * (255 - this[t] + 1) : this[t]; | |
| }, f.prototype.readInt16LE = function(t, r) { | |
| t >>>= 0, r || j(t, 2, this.length); | |
| var e = this[t] | this[t + 1] << 8; | |
| return 32768 & e ? 4294901760 | e : e; | |
| }, f.prototype.readInt16BE = function(t, r) { | |
| t >>>= 0, r || j(t, 2, this.length); | |
| var e = this[t + 1] | this[t] << 8; | |
| return 32768 & e ? 4294901760 | e : e; | |
| }, f.prototype.readInt32LE = function(t, r) { | |
| return t >>>= 0, r || j(t, 4, this.length), this[t] | this[t + 1] << 8 | this[t + 2] << 16 | this[t + 3] << 24; | |
| }, f.prototype.readInt32BE = function(t, r) { | |
| return t >>>= 0, r || j(t, 4, this.length), this[t] << 24 | this[t + 1] << 16 | this[t + 2] << 8 | this[t + 3]; | |
| }, f.prototype.readFloatLE = function(t, e) { | |
| return t >>>= 0, e || j(t, 4, this.length), r.read(this, t, !0, 23, 4); | |
| }, f.prototype.readFloatBE = function(t, e) { | |
| return t >>>= 0, e || j(t, 4, this.length), r.read(this, t, !1, 23, 4); | |
| }, f.prototype.readDoubleLE = function(t, e) { | |
| return t >>>= 0, e || j(t, 8, this.length), r.read(this, t, !0, 52, 8); | |
| }, f.prototype.readDoubleBE = function(t, e) { | |
| return t >>>= 0, e || j(t, 8, this.length), r.read(this, t, !1, 52, 8); | |
| }, f.prototype.writeUintLE = f.prototype.writeUIntLE = function(t, r, e, n) { | |
| (t = +t, r >>>= 0, e >>>= 0, n) || _(this, t, r, e, Math.pow(2, 8 * e) - 1, 0); | |
| var i = 1, o = 0; | |
| for (this[r] = 255 & t; ++o < e && (i *= 256); ) this[r + o] = t / i & 255; | |
| return r + e; | |
| }, f.prototype.writeUintBE = f.prototype.writeUIntBE = function(t, r, e, n) { | |
| (t = +t, r >>>= 0, e >>>= 0, n) || _(this, t, r, e, Math.pow(2, 8 * e) - 1, 0); | |
| var i = e - 1, o = 1; | |
| for (this[r + i] = 255 & t; --i >= 0 && (o *= 256); ) this[r + i] = t / o & 255; | |
| return r + e; | |
| }, f.prototype.writeUint8 = f.prototype.writeUInt8 = function(t, r, e) { | |
| return t = +t, r >>>= 0, e || _(this, t, r, 1, 255, 0), this[r] = 255 & t, r + 1; | |
| }, f.prototype.writeUint16LE = f.prototype.writeUInt16LE = function(t, r, e) { | |
| return t = +t, r >>>= 0, e || _(this, t, r, 2, 65535, 0), this[r] = 255 & t, this[r + 1] = t >>> 8, | |
| r + 2; | |
| }, f.prototype.writeUint16BE = f.prototype.writeUInt16BE = function(t, r, e) { | |
| return t = +t, r >>>= 0, e || _(this, t, r, 2, 65535, 0), this[r] = t >>> 8, this[r + 1] = 255 & t, | |
| r + 2; | |
| }, f.prototype.writeUint32LE = f.prototype.writeUInt32LE = function(t, r, e) { | |
| return t = +t, r >>>= 0, e || _(this, t, r, 4, 4294967295, 0), this[r + 3] = t >>> 24, | |
| this[r + 2] = t >>> 16, this[r + 1] = t >>> 8, this[r] = 255 & t, r + 4; | |
| }, f.prototype.writeUint32BE = f.prototype.writeUInt32BE = function(t, r, e) { | |
| return t = +t, r >>>= 0, e || _(this, t, r, 4, 4294967295, 0), this[r] = t >>> 24, | |
| this[r + 1] = t >>> 16, this[r + 2] = t >>> 8, this[r + 3] = 255 & t, r + 4; | |
| }, f.prototype.writeIntLE = function(t, r, e, n) { | |
| if (t = +t, r >>>= 0, !n) { | |
| var i = Math.pow(2, 8 * e - 1); | |
| _(this, t, r, e, i - 1, -i); | |
| } | |
| var o = 0, f = 1, u = 0; | |
| for (this[r] = 255 & t; ++o < e && (f *= 256); ) t < 0 && 0 === u && 0 !== this[r + o - 1] && (u = 1), | |
| this[r + o] = (t / f >> 0) - u & 255; | |
| return r + e; | |
| }, f.prototype.writeIntBE = function(t, r, e, n) { | |
| if (t = +t, r >>>= 0, !n) { | |
| var i = Math.pow(2, 8 * e - 1); | |
| _(this, t, r, e, i - 1, -i); | |
| } | |
| var o = e - 1, f = 1, u = 0; | |
| for (this[r + o] = 255 & t; --o >= 0 && (f *= 256); ) t < 0 && 0 === u && 0 !== this[r + o + 1] && (u = 1), | |
| this[r + o] = (t / f >> 0) - u & 255; | |
| return r + e; | |
| }, f.prototype.writeInt8 = function(t, r, e) { | |
| return t = +t, r >>>= 0, e || _(this, t, r, 1, 127, -128), t < 0 && (t = 255 + t + 1), | |
| this[r] = 255 & t, r + 1; | |
| }, f.prototype.writeInt16LE = function(t, r, e) { | |
| return t = +t, r >>>= 0, e || _(this, t, r, 2, 32767, -32768), this[r] = 255 & t, | |
| this[r + 1] = t >>> 8, r + 2; | |
| }, f.prototype.writeInt16BE = function(t, r, e) { | |
| return t = +t, r >>>= 0, e || _(this, t, r, 2, 32767, -32768), this[r] = t >>> 8, | |
| this[r + 1] = 255 & t, r + 2; | |
| }, f.prototype.writeInt32LE = function(t, r, e) { | |
| return t = +t, r >>>= 0, e || _(this, t, r, 4, 2147483647, -2147483648), this[r] = 255 & t, | |
| this[r + 1] = t >>> 8, this[r + 2] = t >>> 16, this[r + 3] = t >>> 24, r + 4; | |
| }, f.prototype.writeInt32BE = function(t, r, e) { | |
| return t = +t, r >>>= 0, e || _(this, t, r, 4, 2147483647, -2147483648), t < 0 && (t = 4294967295 + t + 1), | |
| this[r] = t >>> 24, this[r + 1] = t >>> 16, this[r + 2] = t >>> 8, this[r + 3] = 255 & t, | |
| r + 4; | |
| }, f.prototype.writeFloatLE = function(t, r, e) { | |
| return D(this, t, r, !0, e); | |
| }, f.prototype.writeFloatBE = function(t, r, e) { | |
| return D(this, t, r, !1, e); | |
| }, f.prototype.writeDoubleLE = function(t, r, e) { | |
| return F(this, t, r, !0, e); | |
| }, f.prototype.writeDoubleBE = function(t, r, e) { | |
| return F(this, t, r, !1, e); | |
| }, f.prototype.copy = function(t, r, e, n) { | |
| if (!f.isBuffer(t)) throw new TypeError("argument should be a Buffer"); | |
| if (e || (e = 0), n || 0 === n || (n = this.length), r >= t.length && (r = t.length), | |
| r || (r = 0), n > 0 && n < e && (n = e), n === e) return 0; | |
| if (0 === t.length || 0 === this.length) return 0; | |
| if (r < 0) throw new RangeError("targetStart out of bounds"); | |
| if (e < 0 || e >= this.length) throw new RangeError("Index out of range"); | |
| if (n < 0) throw new RangeError("sourceEnd out of bounds"); | |
| n > this.length && (n = this.length), t.length - r < n - e && (n = t.length - r + e); | |
| var i = n - e; | |
| return this === t && "function" == typeof Uint8Array.prototype.copyWithin ? this.copyWithin(r, e, n) : Uint8Array.prototype.set.call(t, this.subarray(e, n), r), | |
| i; | |
| }, f.prototype.fill = function(t, r, e, n) { | |
| if ("string" == typeof t) { | |
| if ("string" == typeof r ? (n = r, r = 0, e = this.length) : "string" == typeof e && (n = e, | |
| e = this.length), void 0 !== n && "string" != typeof n) throw new TypeError("encoding must be a string"); | |
| if ("string" == typeof n && !f.isEncoding(n)) throw new TypeError("Unknown encoding: " + n); | |
| if (1 === t.length) { | |
| var i = t.charCodeAt(0); | |
| ("utf8" === n && i < 128 || "latin1" === n) && (t = i); | |
| } | |
| } else "number" == typeof t ? t &= 255 : "boolean" == typeof t && (t = Number(t)); | |
| if (r < 0 || this.length < r || this.length < e) throw new RangeError("Out of range index"); | |
| if (e <= r) return this; | |
| var o; | |
| if (r >>>= 0, e = void 0 === e ? this.length : e >>> 0, t || (t = 0), "number" == typeof t) for (o = r; o < e; ++o) this[o] = t; else { | |
| var u = f.isBuffer(t) ? t : f.from(t, n), s = u.length; | |
| if (0 === s) throw new TypeError('The value "' + t + '" is invalid for argument "value"'); | |
| for (o = 0; o < e - r; ++o) this[o + r] = u[o % s]; | |
| } | |
| return this; | |
| }; | |
| var N = /[^+/0-9A-Za-z-_]/g; | |
| function Y(t) { | |
| if ((t = (t = t.split("=")[0]).trim().replace(N, "")).length < 2) return ""; | |
| for (;t.length % 4 != 0; ) t += "="; | |
| return t; | |
| } | |
| function q(t, r) { | |
| var e; | |
| r = r || 1 / 0; | |
| for (var n = t.length, i = null, o = [], f = 0; f < n; ++f) { | |
| if ((e = t.charCodeAt(f)) > 55295 && e < 57344) { | |
| if (!i) { | |
| if (e > 56319) { | |
| (r -= 3) > -1 && o.push(239, 191, 189); | |
| continue; | |
| } | |
| if (f + 1 === n) { | |
| (r -= 3) > -1 && o.push(239, 191, 189); | |
| continue; | |
| } | |
| i = e; | |
| continue; | |
| } | |
| if (e < 56320) { | |
| (r -= 3) > -1 && o.push(239, 191, 189), i = e; | |
| continue; | |
| } | |
| e = 65536 + (i - 55296 << 10 | e - 56320); | |
| } else i && (r -= 3) > -1 && o.push(239, 191, 189); | |
| if (i = null, e < 128) { | |
| if ((r -= 1) < 0) break; | |
| o.push(e); | |
| } else if (e < 2048) { | |
| if ((r -= 2) < 0) break; | |
| o.push(e >> 6 | 192, 63 & e | 128); | |
| } else if (e < 65536) { | |
| if ((r -= 3) < 0) break; | |
| o.push(e >> 12 | 224, e >> 6 & 63 | 128, 63 & e | 128); | |
| } else { | |
| if (!(e < 1114112)) throw new Error("Invalid code point"); | |
| if ((r -= 4) < 0) break; | |
| o.push(e >> 18 | 240, e >> 12 & 63 | 128, e >> 6 & 63 | 128, 63 & e | 128); | |
| } | |
| } | |
| return o; | |
| } | |
| function V(t) { | |
| for (var r = [], e = 0; e < t.length; ++e) r.push(255 & t.charCodeAt(e)); | |
| return r; | |
| } | |
| function W(t, r) { | |
| for (var e, n, i, o = [], f = 0; f < t.length && !((r -= 2) < 0); ++f) n = (e = t.charCodeAt(f)) >> 8, | |
| i = e % 256, o.push(i), o.push(n); | |
| return o; | |
| } | |
| function X(r) { | |
| return t.toByteArray(Y(r)); | |
| } | |
| function J(t, r, e, n) { | |
| for (var i = 0; i < n && !(i + e >= r.length || i >= t.length); ++i) r[i + e] = t[i]; | |
| return i; | |
| } | |
| function Z(t, r) { | |
| return t instanceof r || null != t && null != t.constructor && null != t.constructor.name && t.constructor.name === r.name; | |
| } | |
| function $(t) { | |
| return t != t; | |
| } | |
| var G = function() { | |
| for (var t = "0123456789abcdef", r = new Array(256), e = 0; e < 16; ++e) for (var n = 16 * e, i = 0; i < 16; ++i) r[n + i] = t[e] + t[i]; | |
| return r; | |
| }(); | |
| },{"base64-js":1,"ieee754":6}],5:[function(require,module,exports){ | |
| const e = require("events"), r = module.exports = {}; | |
| function n() {} | |
| r.nextTick = Script.nextTick, r.title = "Frida", r.browser = !0, r.env = {}, r.argv = [], | |
| r.version = "", r.versions = {}, r.EventEmitter = e, r.on = n, r.addListener = n, | |
| r.once = n, r.off = n, r.removeListener = n, r.removeAllListeners = n, r.emit = n, | |
| r.binding = function(e) { | |
| throw new Error("process.binding is not supported"); | |
| }, r.cwd = function() { | |
| return "/"; | |
| }, r.chdir = function(e) { | |
| throw new Error("process.chdir is not supported"); | |
| }, r.umask = function() { | |
| return 0; | |
| }; | |
| },{"events":2}],6:[function(require,module,exports){ | |
| /*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */ | |
| exports.read = function(a, o, t, r, h) { | |
| var M, p, w = 8 * h - r - 1, f = (1 << w) - 1, e = f >> 1, i = -7, N = t ? h - 1 : 0, n = t ? -1 : 1, s = a[o + N]; | |
| for (N += n, M = s & (1 << -i) - 1, s >>= -i, i += w; i > 0; M = 256 * M + a[o + N], | |
| N += n, i -= 8) ; | |
| for (p = M & (1 << -i) - 1, M >>= -i, i += r; i > 0; p = 256 * p + a[o + N], N += n, | |
| i -= 8) ; | |
| if (0 === M) M = 1 - e; else { | |
| if (M === f) return p ? NaN : 1 / 0 * (s ? -1 : 1); | |
| p += Math.pow(2, r), M -= e; | |
| } | |
| return (s ? -1 : 1) * p * Math.pow(2, M - r); | |
| }, exports.write = function(a, o, t, r, h, M) { | |
| var p, w, f, e = 8 * M - h - 1, i = (1 << e) - 1, N = i >> 1, n = 23 === h ? Math.pow(2, -24) - Math.pow(2, -77) : 0, s = r ? 0 : M - 1, u = r ? 1 : -1, l = o < 0 || 0 === o && 1 / o < 0 ? 1 : 0; | |
| for (o = Math.abs(o), isNaN(o) || o === 1 / 0 ? (w = isNaN(o) ? 1 : 0, p = i) : (p = Math.floor(Math.log(o) / Math.LN2), | |
| o * (f = Math.pow(2, -p)) < 1 && (p--, f *= 2), (o += p + N >= 1 ? n / f : n * Math.pow(2, 1 - N)) * f >= 2 && (p++, | |
| f /= 2), p + N >= i ? (w = 0, p = i) : p + N >= 1 ? (w = (o * f - 1) * Math.pow(2, h), | |
| p += N) : (w = o * Math.pow(2, N - 1) * Math.pow(2, h), p = 0)); h >= 8; a[t + s] = 255 & w, | |
| s += u, w /= 256, h -= 8) ; | |
| for (p = p << h | w, e += h; e > 0; a[t + s] = 255 & p, s += u, p /= 256, e -= 8) ; | |
| a[t + s - u] |= 128 * l; | |
| }; | |
| },{}],7:[function(require,module,exports){ | |
| (function (process){(function (){ | |
| "use strict"; | |
| function e(e) { | |
| if ("string" != typeof e) throw new TypeError("Path must be a string. Received " + JSON.stringify(e)); | |
| } | |
| function r(e, r) { | |
| for (var t, n = "", i = 0, l = -1, o = 0, a = 0; a <= e.length; ++a) { | |
| if (a < e.length) t = e.charCodeAt(a); else { | |
| if (47 === t) break; | |
| t = 47; | |
| } | |
| if (47 === t) { | |
| if (l === a - 1 || 1 === o) ; else if (l !== a - 1 && 2 === o) { | |
| if (n.length < 2 || 2 !== i || 46 !== n.charCodeAt(n.length - 1) || 46 !== n.charCodeAt(n.length - 2)) if (n.length > 2) { | |
| var h = n.lastIndexOf("/"); | |
| if (h !== n.length - 1) { | |
| -1 === h ? (n = "", i = 0) : i = (n = n.slice(0, h)).length - 1 - n.lastIndexOf("/"), | |
| l = a, o = 0; | |
| continue; | |
| } | |
| } else if (2 === n.length || 1 === n.length) { | |
| n = "", i = 0, l = a, o = 0; | |
| continue; | |
| } | |
| r && (n.length > 0 ? n += "/.." : n = "..", i = 2); | |
| } else n.length > 0 ? n += "/" + e.slice(l + 1, a) : n = e.slice(l + 1, a), i = a - l - 1; | |
| l = a, o = 0; | |
| } else 46 === t && -1 !== o ? ++o : o = -1; | |
| } | |
| return n; | |
| } | |
| function t(e, r) { | |
| var t = r.dir || r.root, n = r.base || (r.name || "") + (r.ext || ""); | |
| return t ? t === r.root ? t + n : t + e + n : n; | |
| } | |
| var n = { | |
| resolve: function() { | |
| for (var t, n = "", i = !1, l = arguments.length - 1; l >= -1 && !i; l--) { | |
| var o; | |
| l >= 0 ? o = arguments[l] : (void 0 === t && (t = process.cwd()), o = t), e(o), | |
| 0 !== o.length && (n = o + "/" + n, i = 47 === o.charCodeAt(0)); | |
| } | |
| return n = r(n, !i), i ? n.length > 0 ? "/" + n : "/" : n.length > 0 ? n : "."; | |
| }, | |
| normalize: function(t) { | |
| if (e(t), 0 === t.length) return "."; | |
| var n = 47 === t.charCodeAt(0), i = 47 === t.charCodeAt(t.length - 1); | |
| return 0 !== (t = r(t, !n)).length || n || (t = "."), t.length > 0 && i && (t += "/"), | |
| n ? "/" + t : t; | |
| }, | |
| isAbsolute: function(r) { | |
| return e(r), r.length > 0 && 47 === r.charCodeAt(0); | |
| }, | |
| join: function() { | |
| if (0 === arguments.length) return "."; | |
| for (var r, t = 0; t < arguments.length; ++t) { | |
| var i = arguments[t]; | |
| e(i), i.length > 0 && (void 0 === r ? r = i : r += "/" + i); | |
| } | |
| return void 0 === r ? "." : n.normalize(r); | |
| }, | |
| relative: function(r, t) { | |
| if (e(r), e(t), r === t) return ""; | |
| if ((r = n.resolve(r)) === (t = n.resolve(t))) return ""; | |
| for (var i = 1; i < r.length && 47 === r.charCodeAt(i); ++i) ; | |
| for (var l = r.length, o = l - i, a = 1; a < t.length && 47 === t.charCodeAt(a); ++a) ; | |
| for (var h = t.length - a, f = o < h ? o : h, c = -1, s = 0; s <= f; ++s) { | |
| if (s === f) { | |
| if (h > f) { | |
| if (47 === t.charCodeAt(a + s)) return t.slice(a + s + 1); | |
| if (0 === s) return t.slice(a + s); | |
| } else o > f && (47 === r.charCodeAt(i + s) ? c = s : 0 === s && (c = 0)); | |
| break; | |
| } | |
| var g = r.charCodeAt(i + s); | |
| if (g !== t.charCodeAt(a + s)) break; | |
| 47 === g && (c = s); | |
| } | |
| var u = ""; | |
| for (s = i + c + 1; s <= l; ++s) s !== l && 47 !== r.charCodeAt(s) || (0 === u.length ? u += ".." : u += "/.."); | |
| return u.length > 0 ? u + t.slice(a + c) : (a += c, 47 === t.charCodeAt(a) && ++a, | |
| t.slice(a)); | |
| }, | |
| _makeLong: function(e) { | |
| return e; | |
| }, | |
| dirname: function(r) { | |
| if (e(r), 0 === r.length) return "."; | |
| for (var t = r.charCodeAt(0), n = 47 === t, i = -1, l = !0, o = r.length - 1; o >= 1; --o) if (47 === (t = r.charCodeAt(o))) { | |
| if (!l) { | |
| i = o; | |
| break; | |
| } | |
| } else l = !1; | |
| return -1 === i ? n ? "/" : "." : n && 1 === i ? "//" : r.slice(0, i); | |
| }, | |
| basename: function(r, t) { | |
| if (void 0 !== t && "string" != typeof t) throw new TypeError('"ext" argument must be a string'); | |
| e(r); | |
| var n, i = 0, l = -1, o = !0; | |
| if (void 0 !== t && t.length > 0 && t.length <= r.length) { | |
| if (t.length === r.length && t === r) return ""; | |
| var a = t.length - 1, h = -1; | |
| for (n = r.length - 1; n >= 0; --n) { | |
| var f = r.charCodeAt(n); | |
| if (47 === f) { | |
| if (!o) { | |
| i = n + 1; | |
| break; | |
| } | |
| } else -1 === h && (o = !1, h = n + 1), a >= 0 && (f === t.charCodeAt(a) ? -1 == --a && (l = n) : (a = -1, | |
| l = h)); | |
| } | |
| return i === l ? l = h : -1 === l && (l = r.length), r.slice(i, l); | |
| } | |
| for (n = r.length - 1; n >= 0; --n) if (47 === r.charCodeAt(n)) { | |
| if (!o) { | |
| i = n + 1; | |
| break; | |
| } | |
| } else -1 === l && (o = !1, l = n + 1); | |
| return -1 === l ? "" : r.slice(i, l); | |
| }, | |
| extname: function(r) { | |
| e(r); | |
| for (var t = -1, n = 0, i = -1, l = !0, o = 0, a = r.length - 1; a >= 0; --a) { | |
| var h = r.charCodeAt(a); | |
| if (47 !== h) -1 === i && (l = !1, i = a + 1), 46 === h ? -1 === t ? t = a : 1 !== o && (o = 1) : -1 !== t && (o = -1); else if (!l) { | |
| n = a + 1; | |
| break; | |
| } | |
| } | |
| return -1 === t || -1 === i || 0 === o || 1 === o && t === i - 1 && t === n + 1 ? "" : r.slice(t, i); | |
| }, | |
| format: function(e) { | |
| if (null === e || "object" != typeof e) throw new TypeError('The "pathObject" argument must be of type Object. Received type ' + typeof e); | |
| return t("/", e); | |
| }, | |
| parse: function(r) { | |
| e(r); | |
| var t = { | |
| root: "", | |
| dir: "", | |
| base: "", | |
| ext: "", | |
| name: "" | |
| }; | |
| if (0 === r.length) return t; | |
| var n, i = r.charCodeAt(0), l = 47 === i; | |
| l ? (t.root = "/", n = 1) : n = 0; | |
| for (var o = -1, a = 0, h = -1, f = !0, c = r.length - 1, s = 0; c >= n; --c) if (47 !== (i = r.charCodeAt(c))) -1 === h && (f = !1, | |
| h = c + 1), 46 === i ? -1 === o ? o = c : 1 !== s && (s = 1) : -1 !== o && (s = -1); else if (!f) { | |
| a = c + 1; | |
| break; | |
| } | |
| return -1 === o || -1 === h || 0 === s || 1 === s && o === h - 1 && o === a + 1 ? -1 !== h && (t.base = t.name = 0 === a && l ? r.slice(1, h) : r.slice(a, h)) : (0 === a && l ? (t.name = r.slice(1, o), | |
| t.base = r.slice(1, h)) : (t.name = r.slice(a, o), t.base = r.slice(a, h)), t.ext = r.slice(o, h)), | |
| a > 0 ? t.dir = r.slice(0, a - 1) : l && (t.dir = "/"), t; | |
| }, | |
| sep: "/", | |
| delimiter: ":", | |
| win32: null, | |
| posix: null | |
| }; | |
| n.posix = n, module.exports = n; | |
| }).call(this)}).call(this,require('_process')) | |
| },{"_process":5}],8:[function(require,module,exports){ | |
| module.exports={ | |
| "name": "r2frida-agent", | |
| "version": "5.4.4", | |
| "description": "Agent for frida:// io plugin", | |
| "private": true, | |
| "main": "src/agent/index.js", | |
| "scripts": { | |
| "lint": "semistandard src/agent/*.js", | |
| "indent": "semistandard --fix src/agent/*.js", | |
| "prepare": "npm run build", | |
| "build": "frida-compile src/agent -Sco src/_agent.js -c", | |
| "watch": "frida-compile src/agent -Sco src/_agent.js -w" | |
| }, | |
| "license": "LGPL-3.0", | |
| "dependencies": { | |
| "frida-compile": "10.2.4" | |
| }, | |
| "engines": { | |
| "node": ">=12" | |
| }, | |
| "devDependencies": { | |
| "semistandard": "16.0.1" | |
| }, | |
| "semistandard": { | |
| "globals": [ | |
| "DebugSymbol", | |
| "File", | |
| "Frida", | |
| "hexdump", | |
| "Instruction", | |
| "Interceptor", | |
| "Java", | |
| "Memory", | |
| "Module", | |
| "NativeCallback", | |
| "NativeFunction", | |
| "NativePointer", | |
| "NULL", | |
| "ObjC", | |
| "Process", | |
| "recv", | |
| "Script", | |
| "Socket", | |
| "Stalker", | |
| "Thread", | |
| "ptr", | |
| "rpc", | |
| "send", | |
| "uint64" | |
| ] | |
| } | |
| } | |
| },{}],9:[function(require,module,exports){ | |
| "use strict"; | |
| const e = { | |
| "java.wait": !1, | |
| "patch.code": !0, | |
| "search.in": "perm:r--", | |
| "search.quiet": !1, | |
| "stalker.event": "compile", | |
| "stalker.timeout": 300, | |
| "stalker.in": "raw", | |
| "hook.backtrace": !0, | |
| "hook.verbose": !0, | |
| "hook.logs": !0, | |
| "hook.output": "simple", | |
| "hook.usecmd": "", | |
| "file.log": "", | |
| "symbols.module": "", | |
| "symbols.unredact": "darwin" === Process.platform | |
| }, t = { | |
| "java.wait": o, | |
| "search.in": r, | |
| "stalker.event": s, | |
| "stalker.timeout": l, | |
| "stalker.in": b, | |
| "hook.backtrace": p, | |
| "hook.verbose": d, | |
| "hook.usecmd": h, | |
| "hook.logs": f, | |
| "hook.output": m, | |
| "file.log": u, | |
| "symbols.module": g, | |
| "symbols.unredact": k | |
| }, n = { | |
| "java.wait": w, | |
| "search.in": a, | |
| "stalker.event": i, | |
| "stalker.timeout": c, | |
| "stalker.in": y, | |
| "hook.backtrace": w, | |
| "hook.verbose": w, | |
| "hook.logs": w, | |
| "hook.output": v, | |
| "file.log": v, | |
| "symbols.module": v, | |
| "symbols.unredact": w | |
| }; | |
| function o() { | |
| return "Wait for Java classloader to be ready (boolean)"; | |
| } | |
| function r() { | |
| return "Specify which memory ranges to search in, possible values:\n\n perm:--- filter by permissions (default: 'perm:r--')\n current search the range containing current offset\n heap search inside the heap allocated regions\n path:pattern search ranges mapping paths containing 'pattern'\n "; | |
| } | |
| function a(e) { | |
| if ("heap" === e) return !0; | |
| const t = e.split(":"), [n, o] = t; | |
| if (void 0 === o) return "current" === n && 1 === t.length; | |
| if ("perm" === n) { | |
| const e = o.split(""); | |
| if (3 !== e.length || t.length > 2) return !1; | |
| const [n, r, a] = e; | |
| return !("r" !== n && "-" !== n || "w" !== r && "-" !== r || "x" !== a && "-" !== a); | |
| } | |
| return "path" === n; | |
| } | |
| function s() { | |
| return "Specify the event to use when stalking, possible values:\n\n call trace calls\n ret trace returns\n exec trace every instruction\n block trace basic block execution (every time)\n compile trace basic blocks once (this is the default)\n "; | |
| } | |
| function i(e) { | |
| return -1 !== [ "call", "ret", "exec", "block", "compile" ].indexOf(e); | |
| } | |
| function l() { | |
| return "Time after which the stalker gives up (in seconds). Defaults to 5 minutes,\n set to 0 to disable."; | |
| } | |
| function c(e) { | |
| return e >= 0; | |
| } | |
| function u() { | |
| return "Set filename to save all the tracing logs generated by :dt\n\n string specify file path of the log file\n "; | |
| } | |
| function h() { | |
| return "Use the given command when registering a new trace (dt) or injection (di) to be executed when hits\n\n '' | 'r2cmd' the r2 command will be executed from the host side and r2frida commands can be also recursively called\n "; | |
| } | |
| function d() { | |
| return "Show trace messages to the console. They are also logged in :dtl\n\n true | false to enable or disable the option\n "; | |
| } | |
| function f() { | |
| return "Save hook trace logs internally in the agent. Use :dtl to list them\n\n true | false to enable or disable the option (enabled by default)\n "; | |
| } | |
| function m() { | |
| return "Choose output format.\n\n simple | json (simple by default)\n "; | |
| } | |
| function p() { | |
| return "Append the backtrace on each trace hook registered with :dt commands\n\n true | false to enable or disable the option\n "; | |
| } | |
| function b() { | |
| return "Restrict stalker results based on where the event has originated:\n\n raw stalk everywhere (the default)\n app stalk only in the app module\n modules stalk in app module and all linked libraries\n "; | |
| } | |
| function g() { | |
| return "When set ignore offset to tell frida which module to use for symbols:\n\n See :dm command to get all maps and :dmm for modules\n "; | |
| } | |
| function k() { | |
| return 'Try to get symbol names from debug symbols when they\'re "redacted":\n\n true try to unredact (the default)\n false do not attempt to unredact\n '; | |
| } | |
| function y(e) { | |
| return -1 !== [ "raw", "app", "modules" ].indexOf(e); | |
| } | |
| function v(e) { | |
| return "string" == typeof e; | |
| } | |
| function w(e) { | |
| return x(e) || S(e); | |
| } | |
| function x(e) { | |
| return !0 === e || 1 === e || "1" === e || /(true)/i.test(e); | |
| } | |
| function S(e) { | |
| return !1 === e || 0 === e || "0" === e || /(false)/i.test(e); | |
| } | |
| function j() { | |
| return Object.keys(e).map((t => "e " + t + "=" + e[t])).join("\n"); | |
| } | |
| function O(t, o) { | |
| if (void 0 !== n[t] && !n[t](o)) return console.error(`Invalid value for ${t}`), | |
| ""; | |
| e[t] = o; | |
| } | |
| function T(e) { | |
| return void 0 !== t[e] ? t[e]() : (console.error(`no help for ${e}`), ""); | |
| } | |
| module.exports = { | |
| values: e, | |
| set: O, | |
| get: t => e[t], | |
| getBoolean: t => x(e[t]), | |
| getString: t => e[t] ? "" + e[t] : "", | |
| asR2Script: j, | |
| helpFor: T | |
| }; | |
| },{}],10:[function(require,module,exports){ | |
| "use strict"; | |
| const {normalize: t} = require("path"), {platform: e, pointerSize: n} = Process, {toByteArray: i} = require("base64-js"); | |
| function r(e) { | |
| if (e.startsWith("base64:")) try { | |
| const t = i(e.slice(7)); | |
| e = String.fromCharCode.apply(null, t); | |
| } catch (t) {} | |
| return t(e); | |
| } | |
| module.exports = { | |
| ls: h, | |
| cat: m, | |
| open: S, | |
| transformVirtualPath: g, | |
| exist: y | |
| }; | |
| let s = null; | |
| const o = { | |
| "linux-32": { | |
| d_name: [ 11, "Utf8String" ], | |
| d_type: [ 10, "U8" ] | |
| }, | |
| "linux-64": { | |
| d_name: [ 19, "Utf8String" ], | |
| d_type: [ 18, "U8" ] | |
| }, | |
| "darwin-32": { | |
| d_name: [ 21, "Utf8String" ], | |
| d_type: [ 20, "U8" ] | |
| }, | |
| "darwin-64": { | |
| d_name: [ [ 8, "Utf8String" ], [ 21, "Utf8String" ] ], | |
| d_type: [ [ 6, "U8" ], [ 20, "U8" ] ] | |
| } | |
| }, a = { | |
| "linux-32": { | |
| size: [ 44, "S32" ] | |
| }, | |
| "linux-64": { | |
| size: [ 48, "S64" ] | |
| }, | |
| "darwin-32": { | |
| size: [ 60, "S64" ] | |
| }, | |
| "darwin-64": { | |
| size: [ 96, "S64" ] | |
| } | |
| }, l = { | |
| "linux-64": { | |
| size: [ 40, "S64" ] | |
| } | |
| }, u = 512; | |
| let c = null; | |
| const p = o[`${e}-${8 * n}`], f = a[`${e}-${8 * n}`] || null, d = l[`${e}-${8 * n}`] || null; | |
| function h(t) { | |
| return null === s && (s = new _), s.ls(r(t)); | |
| } | |
| function m(t, e, n, i) { | |
| return null === s && (s = new _), s.cat(r(t), e, n, i); | |
| } | |
| function S(t) { | |
| return null === s && (s = new _), s.open(r(t)); | |
| } | |
| function g(e) { | |
| return null === s && (s = new _), s.transformVirtualPath(t(e)); | |
| } | |
| function y(t) { | |
| return null === s && (s = new _), s.exist(r(t)); | |
| } | |
| class _ { | |
| constructor() { | |
| this._api = null, this._entryTypes = null, this._excludeSet = new Set([ ".", ".." ]), | |
| this._transform = null; | |
| } | |
| exist(t) { | |
| return this.api.getFileSize(t) >= 0; | |
| } | |
| ls(t) { | |
| const e = [], n = this.transform.toActual(t); | |
| if (null !== n) { | |
| const t = Memory.alloc(Process.pageSize), i = Memory.alloc(Process.pointerSize), r = this.api.opendir(n); | |
| if (null === r) return ""; | |
| let s; | |
| for (;null !== (s = this.api.readdir(r, t, i)); ) this._excludeSet.has(s.name) || e.push([ this._getEntryType(s.type), s.name ].join(" ")); | |
| this.api.closedir(r); | |
| } else { | |
| const n = this.transform.getVirtualDir(t); | |
| for (const t of n) e.push(`d ${t.name}`); | |
| } | |
| return e.join("\n"); | |
| } | |
| cat(t, e, n, i) { | |
| const r = this.transform.toActual(t); | |
| if (null !== r) { | |
| const t = this.api.getFileSize(r); | |
| if (t < 0) return console.log(`ERROR: cannot stat ${r}`), ""; | |
| if (i = parseInt(i), n = parseInt(n), (i = null === i ? t : i) < 0) return console.log(`ERROR: invalid size ${i}`), | |
| ""; | |
| let s = !1; | |
| if (0 === i && (console.log("weak"), s = !0, i = 32768), i > 524288) return console.log("ERROR: file chunk is too big. (" + i + " bytes)"), | |
| ""; | |
| const o = Memory.alloc(i), a = this.api.fopen(r, "rb"); | |
| n > 0 && this.api.fseek(a, n, 0); | |
| const l = this.api.fread(o, 1, i, a); | |
| if (!s && l !== i) return console.log(`ERROR: reading ${r} ${l} vs ${i}`), this.api.fclose(a), | |
| ""; | |
| this.api.fclose(a); | |
| return k(o, i, "*" === e ? "hex" : "utf8"); | |
| } | |
| return console.log("ERROR: no path " + t), ""; | |
| } | |
| open(t) { | |
| const e = this.transform.toActual(t); | |
| if (null !== e) { | |
| const t = this.api.getFileSize(e); | |
| return t < 0 ? (console.log(`ERROR: cannot stat ${e}`), "") : `${t}`; | |
| } | |
| return ""; | |
| } | |
| transformVirtualPath(t) { | |
| for (const e of this.transform._mappedPrefixes) { | |
| const n = t.indexOf(e); | |
| if (n >= 0) { | |
| t = t.slice(n); | |
| break; | |
| } | |
| } | |
| const e = this.transform.toActual(t); | |
| return null !== e ? e : t; | |
| } | |
| get transform() { | |
| return null === this._transform && (A() ? this._transform = new v : this._transform = new N), | |
| this._transform; | |
| } | |
| get api() { | |
| return null === this._api && (this._api = new b), this._api; | |
| } | |
| _getEntryType(t) { | |
| null === this._entryTypes && (this._entryTypes = { | |
| 0: "?", | |
| 1: "p", | |
| 2: "c", | |
| 4: "d", | |
| 6: "b", | |
| 8: "f", | |
| 10: "l", | |
| 12: "s", | |
| 14: "w" | |
| }); | |
| const e = this._entryTypes[t]; | |
| return void 0 === e ? "?" : e; | |
| } | |
| } | |
| class w { | |
| constructor() { | |
| this._virtualDirs = {}, this._mappedPrefixes = []; | |
| } | |
| toActual(t) { | |
| for (const e of this._mappedPrefixes) if (0 === t.indexOf(e)) { | |
| const n = this._virtualDirs[e]; | |
| return t.replace(e, n); | |
| } | |
| return null; | |
| } | |
| getVirtualDir(t) { | |
| const e = this._virtualDirs[t]; | |
| return void 0 === e ? [] : e; | |
| } | |
| } | |
| class N extends w { | |
| toActual(t) { | |
| return t; | |
| } | |
| } | |
| class x { | |
| constructor(t, e = null) { | |
| this.name = t, this.actualPath = e, this.subEnts = []; | |
| } | |
| addSub(t) { | |
| this.subEnts.push(t); | |
| } | |
| hasActualPath() { | |
| return null !== this.actualPath; | |
| } | |
| } | |
| class v extends w { | |
| constructor() { | |
| super(), this._api = null, this._fillVirtualDirs(); | |
| } | |
| _fillVirtualDirs() { | |
| const t = this.api.NSAutoreleasePool.alloc().init(), e = new ObjC.Object(this.api.NSHomeDirectory()).toString(), n = this.api.NSBundle.mainBundle().bundlePath().toString(), i = new x("/"); | |
| i.addSub(new x("AppHome", e)), i.addSub(new x("AppBundle", n)); | |
| const r = this._getAppGroupNames(); | |
| if (r.length > 0) { | |
| const t = this.api.NSFileManager.defaultManager(), e = new x("AppGroups"); | |
| i.addSub(e); | |
| for (const n of r) { | |
| const i = t.containerURLForSecurityApplicationGroupIdentifier_(n); | |
| null !== i && e.addSub(new x(n, i.path().toString())); | |
| } | |
| } | |
| i.addSub(new x("Device", "/")), M(this._virtualDirs, i), this._mappedPrefixes = Object.keys(this._virtualDirs).filter((t => "string" == typeof this._virtualDirs[t])).sort(((t, e) => t.length - e.length)), | |
| t.release(); | |
| } | |
| _getAppGroupNames() { | |
| const t = this.api.SecTaskCreateFromSelf(NULL); | |
| if (t.isNull()) return []; | |
| const e = this.api.NSString.stringWithString_("com.apple.security.application-groups"), n = this.api.SecTaskCopyValueForEntitlement(t, e, NULL); | |
| if (n.isNull()) return this.api.CFRelease(t), []; | |
| const i = C(new ObjC.Object(n).autorelease(), (t => t.toString())); | |
| return this.api.CFRelease(t), i; | |
| } | |
| get api() { | |
| return null === this._api && (this._api = { | |
| NSAutoreleasePool: ObjC.classes.NSAutoreleasePool, | |
| NSBundle: ObjC.classes.NSBundle, | |
| NSFileManager: ObjC.classes.NSFileManager, | |
| NSHomeDirectory: new NativeFunction(Module.findExportByName(null, "NSHomeDirectory"), "pointer", []), | |
| NSString: ObjC.classes.NSString, | |
| SecTaskCreateFromSelf: new NativeFunction(Module.findExportByName(null, "SecTaskCreateFromSelf"), "pointer", [ "pointer" ]), | |
| SecTaskCopyValueForEntitlement: new NativeFunction(Module.findExportByName(null, "SecTaskCopyValueForEntitlement"), "pointer", [ "pointer", "pointer", "pointer" ]), | |
| CFRelease: new NativeFunction(Module.findExportByName(null, "CFRelease"), "void", [ "pointer" ]) | |
| }), this._api; | |
| } | |
| } | |
| class b { | |
| constructor() { | |
| this._api = null; | |
| } | |
| get api() { | |
| if (null === this._api) { | |
| const t = E([ "opendir", "readdir_r", "closedir", "fopen", "fclose", "fread", "fseek" ]); | |
| if (!(0 === Object.keys(t).filter((e => null === t[e])).length)) throw new Error("ERROR: is this a POSIX system?"); | |
| this._api = { | |
| opendir: new NativeFunction(t.opendir, "pointer", [ "pointer" ]), | |
| readdir: new NativeFunction(t.readdir_r, "int", [ "pointer", "pointer", "pointer" ]), | |
| closedir: new NativeFunction(t.closedir, "int", [ "pointer" ]), | |
| fopen: new NativeFunction(t.fopen, "pointer", [ "pointer", "pointer" ]), | |
| fclose: new NativeFunction(t.fclose, "int", [ "pointer" ]), | |
| fread: new NativeFunction(t.fread, "int", [ "pointer", "int", "int", "pointer" ]), | |
| fseek: new NativeFunction(t.fseek, "int", [ "pointer", "int", "int" ]), | |
| stat: null, | |
| statx: null | |
| }; | |
| const e = E([ "stat", "stat64", "statx" ]), n = e.stat64 || e.stat, {statx: i} = e; | |
| null !== n ? this._api.stat = new NativeFunction(n, "int", [ "pointer", "pointer" ]) : null !== i && (this._api.statx = new NativeFunction(i, "int", [ "int", "pointer", "int", "int", "pointer" ])); | |
| } | |
| return this._api; | |
| } | |
| opendir(t) { | |
| const e = this.api.opendir(Memory.allocUtf8String(t)); | |
| return e.isNull() ? null : e; | |
| } | |
| readdir(t, e, n) { | |
| this.api.readdir(t, e, n); | |
| const i = n.readPointer(); | |
| return i.isNull() ? null : new F(i); | |
| } | |
| closedir(t) { | |
| return this.api.closedir(t); | |
| } | |
| fopen(t, e) { | |
| return this.api.fopen(Memory.allocUtf8String(t), Memory.allocUtf8String(e)); | |
| } | |
| fclose(t) { | |
| return this.api.fclose(t); | |
| } | |
| fread(t, e, n, i) { | |
| return this.api.fread(t, e, n, i); | |
| } | |
| fseek(t, e, n) { | |
| return this.api.fseek(t, e, n); | |
| } | |
| getFileSize(t) { | |
| const e = Memory.alloc(Process.pageSize), n = Memory.allocUtf8String(t); | |
| if (null !== this.api.stat) { | |
| return -1 === this.api.stat(n, e) ? -1 : R(e, "size"); | |
| } | |
| if (this.api.statx) { | |
| return -1 === this.api.statx(0, n, 0, 512, e) ? -1 : P(e, "size"); | |
| } | |
| } | |
| } | |
| class F { | |
| constructor(t) { | |
| this.type = O(t, "d_type"), this.name = O(t, "d_name"); | |
| } | |
| } | |
| function O(t, n) { | |
| let i = p[n]; | |
| "darwin" === e && (i = U(t) ? i[1] : i[0]); | |
| const [r, s] = i, o = ("string" == typeof s ? Memory["read" + s] : s)(t.add(r)); | |
| return o instanceof Int64 || o instanceof UInt64 ? o.valueOf() : o; | |
| } | |
| function R(t, e) { | |
| const n = f[e]; | |
| if (void 0 === n) return; | |
| const [i, r] = n, s = ("string" == typeof r ? Memory["read" + r] : r)(t.add(i)); | |
| return s instanceof Int64 || s instanceof UInt64 ? s.valueOf() : s; | |
| } | |
| function P(t, e) { | |
| const n = d[e]; | |
| if (void 0 === n) return; | |
| const [i, r] = n, s = ("string" == typeof r ? Memory["read" + r] : r)(t.add(i)); | |
| return s instanceof Int64 || s instanceof UInt64 ? s.valueOf() : s; | |
| } | |
| function U(t) { | |
| if (null !== c) return c; | |
| const e = t.add(4).readU16(), n = t.add(7).readU8(); | |
| return c = (8 + n + 3 & -4) !== e, c; | |
| } | |
| function E(t) { | |
| return t.reduce(((t, e) => (t[e] = Module.findExportByName(null, e), t)), {}); | |
| } | |
| function M(e, n, i = "") { | |
| const r = t(`${i}/${n.name}`); | |
| if (n.hasActualPath()) e[r] = n.actualPath; else { | |
| e[r] = n.subEnts; | |
| for (const t of n.subEnts) M(e, t, r); | |
| } | |
| } | |
| function C(t, e) { | |
| const n = [], i = t.count().valueOf(); | |
| for (let r = 0; r !== i; r++) n.push(e(t.objectAtIndex_(r))); | |
| return n; | |
| } | |
| function A() { | |
| return "darwin" === e && 0 === Process.arch.indexOf("arm") && ObjC.available; | |
| } | |
| function k(t, e, n) { | |
| if ("hex" !== n) return Memory.readCString(t); | |
| const i = []; | |
| for (let n = 0; n < e; n++) { | |
| const e = Memory.readU8(t.add(n)).toString(16); | |
| e.length < 2 ? i.push(`0${e}`) : i.push(e); | |
| } | |
| return i.join(""); | |
| } | |
| },{"base64-js":1,"path":7}],11:[function(require,module,exports){ | |
| (function (process,global,Buffer){(function (){ | |
| "use strict"; | |
| const {stalkFunction: stalkFunction, stalkEverything: stalkEverything} = require("./stalker"), fs = require("./fs"), path = require("path"), config = require("./config"), io = require("./io"), isObjC = require("./isobjc"), strings = require("./strings"), utils = require("./utils"); | |
| let Gcwd = "/"; | |
| const SwiftAvailable = "darwin" === Process.platform && global.hasOwnProperty("Swift") && Swift.available, ObjCAvailable = "darwin" === Process.platform && ObjC && ObjC.available && ObjC.classes && void 0 !== ObjC.classes.NSString, NeedsSafeIo = "linux" === Process.platform && "arm" === Process.arch && 4 === Process.pointerSize, JavaAvailable = Java && Java.available, pointerSize = Process.pointerSize; | |
| let suspended = !1; | |
| const tracehooks = {}; | |
| let logs = [], traces = {}, breakpoints = {}; | |
| const allocPool = {}, pendingCmds = {}, pendingCmdSends = []; | |
| let sendingCommand = !1; | |
| const specialChars = "`${}~|;#@&<> ()"; | |
| function numEval(e) { | |
| return new Promise(((t, n) => { | |
| const r = DebugSymbol.fromName(e); | |
| if (r && r.name) return t(r.address); | |
| hostCmd("?v " + e).then((e => t(e.trim()))).catch(n); | |
| })); | |
| } | |
| function javaUse(e) { | |
| const t = Java.classFactory.loader; | |
| let n = null; | |
| return javaPerform((function() { | |
| for (const t of Java.enumerateClassLoadersSync()) try { | |
| Java.classFactory.loader = t, n = Java.use(e); | |
| break; | |
| } catch (e) {} | |
| })), Java.classFactory.loader = t, n; | |
| } | |
| function evalNum(e) { | |
| return new Promise(((t, n) => { | |
| numEval(e.join(" ")).then((e => { | |
| t(e); | |
| })); | |
| })); | |
| } | |
| function javaTraceExample() { | |
| javaPerform((function() { | |
| Java.use("java.lang.System").loadLibrary.implementation = function(e) { | |
| try { | |
| traceEmit("System.loadLibrary " + e); | |
| return Runtime.getRuntime().loadLibrary0(VMStack.getCallingClassLoader(), e); | |
| } catch (e) { | |
| console.error(e); | |
| } | |
| }; | |
| })); | |
| } | |
| const commandHandlers = { | |
| E: evalNum, | |
| "?e": echo, | |
| "?E": uiAlert, | |
| "/": search, | |
| "/i": searchInstances, | |
| "/ij": searchInstancesJson, | |
| "/j": searchJson, | |
| "/x": searchHex, | |
| "/xj": searchHexJson, | |
| "/w": searchWide, | |
| "/wj": searchWideJson, | |
| "/v1": searchValueImpl(1), | |
| "/v2": searchValueImpl(2), | |
| "/v4": searchValueImpl(4), | |
| "/v8": searchValueImpl(8), | |
| "/v1j": searchValueImplJson(1), | |
| "/v2j": searchValueImplJson(2), | |
| "/v4j": searchValueImplJson(4), | |
| "/v8j": searchValueImplJson(8), | |
| "?V": fridaVersion, | |
| i: dumpInfo, | |
| "i*": dumpInfoR2, | |
| ij: dumpInfoJson, | |
| e: evalConfig, | |
| "e*": evalConfigR2, | |
| "e/": evalConfigSearch, | |
| db: breakpoint, | |
| dbj: breakpointJson, | |
| "db-": breakpointUnset, | |
| dc: breakpointContinue, | |
| dcu: breakpointContinueUntil, | |
| dk: sendSignal, | |
| s: radareSeek, | |
| r: radareCommand, | |
| ie: listEntrypoint, | |
| ieq: listEntrypointQuiet, | |
| "ie*": listEntrypointR2, | |
| iej: listEntrypointJson, | |
| afs: analFunctionSignature, | |
| ii: listImports, | |
| "ii*": listImportsR2, | |
| iij: listImportsJson, | |
| il: listModules, | |
| "il.": listModulesHere, | |
| "il*": listModulesR2, | |
| ilq: listModulesQuiet, | |
| ilj: listModulesJson, | |
| ia: listAllHelp, | |
| iAs: listAllSymbols, | |
| iAsj: listAllSymbolsJson, | |
| "iAs*": listAllSymbolsR2, | |
| iAn: listAllClassesNatives, | |
| is: listSymbols, | |
| "is.": lookupSymbolHere, | |
| isj: listSymbolsJson, | |
| "is*": listSymbolsR2, | |
| ias: lookupSymbol, | |
| "ias*": lookupSymbolR2, | |
| iasj: lookupSymbolJson, | |
| isa: lookupSymbol, | |
| "isa*": lookupSymbolR2, | |
| isaj: lookupSymbolJson, | |
| isam: lookupSymbolMany, | |
| isamj: lookupSymbolManyJson, | |
| "isam*": lookupSymbolManyR2, | |
| iE: listExports, | |
| "iE.": lookupSymbolHere, | |
| iEj: listExportsJson, | |
| "iE*": listExportsR2, | |
| iaE: lookupExport, | |
| iaEj: lookupExportJson, | |
| "iaE*": lookupExportR2, | |
| iEa: lookupExport, | |
| "iEa*": lookupExportR2, | |
| iEaj: lookupExportJson, | |
| iAE: listAllExports, | |
| iAEj: listAllExportsJson, | |
| "iAE*": listAllExportsR2, | |
| init: initBasicInfoFromTarget, | |
| fD: lookupDebugInfo, | |
| fd: lookupAddress, | |
| "fd.": lookupAddress, | |
| "fd*": lookupAddressR2, | |
| fdj: lookupAddressJson, | |
| ic: listClasses, | |
| ich: listClassesHooks, | |
| icw: listClassesWhere, | |
| icv: listClassVariables, | |
| ics: listClassSuperMethods, | |
| ica: listClassesAllMethods, | |
| icn: listClassesNatives, | |
| icL: listClassesLoaders, | |
| icl: listClassesLoaded, | |
| iclj: listClassesLoadedJson, | |
| "ic*": listClassesR2, | |
| icj: listClassesJson, | |
| icm: listClassMethods, | |
| icmj: listClassMethodsJson, | |
| ip: listProtocols, | |
| ipj: listProtocolsJson, | |
| iz: listStrings, | |
| izj: listStringsJson, | |
| dd: listFileDescriptors, | |
| ddj: listFileDescriptorsJson, | |
| "dd-": closeFileDescriptors, | |
| dm: listMemoryRanges, | |
| "dm*": listMemoryRangesR2, | |
| dmj: listMemoryRangesJson, | |
| dmp: changeMemoryProtection, | |
| "dm.": listMemoryRangesHere, | |
| dmm: listMemoryMaps, | |
| "dmm*": listMemoryMapsR2, | |
| "dmm.": listMemoryMapsHere, | |
| dmh: listMallocRanges, | |
| "dmh*": listMallocRangesR2, | |
| dmhj: listMallocRangesJson, | |
| dmhm: listMallocMaps, | |
| dma: allocSize, | |
| dmas: allocString, | |
| dmaw: allocWstring, | |
| dmad: allocDup, | |
| dmal: listAllocs, | |
| "dma-": removeAlloc, | |
| dp: getPid, | |
| dxc: dxCall, | |
| dxo: dxObjc, | |
| dxs: dxSyscall, | |
| dpj: getPidJson, | |
| dpt: listThreads, | |
| dptj: listThreadsJson, | |
| dr: dumpRegisters, | |
| "dr*": dumpRegistersR2, | |
| drr: dumpRegistersRecursively, | |
| drp: dumpRegisterProfile, | |
| dr8: dumpRegisterArena, | |
| drj: dumpRegistersJson, | |
| env: getOrSetEnv, | |
| envj: getOrSetEnvJson, | |
| dl: dlopen, | |
| dlf: loadFrameworkBundle, | |
| "dlf-": unloadFrameworkBundle, | |
| dtf: traceFormat, | |
| dth: traceHook, | |
| t: types, | |
| "t*": typesR2, | |
| dt: trace, | |
| dtj: traceJson, | |
| dtq: traceQuiet, | |
| "dt*": traceR2, | |
| "dt.": traceHere, | |
| "dt-": clearTrace, | |
| "dt-*": clearAllTrace, | |
| dtr: traceRegs, | |
| dtl: traceLogDump, | |
| "dtl*": traceLogDumpR2, | |
| dtlq: traceLogDumpQuiet, | |
| dtlj: traceLogDumpJson, | |
| "dtl-": traceLogClear, | |
| "dtl-*": traceLogClearAll, | |
| dts: stalkTraceEverything, | |
| "dts?": stalkTraceEverythingHelp, | |
| dtsj: stalkTraceEverythingJson, | |
| "dts*": stalkTraceEverythingR2, | |
| dtsf: stalkTraceFunction, | |
| dtsfj: stalkTraceFunctionJson, | |
| "dtsf*": stalkTraceFunctionR2, | |
| di: interceptHelp, | |
| dif: interceptFunHelp, | |
| dis: interceptRetString, | |
| di0: interceptRet0, | |
| di1: interceptRet1, | |
| dii: interceptRetInt, | |
| "di-1": interceptRet_1, | |
| difs: interceptFunRetString, | |
| dif0: interceptFunRet0, | |
| dif1: interceptFunRet1, | |
| difi: interceptFunRetInt, | |
| "dif-1": interceptFunRet_1, | |
| pwd: getCwd, | |
| cd: chDir, | |
| cat: fsCat, | |
| ls: fsList, | |
| md: fsList, | |
| mg: fsGet, | |
| m: fsOpen, | |
| pd: disasmCode, | |
| px: printHexdump, | |
| x: printHexdump, | |
| eval: evalCode, | |
| chcon: changeSelinuxContext | |
| }; | |
| async function initBasicInfoFromTarget(e) { | |
| return "\ne dbg.backend = io\ne anal.autoname=true\ne cmd.fcn.new=aan\n.:ie*\n.:dmm*\n.:il*\nm /r2f io 0\ns entry0 2> /dev/null\n "; | |
| } | |
| function nameFromAddress(e) { | |
| const t = DebugSymbol.fromAddress(ptr(e)); | |
| if (t) return t.name; | |
| const n = Process.findModuleByAddress(e); | |
| if (null === n) return null; | |
| const r = Module.enumerateImports(n.name); | |
| for (const t of r) if (t.address.equals(e)) return t.name; | |
| const s = Module.enumerateExports(n.name); | |
| for (const t of s) if (t.address.equals(e)) return t.name; | |
| return e.toString(); | |
| } | |
| function allocSize(e) { | |
| const t = +e[0]; | |
| if (t > 0) { | |
| return _addAlloc(Memory.alloc(t)); | |
| } | |
| return 0; | |
| } | |
| function allocString(e) { | |
| const t = e.join(" "); | |
| if (t.length > 0) { | |
| return _addAlloc(Memory.allocUtf8String(t)); | |
| } | |
| throw new Error("Usage: dmas [string]"); | |
| } | |
| function allocWstring(e) { | |
| const t = e.join(" "); | |
| if (t.length > 0) { | |
| return _addAlloc(Memory.allocUtf16String(t)); | |
| } | |
| throw new Error("Usage: dmaw [string]"); | |
| } | |
| function allocDup(e) { | |
| if (e.length < 2) throw new Error("Missing argument"); | |
| const t = +e[0], n = +e[1]; | |
| if (t > 0 && n > 0) { | |
| return _addAlloc(Memory.dup(ptr(t), n)); | |
| } | |
| return 0; | |
| } | |
| function removeAlloc(e) { | |
| if (0 === e.length) _clearAllocs(); else for (const t of e) _delAlloc(t); | |
| return ""; | |
| } | |
| function listAllocs(e) { | |
| return Object.values(allocPool).sort().map((e => `${e}\t"${_filterPrintable(Memory.readByteArray(e, 60))}"`)).join("\n") + "\n"; | |
| } | |
| function _delAlloc(e) { | |
| delete allocPool[e]; | |
| } | |
| function _clearAllocs() { | |
| Object.keys(allocPool).forEach((e => delete allocPool[e])); | |
| } | |
| function _addAlloc(e) { | |
| const t = e.toString(); | |
| return e.isNull() || (allocPool[t] = e), t; | |
| } | |
| function resolveSyscallNumber(e) { | |
| const t = "arm64" === Process.arch; | |
| switch (e) { | |
| case "read": | |
| return t ? 3 : 33554435; | |
| case "write": | |
| return t ? 4 : 33554436; | |
| case "exit": | |
| return t ? 1 : 33554433; | |
| } | |
| return "" + e; | |
| } | |
| function dxSyscall(e) { | |
| if (0 === e.length) return "Usage dxs [syscallname] [args ...]"; | |
| return dxCall([ "syscall", "" + resolveSyscallNumber(e[0]), ...e.slice(1) ]); | |
| } | |
| function autoType(e) { | |
| const t = [], n = []; | |
| for (let r = 0; r < e.length; r++) if ("0x" === e[r].substring(0, 2)) t.push("pointer"), | |
| n.push(ptr(e[r])); else if ('"' === e[r][0]) { | |
| t.push("pointer"); | |
| const s = e[r].substring(1, e[r].length - 1), o = Memory.allocUtf8String(s.replace(/\\n/g, "\n")); | |
| n.push(o); | |
| } else if (e[r].endsWith("f")) t.push("float"), n.push(0 + e[r]); else if (e[r].endsWith("F")) t.push("double"), | |
| n.push(0 + e[r]); else if (+e[r] > 0 || "0" === e[r]) t.push("int"), n.push(+e[r]); else { | |
| t.push("pointer"); | |
| const s = Module.getExportByName(null, e[r]); | |
| n.push(s); | |
| } | |
| return [ t, n ]; | |
| } | |
| function dxObjc(e) { | |
| if (!ObjCAvailable) return "dxo requires the objc runtime to be available to work."; | |
| if (0 === e.length) return "Usage: dxo [klassname|instancepointer] [methodname] [args...]"; | |
| if (1 === e.length) return listClasses(e); | |
| let t = null; | |
| if (e[0].startsWith("0x")) t = new ObjC.Object(ptr(e[0])); else { | |
| const n = e[0]; | |
| if (!ObjC.classes[n]) return "Cannot find objc class " + n; | |
| const r = ObjC.chooseSync(ObjC.classes[n]); | |
| if (!r) return "Cannot find any instance for klass " + n; | |
| t = r[0]; | |
| } | |
| const n = e[1], [r, s] = autoType(e.slice(2)); | |
| try { | |
| ObjC.schedule(ObjC.mainQueue, (function() { | |
| t.hasOwnProperty(n) ? t[n](...s) : console.error("unknown method " + n + " for objc instance at " + padPointer(ptr(t))); | |
| })); | |
| } catch (e) { | |
| console.error(e); | |
| } | |
| return ""; | |
| } | |
| function dxCall(e) { | |
| if (0 === e.length) return '\nUsage: dxc [funcptr] [arg0 arg1..]\nFor example:\n :dxc write 1 "hello\\n" 6\n :dxc read 0 `?v rsp` 10\n'; | |
| const t = "0x" === e[0].substring(0, 2) ? ptr(e[0]) : Module.getExportByName(null, e[0]), [n, r] = autoType(e.slice(1)), s = new NativeFunction(t, "pointer", n); | |
| return 0 === n.length ? s() : s(...r); | |
| } | |
| function evalCode(args) { | |
| const code = args.join(" "), result = eval(code); | |
| return void 0 !== result ? result : ""; | |
| } | |
| function printHexdump(e) { | |
| const t = +e || 32; | |
| try { | |
| return hexdump(ptr(r2frida.offset), t) || ""; | |
| } catch (e) { | |
| return "Cannot read memory."; | |
| } | |
| } | |
| function disasmCode(e) { | |
| const t = +e || 32; | |
| return disasm(r2frida.offset, t); | |
| } | |
| function disasm(e, t, n) { | |
| if (t = t || 32, "string" == typeof e) try { | |
| if (!(e = Module.findExportByName(null, e))) throw new Error; | |
| } catch (t) { | |
| e = ptr(r2frida.offset); | |
| } | |
| let r = void 0 !== n ? n : null, s = null, o = ""; | |
| for (let n = 0; n < t; n++) { | |
| const [t, n] = _tolerantInstructionParse(e), a = padPointer(e); | |
| if (null === t) { | |
| o += `${a}\tinvalid\n`, e = n; | |
| continue; | |
| } | |
| const i = DebugSymbol.fromAddress(e); | |
| let c = null === i.name || 0 === i.name.indexOf("0x") ? "" : i.name, l = i.moduleName; | |
| i.moduleName || (l = ""), c || (c = ""), (l || c) && c !== r && (o += ";;; " + (l || c) + "\n", | |
| r = c); | |
| let u = ""; | |
| const d = t.opStr.indexOf("#0x"); | |
| if (-1 !== d) try { | |
| const e = t.opStr.substring(d + 1).split(" ")[0].split(",")[0].split("]")[0]; | |
| if (-1 !== t.opStr.indexOf("]")) try { | |
| const t = Memory.readPointer(ptr(s).add(e)); | |
| o += "; str:" + Memory.readCString(t) + "\n"; | |
| } catch (t) { | |
| const n = Memory.readPointer(ptr(e)); | |
| o += "; str2:" + Memory.readCString(n) + "\n", console.log(t); | |
| } | |
| s = e; | |
| const n = DebugSymbol.fromAddress(ptr(e)); | |
| if (null !== n.name) u = "\t; " + (n.moduleName || "") + " " + n.name; else { | |
| const t = Instruction.parse(ptr(e)), n = t.opStr.indexOf("#0x"), r = t.opStr.substring(n + 1).split(" ")[0].split(",")[0].split("]")[0], s = DebugSymbol.fromAddress(ptr(r)); | |
| null !== s.name && (u = "\t; -> " + (s.moduleName || "") + " " + s.name); | |
| } | |
| } catch (e) {} | |
| o += [ padPointer(t.address), t.mnemonic, t.opStr, u ].join("\t") + "\n", t.size < 1 && (t.size = 1), | |
| e = e.add(t.size); | |
| } | |
| return o; | |
| } | |
| function sym(e, t, n) { | |
| try { | |
| return new NativeFunction(Module.getExportByName(null, e), t, n); | |
| } catch (t) { | |
| console.error(e, ":", t); | |
| } | |
| } | |
| function symf(e, t, n) { | |
| try { | |
| return new SystemFunction(Module.getExportByName(null, e), t, n); | |
| } catch (e) {} | |
| } | |
| let _getenv = 0, _setenv = 0, _getpid = 0, _getuid = 0, _dup2 = 0, _readlink = 0, _fstat = 0, _close = 0, _kill = 0; | |
| "windows" === Process.platform ? (_getenv = sym("getenv", "pointer", [ "pointer" ]), | |
| _setenv = sym("SetEnvironmentVariableA", "int", [ "pointer", "pointer" ]), _getpid = sym("_getpid", "int", []), | |
| _getuid = getWindowsUserNameA, _dup2 = sym("_dup2", "int", [ "int", "int" ]), _fstat = sym("_fstat", "int", [ "int", "pointer" ]), | |
| _close = sym("_close", "int", [ "int" ]), _kill = sym("TerminateProcess", "int", [ "int", "int" ])) : (_getenv = sym("getenv", "pointer", [ "pointer" ]), | |
| _setenv = sym("setenv", "int", [ "pointer", "pointer", "int" ]), _getpid = sym("getpid", "int", []), | |
| _getuid = sym("getuid", "int", []), _dup2 = sym("dup2", "int", [ "int", "int" ]), | |
| _readlink = sym("readlink", "int", [ "pointer", "pointer", "int" ]), _fstat = Module.findExportByName(null, "fstat") ? sym("fstat", "int", [ "int", "pointer" ]) : sym("__fxstat", "int", [ "int", "pointer" ]), | |
| _close = sym("close", "int", [ "int" ]), _kill = sym("kill", "int", [ "int", "int" ])); | |
| const _setfilecon = symf("setfilecon", "int", [ "pointer", "pointer" ]); | |
| if ("darwin" === Process.platform) try { | |
| Module.load("/System/Library/Frameworks/Foundation.framework/Foundation"); | |
| } catch (e) {} | |
| const traceListeners = []; | |
| async function dumpInfo() { | |
| const e = await dumpInfoJson(); | |
| return Object.keys(e).map((t => { | |
| return t + (n = t.length, "".padStart(20 - n, " ")) + e[t]; | |
| var n; | |
| })).join("\n"); | |
| } | |
| async function dumpInfoR2() { | |
| const e = await dumpInfoJson(), t = void 0 !== e.jniEnv ? e.jniEnv : ""; | |
| return [ "e asm.arch=" + e.arch, "e asm.bits=" + e.bits, "e asm.os=" + e.os ].join("\n") + t; | |
| } | |
| function getR2Arch(e) { | |
| switch (e) { | |
| case "ia32": | |
| case "x64": | |
| return "x86"; | |
| case "arm64": | |
| return "arm"; | |
| } | |
| return e; | |
| } | |
| function breakpointUnset(e) { | |
| if (1 === e.length) { | |
| const t = Module.findExportByName(null, e[0]), n = e[0], r = "*" === n ? ptr(0) : null !== t ? t : ptr(n), s = []; | |
| let o = !1; | |
| for (const e of Object.keys(breakpoints)) { | |
| const t = breakpoints[e]; | |
| console.log(t.address, r, JSON.stringify(t)), "*" === n || "" + t.address == "" + r ? (o = !0, | |
| console.log("Breakpoint reverted", JSON.stringify(t)), breakpoints[e].continue = !0, | |
| t.handler.detach()) : s.push(t); | |
| } | |
| o || console.error("Cannot found any breakpoint matching"), breakpoints = {}; | |
| for (const e of s) breakpoints[e.address] = e; | |
| return Interceptor.flush(), ""; | |
| } | |
| return "Usage: db- [addr|*]"; | |
| } | |
| function breakpointExist(e) { | |
| const t = breakpoints["" + e]; | |
| return t && !t.continue; | |
| } | |
| let _r2 = null, _r_core_new = null, _r_core_cmd_str = null, _r_core_free = null, _free = null; | |
| function radareCommandInit() { | |
| if (_r2) return !0; | |
| if (!_r_core_new) { | |
| if (_r_core_new = sym("r_core_new", "pointer", []), !_r_core_new) return console.error("ERROR: Cannot find r_core_new. Do :dl /tmp/libr.dylib"), | |
| !1; | |
| _r_core_cmd_str = sym("r_core_cmd_str", "pointer", [ "pointer", "pointer" ]), _r_core_free = sym("r_core_free", "void", [ "pointer" ]), | |
| _free = sym("free", "void", [ "pointer" ]), _r2 = _r_core_new(); | |
| } | |
| return !0; | |
| } | |
| function radareCommandString(e) { | |
| if (_r2) { | |
| const t = Memory.allocUtf8String(e), n = _r_core_cmd_str(_r2, t), r = Memory.readCString(n); | |
| return _free(n), r; | |
| } | |
| return console.error("Warning: not calling back r2"), ""; | |
| } | |
| function radareSeek(e) { | |
| return "s " + (getPtr("" + e) || "" + e); | |
| } | |
| function radareCommand(e) { | |
| const t = e.join(" "); | |
| return 0 === t.length ? "Usage: :r [cmd]" : radareCommandInit() ? radareCommandString(t) : ":dl /tmp/libr.dylib"; | |
| } | |
| function sendSignal(e) { | |
| const t = e.length; | |
| if (console.error("WARNING: Frida hangs when signal is sent. But at least the process doesnt continue"), | |
| 1 === t) { | |
| const t = +e[0]; | |
| _kill(_getpid(), t); | |
| } else { | |
| if (2 !== t) return "Usage: :dk ([pid]) [sig]"; | |
| { | |
| const [t, n] = e; | |
| _kill(+t, +n); | |
| } | |
| } | |
| return ""; | |
| } | |
| function breakpointContinueUntil(e) { | |
| return new Promise(((t, n) => { | |
| numEval(e[0]).then((e => { | |
| setBreakpoint(e); | |
| const r = breakpointContinue(); | |
| "object" == typeof r ? r.then(t).catch(n) : t(r); | |
| })).catch(n); | |
| })); | |
| } | |
| function breakpointContinue(e) { | |
| if (suspended) return suspended = !1, hostCmd(":dc"); | |
| let t = 0; | |
| for (const e of Object.keys(breakpoints)) { | |
| const n = breakpoints[e]; | |
| n && n.stopped && (t++, n.continue = !0); | |
| } | |
| for (const e of Process.enumerateThreads()) send(wrapStanza("action-" + e.id, { | |
| action: "continue" | |
| })); | |
| return "Continue " + t + " thread(s)."; | |
| } | |
| function breakpointJson(e) { | |
| return 0 === e.length ? JSON.stringify(breakpoints, null, " ") : new Promise(((t, n) => { | |
| numEval(e[0]).then((e => { | |
| setBreakpoint(e), t(JSON.stringify(breakpoints, null, " ")); | |
| })).catch((e => { | |
| console.error(e), n(e); | |
| })); | |
| })); | |
| } | |
| function breakpoint(e) { | |
| return 0 === e.length ? Object.keys(breakpoints).map((e => { | |
| const t = breakpoints[e], n = t.stopped ? "stop" : "nostop", r = t.continue ? "cont" : "nocont"; | |
| return [ t.address, t.moduleName, t.name, n, r ].join("\t"); | |
| })).join("\n") : new Promise(((t, n) => { | |
| numEval(e[0]).then((n => { | |
| t(setBreakpoint(e[0], n)); | |
| })).catch((e => { | |
| console.error(e), n(e); | |
| })); | |
| })); | |
| } | |
| function setBreakpoint(e, t) { | |
| const n = Module.findExportByName(null, e), r = null !== n ? n : ptr(t); | |
| if (breakpointExist(r)) return "Cant set a breakpoint twice"; | |
| const s = "" + r, o = Process.findModuleByAddress(t), a = { | |
| name: e, | |
| moduleName: o ? o.name : "", | |
| stopped: !1, | |
| address: t, | |
| continue: !1, | |
| handler: Interceptor.attach(r, (function() { | |
| if (breakpoints[s] && (breakpoints[s].stopped = !0, config.getBoolean("hook.backtrace"))) { | |
| console.log(r); | |
| const e = Thread.backtrace(this.context).map(DebugSymbol.fromAddress); | |
| console.log(e.join("\n\t")); | |
| } | |
| const e = this.threadId; | |
| send({ | |
| type: "breakpoint-hit", | |
| name: s, | |
| tid: e | |
| }); | |
| let t = "stopped"; | |
| do { | |
| recv(((e, n) => { | |
| if ("dc" === e.payload.command) { | |
| t = "hit"; | |
| for (const e in breakpoints) breakpoints[e].continue = !0; | |
| } else onceStanza = !0, onStanza(e, n); | |
| })).wait(); | |
| } while ("stopped" === t); | |
| breakpoints[s] && (breakpoints[s].stopped = !1, breakpoints[s].continue = !1); | |
| })) | |
| }; | |
| breakpoints[s] = a; | |
| } | |
| function getCwd() { | |
| let e = 0; | |
| if (e = "windows" === Process.platform ? sym("_getcwd", "pointer", [ "pointer", "int" ]) : sym("getcwd", "pointer", [ "pointer", "int" ]), | |
| e) { | |
| const t = 4096, n = Memory.alloc(t); | |
| if (!n.isNull()) { | |
| const r = e(n, t), s = Memory.readCString(r); | |
| return Gcwd = s, s; | |
| } | |
| } | |
| return ""; | |
| } | |
| function chDir(e) { | |
| const t = sym("chdir", "int", [ "pointer" ]); | |
| if (t && e) { | |
| t(Memory.allocUtf8String(e[0])), getCwd(); | |
| } | |
| return ""; | |
| } | |
| function waitForJava() { | |
| javaPerform((function() { | |
| const e = Java.use("android.app.ActivityThread").currentApplication().getApplicationContext(); | |
| console.log("Done: " + e); | |
| })); | |
| } | |
| async function dumpInfoJson() { | |
| const e = { | |
| arch: getR2Arch(Process.arch), | |
| bits: 8 * pointerSize, | |
| os: Process.platform, | |
| pid: getPid(), | |
| uid: _getuid(), | |
| objc: ObjCAvailable, | |
| runtime: Script.runtime, | |
| swift: SwiftAvailable, | |
| java: JavaAvailable, | |
| mainLoop: hasMainLoop(), | |
| pageSize: Process.pageSize, | |
| pointerSize: Process.pointerSize, | |
| codeSigningPolicy: Process.codeSigningPolicy, | |
| isDebuggerAttached: Process.isDebuggerAttached(), | |
| cwd: getCwd() | |
| }; | |
| if (ObjCAvailable && !suspended) try { | |
| const n = ObjC && ObjC.classes && ObjC.classes.NSBundle ? ObjC.classes.NSBundle.mainBundle() : "", r = n ? n.infoDictionary() : ""; | |
| function t(e) { | |
| const t = r ? r.objectForKey_(e) : ""; | |
| return t ? t.toString() : ""; | |
| } | |
| const s = new NativeFunction(Module.getExportByName(null, "NSHomeDirectory"), "pointer", []), o = new NativeFunction(Module.getExportByName(null, "NSTemporaryDirectory"), "pointer", []); | |
| e.bundle = t("CFBundleIdentifier"), e.exename = t("CFBundleExecutable"), e.appname = t("CFBundleDisplayName"), | |
| e.appversion = t("CFBundleShortVersionString"), e.appnumversion = t("CFBundleNumericVersion"), | |
| e.homedir = new ObjC.Object(s()).toString(), e.tmpdir = new ObjC.Object(o()).toString(), | |
| e.bundledir = ObjC.classes.NSBundle.mainBundle().bundleURL().path(), e.minOS = t("MinimumOSVersion"); | |
| } catch (e) { | |
| console.error(e); | |
| } | |
| return JavaAvailable && await performOnJavaVM((() => { | |
| const t = Java.use("android.app.ActivityThread").currentApplication(); | |
| if (null !== t) { | |
| const n = t.getApplicationContext(); | |
| if (null !== n) { | |
| try { | |
| e.dataDir = n.getDataDir().getAbsolutePath(); | |
| } catch (e) {} | |
| e.codeCacheDir = n.getCodeCacheDir().getAbsolutePath(), e.extCacheDir = n.getExternalCacheDir().getAbsolutePath(), | |
| e.obbDir = n.getObbDir().getAbsolutePath(), e.filesDir = n.getFilesDir().getAbsolutePath(), | |
| e.noBackupDir = n.getNoBackupFilesDir().getAbsolutePath(), e.codePath = n.getPackageCodePath(), | |
| e.packageName = n.getPackageName(); | |
| } | |
| try { | |
| e.androidId = Java.use("android.provider.Settings$Secure").getString(Java.use("android.app.ActivityThread").currentApplication().getApplicationContext().getContentResolver(), "android_id"); | |
| } catch (e) {} | |
| } | |
| e.cacheDir = Java.classFactory.cacheDir; | |
| const n = ptr(Java.vm.getEnv()); | |
| n && (e.jniEnv = n.toString()); | |
| })), e; | |
| } | |
| function listModules() { | |
| return Process.enumerateModules().map((e => padPointer(e.base) + " " + e.name)).join("\n"); | |
| } | |
| function listModulesQuiet() { | |
| return Process.enumerateModules().map((e => e.name)).join("\n"); | |
| } | |
| function listModulesR2() { | |
| return Process.enumerateModules().map((e => "f lib." + utils.flagify(e.name) + " = " + padPointer(e.base))).join("\n"); | |
| } | |
| function listModulesJson() { | |
| return Process.enumerateModules(); | |
| } | |
| function listModulesHere() { | |
| const e = ptr(r2frida.offset); | |
| return Process.enumerateModules().filter((t => e.compare(t.base) >= 0 && e.compare(t.base.add(t.size)) < 0)).map((e => padPointer(e.base) + " " + e.name)).join("\n"); | |
| } | |
| function listExports(e) { | |
| return listExportsJson(e).map((({type: e, name: t, address: n}) => [ n, e[0], t ].join(" "))).join("\n"); | |
| } | |
| function listExportsR2(e) { | |
| return listExportsJson(e).map((({type: e, name: t, address: n}) => [ "f", "sym." + e.substring(0, 3) + "." + t, "=", n ].join(" "))).join("\n"); | |
| } | |
| function listAllExportsJson(e) { | |
| return (0 === e.length ? Process.enumerateModules().map((e => e.path)) : [ e.join(" ") ]).reduce(((e, t) => e.concat(Module.enumerateExports(t))), []); | |
| } | |
| function listAllExports(e) { | |
| return listAllExportsJson(e).map((({type: e, name: t, address: n}) => [ n, e[0], t ].join(" "))).join("\n"); | |
| } | |
| function listAllExportsR2(e) { | |
| return listAllExportsJson(e).map((({type: e, name: t, address: n}) => [ "f", "sym." + e.substring(0, 3) + "." + t, "=", n ].join(" "))).join("\n"); | |
| } | |
| function listAllSymbolsJson(e) { | |
| const t = e[0], n = Process.enumerateModules().map((e => e.path)); | |
| let r = []; | |
| for (const e of n) { | |
| const n = Module.enumerateSymbols(e).filter((e => e.address.compare(ptr("0")) > 0 && e.name)); | |
| t ? r.push(...n.filter((e => -1 !== e.name.indexOf(t)))) : r.push(...n), r.length > 1e5 && (r.forEach((e => { | |
| console.error([ e.address, e.moduleName, e.name ].join(" ")); | |
| })), r = []); | |
| } | |
| return r; | |
| } | |
| function listAllHelp(e) { | |
| return "See :ia? for more information. Those commands may take a while to run."; | |
| } | |
| function listAllSymbols(e) { | |
| return listAllSymbolsJson(e).map((({type: e, name: t, address: n}) => [ n, e[0], t ].join(" "))).join("\n"); | |
| } | |
| function listAllSymbolsR2(e) { | |
| return listAllSymbolsJson(e).map((({type: e, name: t, address: n}) => [ "f", "sym." + e.substring(0, 3) + "." + t, "=", n ].join(" "))).join("\n"); | |
| } | |
| function listExportsJson(e) { | |
| const t = e.length > 0 ? Process.getModuleByName(e[0]) : getModuleByAddress(ptr(r2frida.offset)); | |
| return Module.enumerateExports(t.name); | |
| } | |
| function getModuleByAddress(e) { | |
| const t = config.getString("symbols.module"); | |
| if ("" !== t) return Process.getModuleByName(t); | |
| try { | |
| return Process.getModuleByAddress(e); | |
| } catch (e) { | |
| return Process.getModuleByAddress(ptr(r2frida.offset)); | |
| } | |
| } | |
| function listSymbols(e) { | |
| return listSymbolsJson(e).map((({type: e, name: t, address: n}) => [ n, e[0], t ].join(" "))).join("\n"); | |
| } | |
| function listSymbolsR2(e) { | |
| return listSymbolsJson(e).filter((({address: e}) => !e.isNull())).map((({type: e, name: t, address: n}) => [ "f", "sym." + e.substring(0, 3) + "." + sanitizeString(t), "=", n ].join(" "))).join("\n"); | |
| } | |
| function sanitizeString(e) { | |
| return e.split("").map((e => -1 === specialChars.indexOf(e) ? e : "_")).join(""); | |
| } | |
| function listSymbolsJson(e) { | |
| const t = e.length > 0 ? Process.getModuleByName(e[0]) : getModuleByAddress(r2frida.offset); | |
| return Module.enumerateSymbols(t.name).map((e => { | |
| if (config.getBoolean("symbols.unredact") && -1 !== e.name.indexOf("redacted")) { | |
| const t = DebugSymbol.fromAddress(e.address); | |
| null !== t && (e.name = t.name); | |
| } | |
| return e; | |
| })); | |
| } | |
| function lookupDebugInfo(e) { | |
| const t = DebugSymbol.fromAddress(ptr("" + e)); | |
| console.log(t); | |
| } | |
| function lookupAddress(e) { | |
| return 0 === e.length && (e = [ ptr(r2frida.offset) ]), lookupAddressJson(e).map((({type: e, name: t, address: n}) => [ e, t, n ].join(" "))).join("\n"); | |
| } | |
| function lookupAddressR2(e) { | |
| return lookupAddressJson(e).map((({type: e, name: t, address: n}) => [ "f", "sym." + t, "=", n ].join(" "))).join("\n"); | |
| } | |
| function lookupAddressJson(e) { | |
| const t = ptr(e[0]), n = []; | |
| return Process.enumerateModules().map((e => e.path)).reduce(((e, t) => e.concat(Module.enumerateExports(t))), []).reduce(((e, r) => (0 === ptr(r.address).compare(t) && n.push({ | |
| type: r.type, | |
| name: r.name, | |
| address: r.address | |
| }), n)), []); | |
| } | |
| function lookupSymbolHere(e) { | |
| return lookupAddress([ ptr(r2frida.offset) ]); | |
| } | |
| function lookupExport(e) { | |
| return lookupExportJson(e).map((({address: e}) => "" + e)).join("\n"); | |
| } | |
| function lookupExportR2(e) { | |
| return lookupExportJson(e).map((({name: e, address: t}) => [ "f", "sym." + e, "=", t ].join(" "))).join("\n"); | |
| } | |
| function lookupExportJson(e) { | |
| if (2 === e.length) { | |
| const [t, n] = e, r = Module.findExportByName(t, n); | |
| if (null === r) return []; | |
| return [ { | |
| library: getModuleByAddress(r).name, | |
| name: n, | |
| address: r | |
| } ]; | |
| } | |
| { | |
| const t = e[0]; | |
| let n = null; | |
| return Process.enumerateModules().reduce(((e, r) => { | |
| const s = Module.findExportByName(r.path, t); | |
| return null === s || null !== n && !s.compare(n) || (e.push({ | |
| library: r.name, | |
| name: t, | |
| address: s | |
| }), n = s), e; | |
| }), []); | |
| } | |
| } | |
| function lookupSymbol(e) { | |
| return lookupSymbolJson(e).map((({address: e}) => "" + e)).join("\n"); | |
| } | |
| function lookupSymbolR2(e) { | |
| return lookupSymbolJson(e).map((({name: e, address: t}) => [ "f", "sym." + e, "=", t ].join(" "))).join("\n"); | |
| } | |
| function lookupSymbolManyJson(e) { | |
| const t = []; | |
| for (const n of e) t.push({ | |
| name: n, | |
| address: lookupSymbol([ n ]) | |
| }); | |
| return t; | |
| } | |
| function lookupSymbolMany(e) { | |
| return lookupSymbolManyJson(e).map((({address: e}) => e)).join("\n"); | |
| } | |
| function lookupSymbolManyR2(e) { | |
| return lookupSymbolManyJson(e).map((({name: e, address: t}) => [ "f", "sym." + e, "=", t ].join(" "))).join("\n"); | |
| } | |
| function lookupSymbolJson(e) { | |
| if (0 === e.length) return []; | |
| if (2 === e.length) { | |
| let [t, n] = e; | |
| try { | |
| Process.getModuleByName(t); | |
| } catch (e) { | |
| const n = Process.enumerateModules().filter((function(e) { | |
| return -1 !== e.name.indexOf(t); | |
| })); | |
| if (1 !== n.length) return []; | |
| t = n[0].name; | |
| } | |
| let r = 0; | |
| return Module.enumerateSymbols(t).filter((function(e) { | |
| e.name === n && (r = e.address); | |
| })), [ { | |
| library: t, | |
| name: n, | |
| address: r | |
| } ]; | |
| } | |
| { | |
| const [t] = e, n = getPtr(t), r = getModuleAt(n); | |
| if (n) return [ { | |
| library: r ? r.name : "unknown", | |
| name: t, | |
| address: n | |
| } ]; | |
| const s = DebugSymbol.findFunctionsNamed(t); | |
| return s ? s.map((e => ({ | |
| name: t, | |
| address: e | |
| }))) : []; | |
| } | |
| } | |
| function listEntrypointJson(e) { | |
| if ("linux" === Process.platform) { | |
| const e = DebugSymbol.fromName("main"); | |
| if (e) return [ e ]; | |
| } | |
| const t = Process.enumerateModules()[0]; | |
| return Module.enumerateSymbols(t.name).filter((e => function(e) { | |
| if ("section" === e.type) switch (e.name) { | |
| case "_start": | |
| case "start": | |
| case "main": | |
| return !0; | |
| } | |
| return !1; | |
| }(e))).map((e => (e.moduleName = getModuleByAddress(e.address).name, e))); | |
| } | |
| function listEntrypointR2(e) { | |
| let t = 0; | |
| return listEntrypointJson().map((e => "f entry" + t++ + " = " + e.address)).join("\n"); | |
| } | |
| function listEntrypointQuiet(e) { | |
| return listEntrypointJson().map((e => e.address)).join("\n"); | |
| } | |
| function listEntrypoint(e) { | |
| return listEntrypointJson().map((e => e.address + " " + e.name + " # " + e.moduleName)).join("\n"); | |
| } | |
| function analFunctionSignature(e) { | |
| if (!ObjCAvailable) return "Error: afs is only implemented for ObjC methods."; | |
| if (0 === e.length) return "Usage: afs [class] [method]"; | |
| if (1 === e.length) return listClasses(e); | |
| if (e.length > 1) { | |
| const t = e[0], n = e[1].replace(/:/g, "_"), r = ObjC.classes[t]; | |
| if (!r) { | |
| const e = t.startsWith("0x") ? DebugSymbol.fromAddress(ptr(t)) : DebugSymbol.fromName(t); | |
| return e ? JSON.stringify(e) : "Cannot find class named " + t; | |
| } | |
| const s = ObjC.chooseSync(r)[0]; | |
| if (!s) return "Cannot find any instance for " + t; | |
| const o = s[n]; | |
| return o ? o.returnType + " (" + o.argumentTypes.join(", ") + ");" : "Cannot find method " + n + " for class " + t; | |
| } | |
| return "Usage: afs [klassName] [methodName]"; | |
| } | |
| function listImports(e) { | |
| return listImportsJson(e).map((({type: e, name: t, module: n, address: r}) => [ r, e ? e[0] : " ", t, n ].join(" "))).join("\n"); | |
| } | |
| function listImportsR2(e) { | |
| const t = new Set; | |
| return listImportsJson(e).map((e => { | |
| const n = []; | |
| if (t.has(e.address) || (t.add(e.address), n.push("f sym.imp." + utils.flagify(e.name) + ` = ${e.address}`)), | |
| void 0 !== e.slot) { | |
| const t = utils.flagify(`f reloc.${e.targetModuleName}.${e.name}_${e.index}`); | |
| n.push(`f ${t} = ${e.slot}`); | |
| } | |
| return n.join("\n"); | |
| })).join("\n"); | |
| } | |
| function listImportsJson(e) { | |
| const t = e.length; | |
| let n = [], r = null; | |
| if (2 === t) { | |
| r = e[0]; | |
| const t = e[1], s = Module.enumerateImports(r); | |
| null !== s && (n = s.filter(((e, n) => (e.index = n, e.name === t)))); | |
| } else if (1 === t) r = e[0], n = Module.enumerateImports(r) || []; else { | |
| const e = getModuleByAddress(r2frida.offset); | |
| e && (n = Module.enumerateImports(e.name) || []); | |
| } | |
| return n.forEach(((e, t) => { | |
| void 0 === e.index && (e.index = t), e.targetModuleName = r; | |
| })), n; | |
| } | |
| function listClassesLoadedJson(e) { | |
| return JavaAvailable ? listClasses(e) : ObjCAvailable ? JSON.stringify(ObjC.enumerateLoadedClassesSync()) : void 0; | |
| } | |
| function listClassesLoaders(e) { | |
| if (!JavaAvailable) return "Error: icL is only available on Android targets."; | |
| let t = ""; | |
| return javaPerform((function() { | |
| function e(e) { | |
| let t = 0, n = ""; | |
| for (const r of e.toString()) switch (r) { | |
| case "[": | |
| t++, n += "[\n" + Array(t + 1).join(" "); | |
| break; | |
| case "]": | |
| t--, n += "]\n" + Array(t + 1).join(" "); | |
| break; | |
| case ",": | |
| n += ",\n" + Array(t + 1).join(" "); | |
| break; | |
| default: | |
| n += r; | |
| } | |
| return n; | |
| } | |
| const n = Java.enumerateClassLoadersSync(); | |
| for (const r in n) { | |
| const s = e(n[r].toString()); | |
| t += s; | |
| } | |
| })), t; | |
| } | |
| function listClassesLoaded(e) { | |
| if (JavaAvailable) return listClasses(e); | |
| if (ObjCAvailable) { | |
| const e = ObjC.enumerateLoadedClassesSync(), t = []; | |
| for (const n of Object.keys(e)) t.push(...e[n]); | |
| return t.join("\n"); | |
| } | |
| return []; | |
| } | |
| function listAllClassesNatives(e) { | |
| return listClassesNatives([ "." ]); | |
| } | |
| function listClassesNatives(e) { | |
| const t = [], n = e[0] || "com"; | |
| return javaPerform((function() { | |
| const e = listClassesJson([]); | |
| for (let r of e) if (r = r.toString(), -1 !== r.indexOf(n)) try { | |
| const e = javaUse(r), n = e.class.getMethods().map((e => e.toString())).filter((e => -1 !== e.indexOf("static native"))); | |
| if (n.length > 0) { | |
| const e = n.map((e => { | |
| const t = e.indexOf("("); | |
| let n = ""; | |
| if (-1 !== t) { | |
| const r = e.substring(0, t).split(" "); | |
| return n = r[r.length - 1], n; | |
| } | |
| return e; | |
| })); | |
| console.error(e.join("\n")); | |
| for (const n of e) -1 === t.indexOf(n) && t.push(n); | |
| } | |
| } catch (e) {} | |
| })), t; | |
| } | |
| function listClassesAllMethods(e) { | |
| return listClassesJson(e, "all").join("\n"); | |
| } | |
| function listClassSuperMethods(e) { | |
| return listClassesJson(e, "super").join("\n"); | |
| } | |
| function listClassVariables(e) { | |
| return listClassesJson(e, "ivars").join("\n"); | |
| } | |
| function listClassesHooks(e, t) { | |
| let n = ""; | |
| if (0 === e.length) return "Usage: :ich [kw]"; | |
| const r = {}, s = listClassesJson([]); | |
| if (ObjCAvailable) { | |
| ObjC.classes; | |
| for (const e of s) r[e] = ObjC.classes[e].$moduleName; | |
| } | |
| for (const t of s) { | |
| const s = r[t]; | |
| if (-1 !== t.indexOf(e[0]) || s && -1 !== s.indexOf(e[0])) { | |
| searchInstancesJson([ t ]).map((e => e.address)).join(" "); | |
| const e = "OOO", r = ObjC.classes[t]; | |
| if (r) for (const s of r.$ownMethods) n += ":dtf objc:" + t + "." + s + " " + e + "\n"; | |
| } | |
| } | |
| return n; | |
| } | |
| function listClassesWhere(e, t) { | |
| let n = ""; | |
| if (0 === e.length) { | |
| const e = {}, t = listClassesJson([]); | |
| if (ObjCAvailable) { | |
| const n = ObjC.classes; | |
| for (const r of t) e[r] = n[r].$moduleName; | |
| } | |
| for (const r of t) { | |
| n += [ e[r], r ].join(" ") + "\n"; | |
| } | |
| return n; | |
| } | |
| { | |
| const r = {}, s = listClassesJson([]); | |
| if (ObjCAvailable) { | |
| ObjC.classes; | |
| for (const e of s) r[e] = ObjC.classes[e].$moduleName; | |
| } | |
| for (const o of s) { | |
| const s = r[o]; | |
| if (s && -1 != s.indexOf(e[0])) { | |
| const e = searchInstancesJson([ o ]); | |
| if (n += o + " # " + e.map((e => e.address)).join(" ") + "\n", "ivars" === t) for (const t of e) { | |
| n += "instance " + padPointer(t.address) + "\n"; | |
| const e = new ObjC.Object(ptr(t.address)); | |
| n += JSON.stringify(e.$ivars) + "\n"; | |
| } | |
| } | |
| } | |
| return n; | |
| } | |
| } | |
| function listClasses(e) { | |
| const t = listClassesJson(e); | |
| return t instanceof Array ? t.join("\n") : Object.keys(t).map((e => [ padPointer(t[e]), e ].join(" "))).join("\n"); | |
| } | |
| function classGlob(e, t) { | |
| return !e || !t || -1 !== e.indexOf(t.replace(/\*/g, "")); | |
| } | |
| function listClassesR2(e) { | |
| const t = e[0]; | |
| if (0 === e.length || -1 !== e[0].indexOf("*")) { | |
| let t = ""; | |
| if (ObjCAvailable) for (const n of Object.keys(ObjC.classes)) classGlob(n, e[0]) && (t += listClassesR2([ n ])); | |
| return t; | |
| } | |
| const n = listClassesJson(e); | |
| return Object.keys(n).map((e => { | |
| const r = n[e]; | |
| return [ "f", (s = e, "sym.objc." + (t + "." + s).replace(":", "").replace(" ", "").replace("-", "").replace("+", "")), "=", padPointer(r) ].join(" "); | |
| var s; | |
| })).join("\n") + "\n"; | |
| } | |
| function listJavaClassesJsonSync(e) { | |
| if (1 === e.length) { | |
| let t; | |
| for (javaPerform((function() { | |
| const n = javaUse(e[0]); | |
| t = Object.getOwnPropertyNames(Object.getPrototypeOf(n)); | |
| })); void 0 === t; ) setTimeout(null, 0); | |
| return t; | |
| } | |
| let t; | |
| return javaPerform((function() { | |
| try { | |
| t = Java.enumerateLoadedClassesSync(); | |
| } catch (e) { | |
| t = null; | |
| } | |
| })), t; | |
| } | |
| function listJavaClassesJson(e, t) { | |
| let n = []; | |
| return 1 === e.length ? javaPerform((function() { | |
| try { | |
| const r = e[0], s = javaUse(r); | |
| if (null === s || !s.class) throw new Error("Cannot find a classloader for this class"); | |
| const o = s.class; | |
| try { | |
| t ? o.getMethods().filter((e => -1 !== e.toString().indexOf(r))).map((e => n.push(e.toString()))) : o.getMethods().map((e => n.push(e.toString()))), | |
| o.getFields().map((e => n.push(e.toString()))); | |
| try { | |
| o.getConstructors().map((e => n.push(e.toString()))); | |
| } catch (e) {} | |
| } catch (e) { | |
| console.error(e.message), console.error(Object.keys(o), JSON.stringify(o), o); | |
| } | |
| } catch (e) { | |
| console.error(e.message); | |
| } | |
| })) : javaPerform((function() { | |
| try { | |
| n = Java.enumerateLoadedClassesSync(); | |
| } catch (e) { | |
| console.error(e); | |
| } | |
| })), n; | |
| } | |
| function listClassMethods(e) { | |
| return listClassesJson(e, "methods").join("\n"); | |
| } | |
| function listClassMethodsJson(e) { | |
| return listClassesJson(e, "methods"); | |
| } | |
| function listClassesJson(e, t) { | |
| if (JavaAvailable) return listJavaClassesJson(e, "methods" === t); | |
| if (!ObjCAvailable) return []; | |
| if (0 === e.length) return Object.keys(ObjC.classes); | |
| const n = e[0], r = ObjC.classes[n]; | |
| if (void 0 === r) throw new Error("Class " + n + " not found"); | |
| let s = ""; | |
| if ("ivars" === t) { | |
| const e = searchInstancesJson([ n ]); | |
| s += n + ": "; | |
| for (const t of e) { | |
| s += "instance " + padPointer(ptr(t.address)) + ": "; | |
| const e = new ObjC.Object(ptr(t.address)); | |
| s += JSON.stringify(e.$ivars, null, " "); | |
| } | |
| return [ s ]; | |
| } | |
| const o = "methods" === t ? r.$ownMethods : "super" === t ? r.$super.$ownMethods : "all" === t ? r.$methods : r.$ownMethods, a = ObjC.api.method_getImplementation; | |
| try { | |
| return o.reduce(((e, t) => { | |
| try { | |
| e[t] = a(r[t].handle); | |
| } catch (e) { | |
| console.error("warning: unsupported method '" + t + "' in " + n); | |
| } | |
| return e; | |
| }), {}); | |
| } catch (e) { | |
| return o; | |
| } | |
| } | |
| function listProtocols(e) { | |
| return listProtocolsJson(e).join("\n"); | |
| } | |
| function closeFileDescriptors(e) { | |
| return 0 === e.length ? "Please, provide a file descriptor" : _close(+e[0]); | |
| } | |
| function listFileDescriptors(e) { | |
| return listFileDescriptorsJson(e).map((([e, t]) => e + " " + t)).join("\n"); | |
| } | |
| function listFileDescriptorsJson(e) { | |
| const t = 4096; | |
| function n(e) { | |
| if (_readlink && "linux" === Process.platform) { | |
| const n = path.join("proc", "" + getPid(), "fd", "" + e), r = Memory.alloc(t), s = Memory.alloc(t); | |
| return s.writeUtf8String(n), r.writeUtf8String(""), -1 !== _readlink(s, r, t) ? r.readUtf8String() : void 0; | |
| } | |
| try { | |
| const n = 50, r = Memory.alloc(t), s = Module.getExportByName(null, "fcntl"); | |
| return new NativeFunction(s, "int", [ "int", "int", "pointer" ])(e, n, r), r.readCString(); | |
| } catch (e) { | |
| return ""; | |
| } | |
| } | |
| if (0 === e.length) { | |
| const e = Memory.alloc(128), t = []; | |
| for (let n = 0; n < 1024; n++) 0 === _fstat(n, e) && t.push(n); | |
| return t.map((e => [ e, n(e) ])); | |
| } | |
| return _dup2(+e[0], +e[1]); | |
| } | |
| function listStringsJson(e) { | |
| e && 1 === e.length || (e = [ r2frida.offset ]); | |
| const t = ptr(e[0]), n = Process.findRangeByAddress(t); | |
| if (n) { | |
| const e = { | |
| base: t | |
| }, r = Math.min(n.size, 134217728), s = 1048576; | |
| if (r !== n.size) { | |
| const e = n.size / 1048576; | |
| console.error("Warning: this range is too big (" + e + "MB), truncated to " + r / 1048576 + "MB"); | |
| } | |
| try { | |
| const t = []; | |
| console.log("Reading " + r / 1048576 + "MB ..."); | |
| for (let o = 0; o < r; o += s) { | |
| const r = n.base.add(o).readCString(s), a = strings(r.split("").map((e => e.charCodeAt(0))), e); | |
| t.push(...a); | |
| } | |
| return t; | |
| } catch (e) { | |
| console.log(e.message); | |
| } | |
| } | |
| throw new Error("Memory not mapped here"); | |
| } | |
| function listStrings(e) { | |
| e && 1 === e.length || (e = [ ptr(r2frida.offset) ]); | |
| ptr(e[0]); | |
| return listStringsJson(e).map((({base: e, text: t}) => padPointer(e) + ` "${t}"`)).join("\n"); | |
| } | |
| function listProtocolsJson(e) { | |
| if (!ObjCAvailable) return []; | |
| if (0 === e.length) return Object.keys(ObjC.protocols); | |
| { | |
| const t = ObjC.protocols[e[0]]; | |
| if (void 0 === t) throw new Error("Protocol not found"); | |
| return Object.keys(t.methods); | |
| } | |
| } | |
| function listMallocMaps(e) { | |
| const t = squashRanges(listMallocRangesJson(e)); | |
| return squashRanges(listMemoryRangesJson()).filter((function(e) { | |
| for (const n of t) if (e.base.compare(n.base) >= 0 && e.base.add(e.size).compare(n.base.add(n.size))) return !0; | |
| return !1; | |
| })).map((({base: e, size: t, protection: n, file: r}) => [ padPointer(e), "-", padPointer(e.add(t)), n ].concat(void 0 !== r ? [ r.path ] : []).join(" "))).join("\n") + "\n"; | |
| } | |
| function listMallocRangesJson(e) { | |
| return Process.enumerateMallocRanges(); | |
| } | |
| function listMallocRangesR2(e) { | |
| return listMallocRangesJson(e).map((e => "f chunk." + e.base + " " + e.size + " " + e.base)).join("\n") + squashRanges(listMallocRangesJson(e)).map((e => "f heap." + e.base + " " + e.size + " " + e.base)).join("\n"); | |
| } | |
| function listMallocRanges(e) { | |
| return squashRanges(listMallocRangesJson(e)).map((e => e.base + " - " + e.base.add(e.size) + " (" + e.size + ")")).join("\n") + "\n"; | |
| } | |
| function listMemoryMapsHere(e) { | |
| 1 !== e.length && (e = [ ptr(r2frida.offset) ]); | |
| const t = ptr(e[0]); | |
| return squashRanges(listMemoryRangesJson()).filter((({base: e, size: n}) => t.compare(e) >= 0 && t.compare(e.add(n)) < 0)).map((({base: e, size: t, protection: n, file: r}) => [ padPointer(e), "-", padPointer(e.add(t)), n, r.path ].join(" "))).join("\n") + "\n"; | |
| } | |
| function listMemoryRangesHere(e) { | |
| 1 !== e.length && (e = [ ptr(r2frida.offset) ]); | |
| const t = ptr(e[0]); | |
| return listMemoryRangesJson().filter((({base: e, size: n}) => t.compare(e) >= 0 && t.compare(e.add(n)) < 0)).map((({base: e, size: t, protection: n, file: r}) => [ padPointer(e), "-", padPointer(e.add(t)), n ].concat(void 0 !== r ? [ r.path ] : []).join(" "))).join("\n") + "\n"; | |
| } | |
| function rwxstr(e) { | |
| let t = ""; | |
| return t += 1 & e ? "r" : "-", t += 2 & e ? "w" : "-", t += 4 & e ? "x" : "-", t; | |
| } | |
| function rwxint(e) { | |
| return [ "---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx" ].indexOf([ e ]); | |
| } | |
| function squashRanges(e) { | |
| const t = []; | |
| let n = ptr(0), r = ptr(0), s = 0, o = ""; | |
| for (const a of e) s |= rwxint(a.protection), a.base.equals(r) ? r = r.add(a.size) : n.equals(ptr(0)) ? (n = a.base, | |
| r = n.add(a.size)) : (t.push({ | |
| base: n, | |
| size: r.sub(n), | |
| protection: rwxstr(s), | |
| file: o | |
| }), r = ptr(0), n = ptr(0), s = 0, o = ""), a.file && (o = a.file); | |
| return n.equals(ptr(0)) || t.push({ | |
| base: n, | |
| size: r.sub(n), | |
| protection: rwxstr(s), | |
| file: o | |
| }), t; | |
| } | |
| function listMemoryMapsR2() { | |
| function e(e) { | |
| return e.replace(/\//g, "_").replace(/-/g, "_"); | |
| } | |
| return squashRanges(listMemoryRangesJson()).filter((e => e.file)).map((({base: t, size: n, protection: r, file: s}) => [ "f", "dmm." + e(s.path), "=", padPointer(t) ].join(" "))).join("\n") + "\n"; | |
| } | |
| function listMemoryMaps() { | |
| return squashRanges(listMemoryRangesJson()).filter((e => e.file)).map((({base: e, size: t, protection: n, file: r}) => [ padPointer(e), "-", padPointer(e.add(t)), n ].concat(void 0 !== r ? [ r.path ] : []).join(" "))).join("\n") + "\n"; | |
| } | |
| function listMemoryRangesR2() { | |
| return listMemoryRangesJson().map((({base: e, size: t, protection: n, file: r}) => [ "f", "map." + padPointer(e), "=", e, "#", n ].concat(void 0 !== r ? [ r.path ] : []).join(" "))).join("\n") + "\n"; | |
| } | |
| function listMemoryRanges() { | |
| return listMemoryRangesJson().map((({base: e, size: t, protection: n, file: r}) => [ padPointer(e), "-", padPointer(e.add(t)), n ].concat(void 0 !== r ? [ r.path ] : []).join(" "))).join("\n") + "\n"; | |
| } | |
| function listMemoryRangesJson() { | |
| return _getMemoryRanges("---"); | |
| } | |
| function _getMemoryRanges(e) { | |
| return null !== r2frida.hookedRanges ? r2frida.hookedRanges(e) : Process.enumerateRangesSync({ | |
| protection: e, | |
| coalesce: !1 | |
| }); | |
| } | |
| async function changeMemoryProtection(e) { | |
| const [t, n, r] = e; | |
| if (3 !== e.length || r.length > 3) return "Usage: :dmp [address] [size] [rwx]"; | |
| const s = getPtr(t), o = await numEval(n); | |
| return Memory.protect(s, ptr(o).toInt32(), r), ""; | |
| } | |
| function getPidJson() { | |
| return JSON.stringify({ | |
| pid: getPid() | |
| }); | |
| } | |
| function getPid() { | |
| return _getpid(); | |
| } | |
| function listThreads() { | |
| let e = !1; | |
| try { | |
| const r = Module.getExportByName(null, "pthread_getname_np"); | |
| var t = new NativeFunction(r, "int", [ "pointer", "pointer", "int" ]); | |
| const s = Module.getExportByName(null, "pthread_from_mach_thread_np"); | |
| var n = new NativeFunction(s, "pointer", [ "uint" ]); | |
| e = !0; | |
| } catch (e) {} | |
| return Process.enumerateThreads().map((r => { | |
| const s = function(r) { | |
| if (!e) return ""; | |
| const s = Memory.alloc(4096), o = n(r); | |
| return t(o, s, 4096), s.readCString(); | |
| }(r.id); | |
| return [ r.id, s ].join(" "); | |
| })).join("\n") + "\n"; | |
| } | |
| function listThreadsJson() { | |
| return Process.enumerateThreads().map((e => e.id)); | |
| } | |
| function regProfileAliasFor(e) { | |
| switch (e) { | |
| case "arm64": | |
| return "=PC pc\n=SP sp\n=BP x29\n=A0 x0\n=A1 x1\n=A2 x2\n=A3 x3\n=ZF zf\n=SF nf\n=OF vf\n=CF cf\n=SN x8\n"; | |
| case "arm": | |
| return "=PC r15\n=LR r14\n=SP sp\n=BP fp\n=A0 r0\n=A1 r1\n=A2 r2\n=A3 r3\n=ZF zf\n=SF nf\n=OF vf\n=CF cf\n=SN r7\n"; | |
| case "ia64": | |
| case "x64": | |
| return "=PC rip\n=SP rsp\n=BP rbp\n=A0 rdi\n=A1 rsi\n=A2 rdx\n=A3 rcx\n=A4 r8\n=A5 r9\n=SN rax\n"; | |
| case "ia32": | |
| case "x86": | |
| return "=PC eip\n=SP esp\n=BP ebp\n=A0 eax\n=A1 ebx\n=A2 ecx\n=A3 edx\n=A4 esi\n=A5 edi\n=SN eax\n"; | |
| } | |
| return ""; | |
| } | |
| function dumpRegisterProfile(e) { | |
| const t = Process.enumerateThreads()[0].context, n = Object.keys(JSON.parse(JSON.stringify(t))).filter((e => "pc" !== e && "sp" !== e)); | |
| n.sort(compareRegisterNames); | |
| let r = 0; | |
| const s = Process.pointerSize; | |
| let o = regProfileAliasFor(Process.arch); | |
| for (const e of n) o += `gpr\t${e}\t${s}\t${r}\t0\n`, r += s; | |
| return o; | |
| } | |
| function dumpRegisterArena(e) { | |
| const t = Process.enumerateThreads(); | |
| let [n] = e; | |
| if (n || (n = 0), n < 0 || n >= t.length) return ""; | |
| const r = t[n].context, s = Object.keys(JSON.parse(JSON.stringify(r))).filter((e => "pc" !== e && "sp" !== e)); | |
| s.sort(compareRegisterNames); | |
| let o = 0; | |
| const a = Process.pointerSize, i = Buffer.alloc(a * s.length); | |
| for (const e of s) { | |
| const t = r[e], n = [ t.and(255), t.shr(8).and(255), t.shr(16).and(255), t.shr(24).and(255), t.shr(32).and(255), t.shr(40).and(255), t.shr(48).and(255), t.shr(56).and(255) ]; | |
| for (let e = 0; e < a; e++) i.writeUInt8(n[e], o + e); | |
| o += a; | |
| } | |
| return i.toString("hex"); | |
| } | |
| function regcursive(e, t) { | |
| const n = [ t ]; | |
| try { | |
| const r = Memory.readCString(t, 32); | |
| if (r && r.length > 3) { | |
| const e = r.replace(/[^\x20-\x7E]/g, ""); | |
| n.push("'" + e + "'"); | |
| } | |
| const s = t.readPointer(); | |
| n.push("=>"), n.push(regcursive(e, s)); | |
| } catch (e) {} | |
| 0 === t ? n.push("NULL") : 4294967295 === t ? n.push(-1) : t > " " && t < 127 && n.push("'" + String.fromCharCode(t) + "'"); | |
| try { | |
| const e = Process.findModuleByAddress(t); | |
| e && n.push(e.name); | |
| } catch (e) {} | |
| try { | |
| const e = nameFromAddress(t); | |
| e && n.push(e); | |
| } catch (e) {} | |
| return n.join(" "); | |
| } | |
| function dumpRegistersRecursively(e) { | |
| const [t] = e; | |
| return Process.enumerateThreads().filter((e => !t || t === e.id)).map((e => { | |
| const {id: t, state: n, context: r} = e, s = [ "# thread " + t + " " + n ]; | |
| for (const e of Object.keys(r)) try { | |
| const t = regcursive(e, r[e]); | |
| s.push(e + ": " + t); | |
| } catch (t) { | |
| s.push(e); | |
| } | |
| console.log(s.join("\n")); | |
| })), ""; | |
| } | |
| function dumpRegistersR2(e) { | |
| const t = Process.enumerateThreads(), [n] = e, r = n ? t.filter((e => e.id === n)) : t[0].context; | |
| if (!r) return ""; | |
| const s = Object.keys(JSON.parse(JSON.stringify(r))); | |
| s.sort(compareRegisterNames); | |
| return s.map(((e, t) => { | |
| if ("pc" === e || "sp" === e) return ""; | |
| return `ar ${e} = ${r[e] || 0}\n`; | |
| })).join(""); | |
| } | |
| function dumpRegisters(e) { | |
| const [t] = e; | |
| return Process.enumerateThreads().filter((e => !t || e.id === t)).map((e => { | |
| const {id: t, state: n, context: r} = e, s = `tid ${t} ${n}`, o = Object.keys(JSON.parse(JSON.stringify(r))); | |
| o.sort(compareRegisterNames); | |
| return s + "\n" + o.map(((e, t) => alignRight(e, 3) + " : " + padPointer(r[e]))).map(indent).join(""); | |
| })).join("\n\n") + "\n"; | |
| } | |
| function dumpRegistersJson() { | |
| return Process.enumerateThreads(); | |
| } | |
| function getOrSetEnv(e) { | |
| if (0 === e.length) return getEnv().join("\n") + "\n"; | |
| const {key: t, value: n} = getOrSetEnvJson(e); | |
| return t + "=" + n; | |
| } | |
| function getOrSetEnvJson(e) { | |
| if (0 === e.length) return getEnvJson(); | |
| const t = e.join(""), n = t.indexOf("="); | |
| if (-1 !== n) { | |
| const e = t.substring(0, n), r = t.substring(n + 1); | |
| return setenv(e, r, !0), { | |
| key: e, | |
| value: r | |
| }; | |
| } | |
| return { | |
| key: t, | |
| value: getenv(t) | |
| }; | |
| } | |
| function getEnv() { | |
| const e = []; | |
| let t, n = Memory.readPointer(Module.findExportByName(null, "environ")); | |
| for (;!n.isNull() && !(t = n.readPointer()).isNull(); ) e.push(t.readCString()), | |
| n = n.add(Process.pointerSize); | |
| return e; | |
| } | |
| function getEnvJson() { | |
| return getEnv().map((e => { | |
| const t = e.indexOf("="); | |
| return { | |
| key: e.substring(0, t), | |
| value: e.substring(t + 1) | |
| }; | |
| })); | |
| } | |
| function dlopen(e) { | |
| const t = fs.transformVirtualPath(e[0]); | |
| return fs.exist(t) ? Module.load(t) : Module.load(e[0]); | |
| } | |
| function loadFrameworkBundle(e) { | |
| if (!ObjCAvailable) return console.log("dlf: This command requires the objc runtime"), | |
| !1; | |
| const t = e[0], n = ObjC.classes.NSBundle.mainBundle().bundlePath().stringByAppendingPathComponent_(t), r = ObjC.classes.NSBundle.bundleWithPath_(n); | |
| return r.isLoaded() ? (console.log("Bundle already loaded"), !1) : r.load(); | |
| } | |
| function unloadFrameworkBundle(e) { | |
| if (!ObjCAvailable) return console.log("dlf: This command requires the objc runtime"), | |
| !1; | |
| const t = e[0], n = ObjC.classes.NSBundle.mainBundle().bundlePath().stringByAppendingPathComponent_(t), r = ObjC.classes.NSBundle.bundleWithPath_(n); | |
| return r.isLoaded() ? r.unload() : (console.log("Bundle already unloaded"), !1); | |
| } | |
| function changeSelinuxContext(e) { | |
| if (null === _setfilecon) return "Error: cannot find setfilecon symbol"; | |
| const t = e[0], n = Memory.allocUtf8String("u:object_r:frida_file:s0"), r = Memory.allocUtf8String(t), s = _setfilecon(r, n); | |
| return JSON.stringify({ | |
| ret: s.value, | |
| errno: s.errno | |
| }); | |
| } | |
| function formatArgs(e, t) { | |
| const n = [], r = []; | |
| let s, o = 0; | |
| for (let a = 0; a < t.length; a++, o++) { | |
| try { | |
| s = e[o]; | |
| } catch (e) { | |
| console.error("invalid format", a); | |
| } | |
| switch (t[a]) { | |
| case "+": | |
| case "^": | |
| o--; | |
| break; | |
| case "h": | |
| { | |
| let e = 128; | |
| const o = t.slice(a + 1).match(/^[0-9]*/)[0]; | |
| o.length > 0 && (a += o.length, e = +o), r.push(_hexdumpUntrusted(s, e)), n.push(`dump:${r.length} (len=${e})`); | |
| } | |
| break; | |
| case "H": | |
| { | |
| let i = 128; | |
| const c = t.slice(a + 1).match(/^[0-9]*/)[0]; | |
| if (c.length > 0) { | |
| a += c.length; | |
| const t = +c; | |
| t !== o && (i = +e[t]); | |
| } | |
| const l = 65536; | |
| i = i > l ? l : i, r.push(_hexdumpUntrusted(s, i)), n.push(`dump:${r.length} (len=${i})`); | |
| } | |
| break; | |
| case "x": | |
| n.push("" + ptr(s)); | |
| break; | |
| case "c": | |
| n.push("'" + s + "'"); | |
| break; | |
| case "i": | |
| n.push(+s); | |
| break; | |
| case "z": | |
| const i = _readUntrustedUtf8(s); | |
| n.push(JSON.stringify(i)); | |
| break; | |
| case "w": | |
| const c = _readUntrustedUtf16(s); | |
| n.push(JSON.stringify(c)); | |
| break; | |
| case "a": | |
| const l = _readUntrustedAnsi(s); | |
| n.push(JSON.stringify(l)); | |
| break; | |
| case "Z": | |
| const u = _readUntrustedUtf8(s, +e[o + 1]); | |
| n.push(JSON.stringify(u)); | |
| break; | |
| case "S": | |
| const d = _readUntrustedUtf8(Memory.readPointer(s)); | |
| n.push(JSON.stringify(d)); | |
| break; | |
| case "o": | |
| case "O": | |
| if (ObjC.available) if (s.isNull()) n.push("nil"); else if (isObjC(s)) { | |
| const e = new ObjC.Object(s); | |
| "Foundation.__NSSwiftData" === e.$className ? n.push(`${e.$className}: "${ObjC.classes.NSString.alloc().initWithData_encoding_(e, 4).toString()}"`) : n.push(`${e.$className}: "${e.toString()}"`); | |
| } else { | |
| const e = Memory.readCString(s); | |
| e.length > 2 ? n.push(e) : n.push("" + s); | |
| } else n.push(s); | |
| break; | |
| default: | |
| n.push(s); | |
| } | |
| } | |
| return { | |
| args: n, | |
| dumps: r | |
| }; | |
| } | |
| function cloneArgs(e, t) { | |
| const n = []; | |
| let r = 0; | |
| for (let s = 0; s < t.length; s++, r++) { | |
| const o = e[r]; | |
| switch (t[s]) { | |
| case "+": | |
| case "^": | |
| r--; | |
| break; | |
| default: | |
| n.push(o); | |
| } | |
| } | |
| return n; | |
| } | |
| function _hexdumpUntrusted(e, t) { | |
| try { | |
| return "number" == typeof t ? hexdump(e, { | |
| length: t | |
| }) : hexdump(e); | |
| } catch (t) { | |
| return `hexdump at ${e} failed: ${t}`; | |
| } | |
| } | |
| function _readUntrustedUtf8(e, t) { | |
| try { | |
| return "number" == typeof t ? Memory.readUtf8String(ptr(e), t) : Memory.readUtf8String(ptr(e)); | |
| } catch (t) { | |
| return "invalid UTF-8" !== t.message ? Memory.readCString(ptr(e)) : "(invalid utf8)"; | |
| } | |
| } | |
| function _readUntrustedUtf16(e, t) { | |
| try { | |
| return "number" == typeof t ? Memory.readUtf16String(ptr(e), t) : Memory.readUtf16String(ptr(e)); | |
| } catch (t) { | |
| return "invalid UTF-16" !== t.message ? Memory.readCString(ptr(e)) : "(invalid utf16)"; | |
| } | |
| } | |
| function _readUntrustedAnsi(e, t) { | |
| try { | |
| return "number" == typeof t ? Memory.readAnsiString(ptr(e), t) : Memory.readAnsiString(ptr(e)); | |
| } catch (t) { | |
| return "invalid Ansi" !== t.message ? Memory.readCString(ptr(e)) : "(invalid Ansi)"; | |
| } | |
| } | |
| function traceList() { | |
| let e = 0; | |
| return traceListeners.map((t => [ e++, t.hits, t.at, t.source, t.moduleName, t.name, t.args ].join("\t"))).join("\n") + "\n"; | |
| } | |
| function traceListJson() { | |
| return traceListeners.map((e => JSON.stringify(e))).join("\n") + "\n"; | |
| } | |
| function getPtr(e) { | |
| if ("string" == typeof e && (e = e.trim()), !e || "$$" === e) return ptr(global.r2frida.offset); | |
| if (e.startsWith("swift:")) { | |
| if (!SwiftAvailable) return ptr(0); | |
| const t = e.substring(6).split("."); | |
| if (2 !== t.length) return ptr(0); | |
| const n = t[0], r = t[1]; | |
| if (!Swift.classes[n]) return void console.error("Missing class " + n); | |
| const s = Swift.classes[n]; | |
| let o = ptr(0); | |
| for (const e of s.$methods) r === e.name && (o = e.address); | |
| return e; | |
| } | |
| if (e.startsWith("java:")) return e; | |
| if (e.startsWith("objc:")) { | |
| const t = -1 !== e.indexOf("^"); | |
| -1 !== t && (e = e.replace("^", "")); | |
| const n = e.endsWith("$"); | |
| n && (e = e.substring(0, e.length - 1)); | |
| let r = (e = e.substring(5)).indexOf("."); | |
| if (-1 === r && (r = e.indexOf(":"), -1 === r)) throw new Error("r2frida's ObjC class syntax is: objc:CLASSNAME.METHOD"); | |
| const s = e.substring(0, r), o = e.substring(r + 1), a = ObjC.classes[s]; | |
| if (void 0 === a) throw new Error("Class " + s + " not found"); | |
| let i = null, c = !1, l = null; | |
| for (const e of a.$ownMethods) { | |
| const r = a[e]; | |
| if (-1 !== e.indexOf(o)) { | |
| if (t && !e.substring(2).startsWith(o)) continue; | |
| if (n && !e.endsWith(o)) continue; | |
| i && (c || (console.error(i.implementation, l), c = !0), console.error(r.implementation, e)), | |
| i = r, l = e; | |
| } | |
| } | |
| return c ? ptr(0) : i ? i.implementation : ptr(0); | |
| } | |
| try { | |
| if ("0x" === e.substring(0, 2)) return ptr(e); | |
| } catch (e) {} | |
| return Module.findExportByName(null, e); | |
| } | |
| function traceHook(e) { | |
| if (0 === e.length) return JSON.stringify(tracehooks, null, 2); | |
| const t = e[0]; | |
| return void 0 !== t && tracehookSet(t, e.slice(1).join(" ")), ""; | |
| } | |
| function traceFormat(e) { | |
| if (0 === e.length) return traceList(); | |
| let t, n; | |
| const r = e[0]; | |
| if (2 === e.length ? (t = "" + getPtr(r), n = e[1]) : 1 === e.length ? (t = "" + getPtr(r), | |
| n = "") : (t = global.r2frida.offset, n = e[0]), haveTraceAt(t)) return "There's already a trace in here"; | |
| const s = -1 !== n.indexOf("^"), o = -1 !== n.indexOf("+"), a = config.getString("hook.usecmd"), i = getModuleByAddress(t), c = Interceptor.attach(ptr(t), { | |
| myArgs: [], | |
| myBacktrace: [], | |
| keepArgs: [], | |
| onEnter: function(e) { | |
| if (l.hits++, s) { | |
| const t = formatArgs(e, n); | |
| this.myArgs = t.args, this.myDumps = t.dumps; | |
| } else this.keepArgs = cloneArgs(e, n); | |
| if (o && (this.myBacktrace = Thread.backtrace(this.context).map(DebugSymbol.fromAddress)), | |
| s) { | |
| const e = { | |
| source: "dtf", | |
| name: r, | |
| address: t, | |
| timestamp: new Date, | |
| values: this.myArgs | |
| }; | |
| if (config.getBoolean("hook.backtrace") && (e.backtrace = Thread.backtrace(this.context).map(DebugSymbol.fromAddress)), | |
| "json" === config.getString("hook.output")) traceEmit(e); else { | |
| let n = `[dtf onEnter][${e.timestamp}] ${r}@${t} - args: ${this.myArgs.join(", ")}`; | |
| config.getBoolean("hook.backtrace") && (n += ` backtrace: ${e.backtrace.toString()}`); | |
| for (let e = 0; e < this.myDumps.length; e++) n += `\ndump:${e + 1}\n${this.myDumps[e]}`; | |
| traceEmit(n); | |
| } | |
| a.length > 0 && console.log("[r2cmd]" + a); | |
| } | |
| }, | |
| onLeave: function(e) { | |
| if (!s) { | |
| const s = formatArgs(this.keepArgs, n); | |
| this.myArgs = s.args, this.myDumps = s.dumps; | |
| const o = { | |
| source: "dtf", | |
| name: r, | |
| address: t, | |
| timestamp: new Date, | |
| values: this.myArgs, | |
| retval: e | |
| }; | |
| if (config.getBoolean("hook.backtrace") && (o.backtrace = Thread.backtrace(this.context).map(DebugSymbol.fromAddress)), | |
| "json" === config.getString("hook.output")) traceEmit(o); else { | |
| let n = `[dtf onLeave][${o.timestamp}] ${r}@${t} - args: ${this.myArgs.join(", ")}. Retval: ${e.toString()}`; | |
| config.getBoolean("hook.backtrace") && (n += ` backtrace: ${o.backtrace.toString()}`); | |
| for (let e = 0; e < this.myDumps.length; e++) n += `\ndump:${e + 1}\n${this.myDumps[e]}`; | |
| traceEmit(n); | |
| } | |
| a.length > 0 && console.log("[r2cmd]" + a); | |
| } | |
| } | |
| }), l = { | |
| source: "dtf", | |
| hits: 0, | |
| at: ptr(t), | |
| name: r, | |
| moduleName: i ? i.name : "", | |
| format: n, | |
| listener: c | |
| }; | |
| return traceListeners.push(l), !0; | |
| } | |
| function traceListenerFromAddress(e) { | |
| const t = traceListeners.filter((t => "" + e == "" + t.at)); | |
| return t.length > 0 ? t[0] : void 0; | |
| } | |
| function traceCountFromAddress(e) { | |
| const t = traceListenerFromAddress(e); | |
| return t ? t.hits : 0; | |
| } | |
| function traceNameFromAddress(e) { | |
| const t = traceListenerFromAddress(e); | |
| return t ? t.moduleName + ":" + t.name : ""; | |
| } | |
| function traceLogDumpQuiet() { | |
| return logs.map((({address: e, timestamp: t}) => [ e, t, traceCountFromAddress(e), traceNameFromAddress(e) ].join(" "))).join("\n") + "\n"; | |
| } | |
| function traceLogDumpJson() { | |
| return JSON.stringify(logs); | |
| } | |
| function traceLogDumpR2() { | |
| let e = ""; | |
| for (const t of logs) t.script && (e += t.script); | |
| return e; | |
| } | |
| function objectToString(e) { | |
| return "(" + Object.keys(e).map((t => { | |
| try { | |
| const n = ptr(e[t]); | |
| if (isObjC(n)) { | |
| return t + ": " + new ObjC.Object(n).toString(); | |
| } | |
| const r = Memory.readCString(n); | |
| if (r.length > 2) return t + ': "' + r + '"'; | |
| } catch (e) {} | |
| return t + ": " + e[t]; | |
| })).join(" ") + ")"; | |
| } | |
| function tracelogToString(e) { | |
| return [ e.source, e.name || e.address, objectToString(e.values) ].join("\t") + (e.backtrace ? e.backtrace.map((e => [ "", e.address, e.moduleName, e.name ].join("\t"))).join("\n") + "\n" : ""); | |
| } | |
| function traceLogDump() { | |
| return logs.map(tracelogToString).join("\n") + "\n"; | |
| } | |
| function traceLogClear(e) { | |
| return console.error("ARGS", JSON.stringify(e)), traceLogClearAll(); | |
| } | |
| function traceLogClearAll() { | |
| return logs = [], traces = {}, ""; | |
| } | |
| function traceEmit(e) { | |
| const t = config.getString("file.log"); | |
| t.length > 0 ? send(wrapStanza("log-file", { | |
| filename: t, | |
| message: e | |
| })) : traceLog(e), config.getBoolean("hook.logs") && logs.push(e), global.r2frida.logs = logs; | |
| } | |
| function traceLog(e) { | |
| config.getBoolean("hook.verbose") && send(wrapStanza("log", { | |
| message: e | |
| })); | |
| } | |
| function haveTraceAt(e) { | |
| try { | |
| for (const t of traceListeners) if (0 === t.at.compare(e)) return !0; | |
| } catch (e) { | |
| console.error(e); | |
| } | |
| return !1; | |
| } | |
| function traceRegs(e) { | |
| if (e.length < 1) return "Usage: dtr [name|address] [reg ...]"; | |
| const t = getPtr(e[0]); | |
| if (haveTraceAt(t)) return "There's already a trace in here"; | |
| const n = e.slice(1), r = getModuleByAddress(t), s = Interceptor.attach(t, (function(e) { | |
| o.hits++; | |
| const r = {}; | |
| n.forEach((e => { | |
| let t, n = e; | |
| if (-1 !== e.indexOf("=")) { | |
| const r = e.split("="); | |
| this.context[r[0]] = ptr(r[1]), n = r[0], t = r[1]; | |
| } else try { | |
| const n = ptr(this.context[e]); | |
| t = n; | |
| let r = Memory.readCString(n); | |
| r && (r = " (" + r + ")", t += r); | |
| } catch (e) {} | |
| r[n] = t; | |
| })); | |
| const s = { | |
| source: "dtr", | |
| address: t, | |
| timestamp: new Date, | |
| values: r | |
| }; | |
| config.getBoolean("hook.backtrace") && (s.backtrace = Thread.backtrace(this.context).map(DebugSymbol.fromAddress)); | |
| if ("json" === config.getString("hook.output")) traceEmit(s); else { | |
| let e = `[dtr][${s.timestamp}] ${t} - registers: ${JSON.stringify(r)}`; | |
| config.getBoolean("hook.backtrace") && (e += ` backtrace: ${s.backtrace.toString()}`), | |
| traceEmit(e); | |
| } | |
| })); | |
| const o = { | |
| source: "dtr", | |
| hits: 0, | |
| at: t, | |
| moduleName: r ? r.name : "unknown", | |
| name: e[0], | |
| listener: s, | |
| args: n | |
| }; | |
| return traceListeners.push(o), ""; | |
| } | |
| function traceHere() { | |
| return [ r2frida.offset ].forEach((e => { | |
| const t = DebugSymbol.fromAddress(ptr(e)) || "" + ptr(e), n = Interceptor.attach(ptr(e), (function() { | |
| const t = Thread.backtrace(this.context).map(DebugSymbol.fromAddress), n = nameFromAddress(e); | |
| console.log("Trace here probe hit at " + e + "::" + n + "\n\t" + t.join("\n\t")); | |
| })); | |
| traceListeners.push({ | |
| at: t, | |
| listener: n | |
| }); | |
| })), !0; | |
| } | |
| function traceR2(e) { | |
| return traceListeners.map((e => `dt+ ${e.at} ${e.hits}`)).join("\n") + "\n"; | |
| } | |
| function dumpJavaArguments(e) { | |
| let t = ""; | |
| try { | |
| for (const n of e) try { | |
| t += n.toString() + " "; | |
| } catch (e) {} | |
| } catch (e) {} | |
| return t; | |
| } | |
| function traceJavaConstructors(e) { | |
| javaPerform((function() { | |
| Java.use(e).$init.overloads.forEach((t => { | |
| t.implementation = function() { | |
| if (console.log("dt", e, "(", dumpJavaArguments(arguments), ")"), config.getBoolean("hook.backtrace")) { | |
| const e = Java.use("java.lang.Throwable").$new().getStackTrace().map((e => e.toString())).join("\n- ") + "\n"; | |
| console.log("-", e); | |
| } | |
| return t.apply(this, arguments); | |
| }; | |
| })); | |
| })); | |
| } | |
| function traceSwift(e, t) { | |
| if (!SwiftAvailable) return; | |
| const n = getPtr("swift:" + e + "." + t); | |
| if (ptr(0).equals(n)) return void console.error("Missing method " + t + " in class " + e); | |
| Swift.Interceptor.Attach(target, (function(n) { | |
| traceEmit([ "[SWIFT]", e, t, JSON.stringify(n) ].join(" ")); | |
| })); | |
| } | |
| function traceJava(e, t) { | |
| javaPerform((function() { | |
| const n = Java.use("java.lang.Throwable"); | |
| javaUse(e)[t].implementation = function(r) { | |
| const s = this[t](), o = config.getBoolean("hook.backtrace") ? n.$new().getStackTrace().map((e => e.toString())) : [], a = { | |
| source: "dt", | |
| klass: e, | |
| method: t, | |
| backtrace: o, | |
| timestamp: new Date, | |
| result: s, | |
| values: r | |
| }; | |
| if ("json" === config.getString("hook.output")) traceEmit(a); else { | |
| let n = `[JAVA TRACE][${a.timestamp}] ${e}:${t} - args: ${JSON.stringify(r)}. Return value: ${s.toString()}`; | |
| config.getBoolean("hook.backtrace") && (n += ` backtrace: \n${a.backtrace.toString().split(",").join("\nat ")}\n`), | |
| traceEmit(n); | |
| } | |
| return s; | |
| }; | |
| })); | |
| } | |
| function traceQuiet(e) { | |
| return traceListeners.map((({address: e, hits: t, moduleName: n, name: r}) => [ e, t, n + ":" + r ].join(" "))).join("\n") + "\n"; | |
| } | |
| function traceJson(e) { | |
| return 0 === e.length ? traceListJson() : e[0].startsWith("java:") ? void traceReal(e[0]) : new Promise((function(t, n) { | |
| !function r() { | |
| const s = e.pop(); | |
| if (void 0 === s) return t(""); | |
| const o = getPtr(s); | |
| o ? (traceReal(s, o), r()) : numEval(s).then((function(e) { | |
| console.error(traceReal(s, e)), r(); | |
| })).catch(n); | |
| }(); | |
| })); | |
| } | |
| function typesR2(e) { | |
| let t = ""; | |
| if (SwiftAvailable) switch (e.length) { | |
| case 0: | |
| for (const e in Swift.modules) t += e + "\n"; | |
| break; | |
| case 1: | |
| try { | |
| const n = e[0], r = Swift && Swift.modules ? Swift.modules[n] : null; | |
| if (!r) throw new Error("No module named like this."); | |
| let s = r.enums; | |
| if (s) for (const e of Object.keys(s)) { | |
| t += "td enum " + e + " {"; | |
| const n = []; | |
| if (s[e].$fields) for (const t of s[e].$fields) n.push(t.name); | |
| t += n.join(", "), t += "}\n"; | |
| } | |
| if (s = Swift.modules[n].classes, s) for (const e of Object.keys(s)) if (s[e].$methods) for (const r of s[e].$methods) { | |
| t += "f swift." + n + "." + e + "." + (r.type + "_" + (r.name ? r.name : r.address)) + " = " + r.address + "\n"; | |
| } | |
| if (s = Swift.modules[n].structs, s) for (const e of Object.keys(s)) { | |
| if (t += '"td struct ' + n + "." + e + " {", s[e].$fields) for (const n of s[e].$fields) t += "int " + n.name + ";"; | |
| t += '}"\n'; | |
| } | |
| } catch (e) { | |
| t += e; | |
| } | |
| } | |
| return t; | |
| } | |
| function types(e) { | |
| return SwiftAvailable ? swiftTypes(e) : ""; | |
| } | |
| function swiftTypes(e) { | |
| if (!SwiftAvailable) return ""; | |
| let t = ""; | |
| switch (e.length) { | |
| case 0: | |
| for (const e in Swift.modules) t += e + "\n"; | |
| break; | |
| case 1: | |
| try { | |
| const n = e[0], r = Swift && Swift.modules ? Swift.modules[n] : null; | |
| if (!r) throw new Error("No module named like this."); | |
| t += "module " + n + "\n\n"; | |
| let s = r.enums; | |
| if (s) { | |
| for (const e of Object.keys(s)) { | |
| if (e.$conformances && (t += "// conforms to " + s[e].$conformances.join(", ") + "\n"), | |
| t += "enum " + e + " {\n", s[e].$fields) for (const n of s[e].$fields) t += " " + n.name + ",\n"; | |
| t += "}\n"; | |
| } | |
| t += "\n"; | |
| } | |
| if (s = Swift.modules[n].classes, s) { | |
| for (const e of Object.keys(s)) { | |
| if (t += "class " + e + " {\n", s[e].$fields) for (const n of s[e].$fields) t += " " + n.name + " " + n.typeName + "\n"; | |
| if (s[e].$methods) for (const n of s[e].$methods) { | |
| t += " fn " + (n.type + (n.name ? n.name : n.address)) + "() // " + n.address + "\n"; | |
| } | |
| t += "}\n"; | |
| } | |
| t += "\n"; | |
| } | |
| if (s = Swift.modules[n].structs, s) { | |
| for (const e of Object.keys(s)) { | |
| if (e.$conformances && (t += "// conforms to " + s[e].$conformances.join(", ") + "\n"), | |
| t += "struct " + e + " {\n", s[e].$fields) for (const n of s[e].$fields) t += " " + n.name + " " + n.typeName + "\n"; | |
| t += "}\n"; | |
| } | |
| t += "\n"; | |
| } | |
| if (s = r.protocols, s) { | |
| for (const e of Object.keys(s)) s[e].isClassOnly && (t += "class "), t += "protocol " + e + " (requires: " + s[e].numRequirements + ")\n"; | |
| t += "\n"; | |
| } | |
| } catch (e) { | |
| t += e; | |
| } | |
| } | |
| return t; | |
| } | |
| function trace(e) { | |
| return 0 === e.length ? traceList() : traceJson(e); | |
| } | |
| function tracehookSet(e, t, n) { | |
| return null === e ? (console.error("Name was not resolved"), !1) : (tracehooks[e] = { | |
| format: t, | |
| callback: n | |
| }, !0); | |
| } | |
| function arrayBufferToHex(e) { | |
| if ("object" != typeof e || null === e || "number" != typeof e.byteLength) throw new TypeError("Expected input to be an ArrayBuffer"); | |
| const t = new Uint8Array(e); | |
| let n, r = ""; | |
| for (let e = 0; e < t.length; e++) n = t[e].toString(16), r += 1 === n.length ? "0" + n : n; | |
| return r; | |
| } | |
| function tracehook(e, t) { | |
| const n = nameFromAddress(e), r = tracehooks[n], s = []; | |
| if (r && r.format) for (const e of r.format.split(" ")) { | |
| const [n, r] = e.split(":"); | |
| switch (n) { | |
| case "i": | |
| s.push(+t[r]); | |
| break; | |
| case "s": | |
| { | |
| const [e, n] = r.split(","), o = ptr(t[e]), a = +t[n]; | |
| s.push(Memory.readCString(o, a)); | |
| } | |
| break; | |
| case "z": | |
| s.push(Memory.readCString(ptr(t[+r]))); | |
| break; | |
| case "v": | |
| { | |
| const [e, n] = r.split(","), o = ptr(t[e]), a = Memory.readByteArray(o, +t[n]); | |
| s.push(arrayBufferToHex(a)); | |
| } | |
| } | |
| } | |
| return s; | |
| } | |
| function traceReal(e, t) { | |
| if (0 === arguments.length) return traceList(); | |
| if (e.startsWith("swift:")) { | |
| const t = e.substring(6), n = t.lastIndexOf("."); | |
| if (-1 === n) return 'Invalid syntax for swift uri. Use "swift:KLASS.METHOD"'; | |
| return traceSwift(t.substring(0, n), t.substring(n + 1)); | |
| } | |
| if (e.startsWith("java:")) { | |
| const t = e.substring(5); | |
| if (javaUse(t)) console.error("Tracing class constructors"), traceJavaConstructors(t); else { | |
| const e = t.lastIndexOf("."); | |
| if (-1 !== e) { | |
| traceJava(t.substring(0, e), t.substring(e + 1)); | |
| } else console.log("Invalid java method name. Use :dt java:package.class.method"); | |
| } | |
| return; | |
| } | |
| const n = ptr(t); | |
| if (haveTraceAt(n)) return "There's already a trace in here"; | |
| const r = getModuleByAddress(n), s = Interceptor.attach(n, (function(e) { | |
| const t = tracehook(n, e), r = { | |
| source: "dt", | |
| address: n, | |
| timestamp: new Date, | |
| values: t | |
| }; | |
| o.hits++, "json" === config.getString("hook.output") ? traceEmit(r) : traceEmit(`[dt][${r.timestamp}] ${n} - args: ${JSON.stringify(t)}`); | |
| })), o = { | |
| source: "dt", | |
| at: n, | |
| hits: 0, | |
| name: e, | |
| moduleName: r ? r.name : "unknown", | |
| args: "", | |
| listener: s | |
| }; | |
| return traceListeners.push(o), ""; | |
| } | |
| function clearAllTrace(e) { | |
| return traceListeners.splice(0).forEach((e => e.listener ? e.listener.detach() : null)), | |
| ""; | |
| } | |
| function clearTrace(e) { | |
| if (e.length > 0 && +e[0] > 0) { | |
| const t = [], n = +e[0]; | |
| for (let e = 0; e < traceListeners.length; e++) { | |
| const r = traceListeners[e]; | |
| e === n ? r.listener.detach() : t.push(r); | |
| } | |
| } | |
| return ""; | |
| } | |
| function interceptHelp(e) { | |
| return "Usage: di[0,1,-1,s] [addr] : intercepts function method and replace the return value.\n"; | |
| } | |
| function interceptFunHelp(e) { | |
| return "Usage: dif[0,1,-1,s] [addr] [str] [param_types]: intercepts function method, call it, and replace the return value.\n"; | |
| } | |
| function interceptRetJava(e, t, n) { | |
| javaPerform((function() { | |
| javaUse(e)[t].implementation = function(r) { | |
| const s = new Date; | |
| switch ("json" === config.getString("hook.output") ? traceEmit({ | |
| source: "java", | |
| class: e, | |
| method: t, | |
| returnValue: n, | |
| timestamp: s | |
| }) : traceEmit(`[JAVA TRACE][${s}] Intercept return for ${e}:${t} with ${n}`), n) { | |
| case 0: | |
| return !1; | |
| case 1: | |
| return !0; | |
| case -1: | |
| return -1; | |
| } | |
| return n; | |
| }; | |
| })); | |
| } | |
| function interceptFunRetJava(e, t, n, r) { | |
| javaPerform((function() { | |
| javaUse(e)[t].overload(r).implementation = function(r) { | |
| const s = new Date; | |
| switch ("json" === config.getString("hook.output") ? traceEmit({ | |
| source: "java", | |
| class: e, | |
| methodName: t, | |
| returnValue: n, | |
| timestamp: s | |
| }) : traceEmit(`[JAVA TRACE][${s}] Intercept return for ${e}:${t} with ${n}`), this[t](r), | |
| n) { | |
| case 0: | |
| return !1; | |
| case 1: | |
| return !0; | |
| case -1: | |
| return -1; | |
| } | |
| return n; | |
| }; | |
| })); | |
| } | |
| function parseTargetJavaExpression(e) { | |
| let t = e.substring("java:".length); | |
| const n = t.lastIndexOf("."); | |
| if (-1 !== n) { | |
| const e = t.substring(n + 1); | |
| return t = t.substring(0, n), [ t, e ]; | |
| } | |
| throw new Error("Error: Wrong java method syntax"); | |
| } | |
| function interceptRet(e, t) { | |
| if (e.startsWith("java:")) try { | |
| const n = parseTargetJavaExpression(e, t); | |
| return interceptRetJava(n[0], n[1], t); | |
| } catch (e) { | |
| return e.message; | |
| } | |
| const n = getPtr(e), r = config.getString("hook.usecmd"); | |
| Interceptor.replace(n, new NativeCallback((function() { | |
| return r.length > 0 && console.log("[r2cmd]" + r), ptr(t); | |
| }), "pointer", [ "pointer" ])); | |
| } | |
| function interceptRet0(e) { | |
| return interceptRet(e[0], 0); | |
| } | |
| function interceptRetString(e) { | |
| return interceptRet(e[0], e[1]); | |
| } | |
| function interceptRetInt(e) { | |
| return interceptRet(e[0], e[1]); | |
| } | |
| function interceptRet1(e) { | |
| return interceptRet(e[0], 1); | |
| } | |
| function interceptRet_1(e) { | |
| return interceptRet(e[0], -1); | |
| } | |
| function interceptFunRet(e, t, n) { | |
| if (e.startsWith("java:")) { | |
| const r = parseTargetJavaExpression(e, t); | |
| return interceptFunRetJava(r[0], r[1], t, n); | |
| } | |
| const r = getPtr(e); | |
| Interceptor.attach(r, { | |
| onLeave(e) { | |
| e.replace(ptr(t)); | |
| } | |
| }); | |
| } | |
| function interceptFunRet0(e) { | |
| return interceptFunRet(e[0], 0, e[1]); | |
| } | |
| function interceptFunRetString(e) { | |
| const t = e[0], n = e[2]; | |
| return interceptFunRet(t, e[1], n); | |
| } | |
| function interceptFunRetInt(e) { | |
| const t = e[0], n = e[2]; | |
| return interceptFunRet(t, e[1], n); | |
| } | |
| function interceptFunRet1(e) { | |
| return interceptFunRet(e[0], 1, e[1]); | |
| } | |
| function interceptFunRet_1(e) { | |
| return interceptFunRet(e[0], -1, e[1]); | |
| } | |
| function getenv(e) { | |
| return Memory.readUtf8String(_getenv(Memory.allocUtf8String(e))); | |
| } | |
| function setenv(e, t, n) { | |
| return _setenv(Memory.allocUtf8String(e), Memory.allocUtf8String(t), n ? 1 : 0); | |
| } | |
| function getWindowsUserNameA() { | |
| const e = sym("GetUserNameA", "int", [ "pointer", "pointer" ]), t = Memory.allocUtf8String("A".repeat(4096)); | |
| return e(t, Memory.allocUtf8String("A".repeat(4096))) ? Memory.readCString(t) : ""; | |
| } | |
| function stalkTraceFunction(e) { | |
| return _stalkTraceSomething(_stalkFunctionAndGetEvents, e); | |
| } | |
| function stalkTraceFunctionR2(e) { | |
| return _stalkTraceSomethingR2(_stalkFunctionAndGetEvents, e); | |
| } | |
| function stalkTraceFunctionJson(e) { | |
| return _stalkTraceSomethingJson(_stalkFunctionAndGetEvents, e); | |
| } | |
| function stalkTraceEverything(e) { | |
| return 0 === e.length ? "Warnnig: dts is experimental and slow\nUsage: dts [symbol]" : _stalkTraceSomething(_stalkEverythingAndGetEvents, e); | |
| } | |
| function stalkTraceEverythingR2(e) { | |
| return 0 === e.length ? "Warnnig: dts is experimental and slow\nUsage: dts* [symbol]" : _stalkTraceSomethingR2(_stalkEverythingAndGetEvents, e); | |
| } | |
| function stalkTraceEverythingJson(e) { | |
| return 0 === e.length ? "Warnnig: dts is experimental and slow\nUsage: dtsj [symbol]" : _stalkTraceSomethingJson(_stalkEverythingAndGetEvents, e); | |
| } | |
| function _stalkTraceSomething(e, t) { | |
| return e(t, ((e, t) => { | |
| let r; | |
| const s = [], o = Object.keys(t); | |
| for (const a of o) s.push(`; --- thread ${a} --- ;`), e ? s.push(..._mapBlockEvents(t[a], (e => { | |
| const t = n(e, r); | |
| return r = getSymbolName(e), t; | |
| }), ((e, t) => (r = null, "")))) : s.push(...t[a].map((e => { | |
| const t = e[0], s = e[1], o = n(t, r, s); | |
| return r = getSymbolName(t), o; | |
| }))); | |
| return s.join("\n") + "\n"; | |
| })); | |
| function n(e, t, n) { | |
| let r = disasm(e, 1, t); | |
| return r.endsWith("\n") && (r = r.slice(0, -1)), n && (r += ` ; ${n} ${getSymbolName(n)}`), | |
| r; | |
| } | |
| } | |
| function _stalkTraceSomethingR2(e, t) { | |
| return e(t, ((e, t) => { | |
| const n = [], r = Object.keys(t); | |
| for (const s of r) e ? n.push(..._mapBlockEvents(t[s], (e => `dt+ ${e} 1`))) : n.push(...t[s].map((e => { | |
| const t = [], n = e[0]; | |
| t.push(`dt+ ${n} 1`); | |
| const r = e[1]; | |
| return r && t.push(`CC ${r} ${getSymbolName(r)} @ ${n}`), t.join("\n") + "\n"; | |
| }))); | |
| return n.join("\n") + "\n"; | |
| })); | |
| } | |
| function _stalkTraceSomethingJson(e, t) { | |
| return e(t, ((e, t) => ({ | |
| event: config.get("stalker.event"), | |
| threads: t | |
| }))); | |
| } | |
| function _stalkFunctionAndGetEvents(e, t) { | |
| _requireFridaVersion(10, 3, 13); | |
| const n = getPtr(e[0]), r = { | |
| event: config.get("stalker.event"), | |
| timeout: config.get("stalker.timeout"), | |
| stalkin: config.get("stalker.in") | |
| }, s = "block" === r.event || "compile" === r.event, o = stalkFunction(r, n).then((e => t(s, e))); | |
| return breakpointContinue([]), o; | |
| } | |
| function _stalkEverythingAndGetEvents(e, t) { | |
| _requireFridaVersion(10, 3, 13); | |
| const n = e.length > 0 ? +e[0] : null, r = { | |
| event: config.get("stalker.event"), | |
| timeout: config.get("stalker.timeout"), | |
| stalkin: config.get("stalker.in") | |
| }, s = "block" === r.event || "compile" === r.event, o = stalkEverything(r, n).then((e => t(s, e))); | |
| return breakpointContinue([]), o; | |
| } | |
| function getSymbolName(e) { | |
| const t = DebugSymbol.fromAddress(e); | |
| return null === t.name || 0 === t.name.indexOf("0x") ? "" : t.name; | |
| } | |
| function _requireFridaVersion(e, t, n) { | |
| const r = [ e, t, n ], s = Frida.version.split("."); | |
| for (let o = 0; o < s.length; o++) { | |
| if (s[o] > r[o]) return; | |
| if (s[o] < r[o]) throw new Error(`Frida v${e}.${t}.${n} or higher required for this (you have v${Frida.version}).`); | |
| } | |
| } | |
| function _mapBlockEvents(e, t, n) { | |
| const r = []; | |
| return e.forEach((([e, s]) => { | |
| "function" == typeof n && r.push(n(e, s)); | |
| let o = e; | |
| for (;o < s; ) { | |
| const [e, n] = _tolerantInstructionParse(o); | |
| null !== e && r.push(t(o)), o = n; | |
| } | |
| })), r; | |
| } | |
| function _tolerantInstructionParse(e) { | |
| let t = null, n = e; | |
| try { | |
| t = Instruction.parse(n), n = t.next; | |
| } catch (e) { | |
| if ("invalid instruction" !== e.message && e.message !== `access violation accessing ${n}`) throw e; | |
| switch (e.message.indexOf("access violation"), Process.arch) { | |
| case "arm64": | |
| n = n.add(4); | |
| break; | |
| case "arm": | |
| n = n.add(2); | |
| break; | |
| default: | |
| n = n.add(1); | |
| } | |
| } | |
| return [ t, n ]; | |
| } | |
| function compareRegisterNames(e, t) { | |
| const n = parseRegisterIndex(e), r = parseRegisterIndex(t), s = null !== n, o = null !== r; | |
| if (s && o) return n - r; | |
| if (s === o) { | |
| const n = e.length, r = t.length; | |
| return n === r ? e.localeCompare(t) : n > r ? 1 : -1; | |
| } | |
| return s ? 1 : -1; | |
| } | |
| function parseRegisterIndex(e) { | |
| const t = e.length; | |
| for (let n = 1; n < t; n++) { | |
| const t = parseInt(e.substr(n)); | |
| if (!isNaN(t)) return t; | |
| } | |
| return null; | |
| } | |
| function indent(e, t) { | |
| return 0 === t ? e : t % 3 == 0 ? "\n" + e : "\t" + e; | |
| } | |
| function alignRight(e, t) { | |
| let n = e; | |
| for (;n.length < t; ) n = " " + n; | |
| return n; | |
| } | |
| function padPointer(e) { | |
| let t = e.toString(16); | |
| const n = 2 * pointerSize; | |
| for (;t.length < n; ) t = "0" + t; | |
| return "0x" + t; | |
| } | |
| const requestHandlers = { | |
| safeio: () => { | |
| r2frida.safeio = !0; | |
| }, | |
| read: io.read, | |
| write: io.write, | |
| state: state, | |
| perform: perform, | |
| evaluate: evaluate | |
| }; | |
| function state(e, t) { | |
| return r2frida.offset = e.offset, suspended = e.suspended, [ {}, null ]; | |
| } | |
| function isPromise(e) { | |
| return null !== e && "object" == typeof e && "function" == typeof e.then; | |
| } | |
| function stalkTraceEverythingHelp() { | |
| return "Usage: dts[j*] [symbol|address] - Trace given symbol using the Frida Stalker\ndtsf[*j] [sym|addr] Trace address or symbol using the stalker\ndts[*j] seconds Trace all threads for given seconds using the stalker\n"; | |
| } | |
| function getHelpMessage(e) { | |
| return Object.keys(commandHandlers).sort().filter((t => !e || t.startsWith(e))).map((e => " " + e + "\t" + commandHandlers[e].name.replace(/(?:^|\.?)([A-Z])/g, (function(e, t) { | |
| return " " + t.toLowerCase(); | |
| })).replace(/^_/, ""))).join("\n") + "\n"; | |
| } | |
| function perform(e) { | |
| const {command: t} = e, n = t.split(/ /).map((e => e.trim())).filter((e => e)), [r, ...s] = n; | |
| if (void 0 === r) { | |
| return [ { | |
| value: normalizeValue(getHelpMessage("")) | |
| }, null ]; | |
| } | |
| if (r.length > 0 && r.endsWith("?") && !commandHandlers[r]) { | |
| return [ { | |
| value: normalizeValue(getHelpMessage(r.substring(0, r.length - 1))) | |
| }, null ]; | |
| } | |
| const o = global.r2frida.commandHandler(r), a = void 0 !== o ? o : commandHandlers[r]; | |
| if (void 0 === a) throw new Error("Unhandled command: " + r); | |
| if (isPromise(a)) throw new Error("The handler can't be a promise"); | |
| const i = a(s); | |
| if (isPromise(i)) return new Promise(((e, t) => i.then((t => { | |
| e([ { | |
| value: normalizeValue(t) | |
| }, null ]); | |
| })).catch(t))); | |
| const c = normalizeValue(i); | |
| return "" === c || "null" === c || null == c ? [ {}, null ] : [ { | |
| value: c | |
| }, null ]; | |
| } | |
| function normalizeValue(e) { | |
| return null == typeof e ? null : void 0 === e ? "undefined" : "string" == typeof e ? e : JSON.stringify(e); | |
| } | |
| function evaluate(e) { | |
| return new Promise((t => { | |
| let {code: n, ccode: r} = e; | |
| const s = ObjCAvailable && hasMainLoop(); | |
| function o() { | |
| let e; | |
| try { | |
| r && (n = "\nvar m = new CModule(`" + r + "`);\nconst main = new NativeFunction(m.main, 'int', []);\nmain();\n"); | |
| const t = (0, eval)(n); | |
| global._ = t, e = t; | |
| } catch (t) { | |
| e = "throw new " + t.name + '("' + t.message + '")'; | |
| } | |
| t([ { | |
| value: e | |
| }, null ]); | |
| } | |
| ObjCAvailable && s && !suspended ? ObjC.schedule(ObjC.mainQueue, o) : o(); | |
| })); | |
| } | |
| function hasMainLoop() { | |
| const e = Module.findExportByName(null, "CFRunLoopGetMain"); | |
| if (null === e) return !1; | |
| const t = Module.findExportByName(null, "CFRunLoopCopyCurrentMode"); | |
| if (null === t) return !1; | |
| const n = new NativeFunction(e, "pointer", []), r = new NativeFunction(t, "pointer", [ "pointer" ]), s = n(); | |
| if (s.isNull()) return !1; | |
| const o = r(s), a = !o.isNull(); | |
| return a && new ObjC.Object(o).release(), a; | |
| } | |
| function fridaVersion() { | |
| return { | |
| version: Frida.version | |
| }; | |
| } | |
| function uiAlertAndroid(e) { | |
| if (e.length < 2) return "Usage: ?E title message"; | |
| const t = e[0], n = e.slice(1).join(" "); | |
| Java.perform((function() { | |
| Java.use("java.lang.System"); | |
| const e = Java.use("android.app.ActivityThread"), r = Java.use("android.app.AlertDialog$Builder"); | |
| Java.use("android.content.DialogInterface$OnClickListener"); | |
| Java.use("android.app.Activity").onCreate.overload("android.os.Bundle").implementation = function(s) { | |
| const o = e.currentApplication(); | |
| if (o.getPackageManager().getLaunchIntentForPackage(o.getPackageName()).resolveActivityInfo(o.getPackageManager(), 0).name.value === this.getComponentName().getClassName()) { | |
| const e = r.$new(this); | |
| e.setMessage(t + n), e.create().show(); | |
| } | |
| return this.onCreate.overload("android.os.Bundle").call(this, s); | |
| }; | |
| })); | |
| } | |
| function uiAlert(e) { | |
| if (JavaAvailable) return uiAlertAndroid(e); | |
| if (!ObjCAvailable) return "Error: ui-alert is not implemented for this platform"; | |
| if (e.length < 2) return "Usage: ?E title message"; | |
| const t = e[0], n = e.slice(1).join(" "); | |
| ObjC.schedule(ObjC.mainQueue, (function() { | |
| const e = ObjC.classes.UIAlertView.alloc().initWithTitle_message_delegate_cancelButtonTitle_otherButtonTitles_(t, n, NULL, "OK", NULL); | |
| e.show(), e.release(); | |
| })); | |
| } | |
| function search(e) { | |
| return searchJson(e).then((e => _readableHits(e))); | |
| } | |
| function echo(e) { | |
| return console.log(e.join(" ")), null; | |
| } | |
| function searchJson(e) { | |
| return _searchPatternJson(_toHexPairs(e.join(" "))).then((e => (e.forEach((e => { | |
| try { | |
| const t = io.read({ | |
| offset: e.address, | |
| count: 60 | |
| })[1]; | |
| e.content = _filterPrintable(t); | |
| } catch (e) {} | |
| })), e.filter((e => void 0 !== e.content))))); | |
| } | |
| function searchInstancesJson(e) { | |
| const t = e.join(""); | |
| if (ObjCAvailable) { | |
| return JSON.parse(JSON.stringify(ObjC.chooseSync(ObjC.classes[t]))).map((function(e) { | |
| return { | |
| address: e.handle, | |
| content: t | |
| }; | |
| })); | |
| } | |
| Java.performNow((function() { | |
| return Java.choose(Java.classes[t]).map((function(e) { | |
| return { | |
| address: e, | |
| content: t | |
| }; | |
| })); | |
| })); | |
| } | |
| function searchInstances(e) { | |
| return _readableHits(searchInstancesJson(e)); | |
| } | |
| function searchHex(e) { | |
| return searchHexJson(e).then((e => _readableHits(e))); | |
| } | |
| function searchHexJson(e) { | |
| return _searchPatternJson(_normHexPairs(e.join(""))).then((e => (e.forEach((e => { | |
| const t = Memory.readByteArray(e.address, e.size); | |
| e.content = _byteArrayToHex(t); | |
| })), e))); | |
| } | |
| function searchWide(e) { | |
| return searchWideJson(e).then((e => _readableHits(e))); | |
| } | |
| function searchWideJson(e) { | |
| return searchHexJson([ _toWidePairs(e.join(" ")) ]); | |
| } | |
| function searchValueImpl(e) { | |
| return function(t) { | |
| return searchValueJson(t, e).then((e => _readableHits(e))); | |
| }; | |
| } | |
| function searchValueImplJson(e) { | |
| return function(t) { | |
| return searchValueJson(t, e); | |
| }; | |
| } | |
| function searchValueJson(e, t) { | |
| let n; | |
| try { | |
| n = uint64(e.join("")); | |
| } catch (e) { | |
| return new Promise(((t, n) => n(e))); | |
| } | |
| return hostCmdj("ej").then((e => { | |
| const r = e["cfg.bigendian"]; | |
| return searchHexJson([ _toHexPairs(_renderEndian(n, r, t)) ]); | |
| })); | |
| } | |
| function evalConfigSearch(e) { | |
| const t = Process.getRangeByAddress(ptr(r2frida.offset)), n = t.base, r = n.add(t.size); | |
| return `e search.in=raw\ne search.from=${n}\ne search.to=${r}\ne anal.in=raw\ne anal.from=${n}\ne anal.to=${r}`; | |
| } | |
| function evalConfigR2(e) { | |
| return config.asR2Script(); | |
| } | |
| function evalConfig(e) { | |
| if (0 === e.length) return config.asR2Script(); | |
| const t = e.join(" "), n = t.split(/=/), [r, s] = n; | |
| if (2 === n.length) { | |
| if (void 0 !== config.get(r)) { | |
| if ("?" === s) return config.helpFor(n[0]); | |
| config.set(n[0], n[1]); | |
| } else console.error("unknown variable"); | |
| return ""; | |
| } | |
| return config.getString(t); | |
| } | |
| function _renderEndian(e, t, n) { | |
| const r = []; | |
| for (let s = 0; s !== n; s++) t ? r.push(e.shr(8 * (n - s - 1)).and(255).toNumber()) : r.push(e.shr(8 * s).and(255).toNumber()); | |
| return r; | |
| } | |
| function _byteArrayToHex(e) { | |
| const t = new Uint8Array(e), n = []; | |
| for (let e = 0; e !== t.length; e += 1) { | |
| const r = t[e].toString(16); | |
| n.push(2 === r.length ? r : `0${r}`); | |
| } | |
| return n.join(""); | |
| } | |
| Script.setGlobalAccessHandler({ | |
| enumerate: () => [], | |
| get(e) {} | |
| }); | |
| const minPrintable = " ".charCodeAt(0), maxPrintable = "~".charCodeAt(0); | |
| function _filterPrintable(e) { | |
| const t = new Uint8Array(e), n = []; | |
| for (let e = 0; e !== t.length; e += 1) { | |
| const r = t[e]; | |
| if (0 === r) break; | |
| r >= minPrintable && r <= maxPrintable && n.push(String.fromCharCode(r)); | |
| } | |
| return n.join(""); | |
| } | |
| function _readableHits(e) { | |
| return e.map((e => "string" == typeof e.flag ? `${hexPtr(e.address)} ${e.flag} ${e.content}` : `${hexPtr(e.address)} ${e.content}`)).join("\n") + "\n"; | |
| } | |
| function hexPtr(e) { | |
| return e instanceof UInt64 ? `0x${e.toString(16)}` : e.toString(); | |
| } | |
| function _searchPatternJson(e) { | |
| return hostCmdj("ej").then((n => { | |
| const r = n["search.flags"], s = n["search.prefix"] || "hit", o = n["search.count"] || 0, a = n["search.kwidx"] || 0, i = _getRanges(n["search.from"], n["search.to"]), c = e.split(" ").length; | |
| t(`Searching ${c} bytes: ${e}`); | |
| let l = []; | |
| const u = []; | |
| let d = 0; | |
| for (const n of i) { | |
| if (0 === n.size) continue; | |
| t(`Searching ${c} bytes in ${`[${padPointer(n.address)}-${padPointer(n.address.add(n.size))}]`}`); | |
| try { | |
| const t = _scanForPattern(n.address, n.size, e); | |
| t.forEach((e => { | |
| r && (e.flag = `${s}${a}_${d + o}`, u.push("fs+searches"), u.push(`f ${e.flag} ${e.size} ${hexPtr(e.address)}`), | |
| u.push("fs-")), d += 1; | |
| })), l = l.concat(t); | |
| } catch (e) { | |
| console.error("Oops", e); | |
| } | |
| } | |
| return t(`hits: ${l.length}`), u.push(`e search.kwidx=${a + 1}`), hostCmds(u).then((() => l)); | |
| })); | |
| function t(e) { | |
| config.getBoolean("search.quiet") || console.log(e); | |
| } | |
| } | |
| function _scanForPattern(e, t, n) { | |
| return null !== r2frida.hookedScan ? r2frida.hookedScan(e, t, n) : Memory.scanSync(e, t, n); | |
| } | |
| function _configParseSearchIn() { | |
| const e = { | |
| current: !1, | |
| perm: "r--", | |
| path: null, | |
| heap: !1 | |
| }, t = config.getString("search.in").split(":"), [n, r] = t; | |
| return "current" === n && (e.current = !0), "heap" === n && (e.heap = !0), "perm" === n && (e.perm = r), | |
| "path" === n && (t.shift(), e.path = t.join("")), e; | |
| } | |
| function _getRanges(e, t) { | |
| const n = _configParseSearchIn(); | |
| if (n.heap) return Process.enumerateMallocRanges().map((e => ({ | |
| address: e.base, | |
| size: e.size | |
| }))); | |
| const r = _getMemoryRanges(n.perm).filter((e => { | |
| const t = e.base, r = t.add(e.size), s = ptr(r2frida.offset); | |
| return n.current ? s.compare(t) >= 0 && s.compare(r) < 0 : null === n.path || void 0 !== e.file && e.file.path.indexOf(n.path) >= 0; | |
| })); | |
| if (0 === r.length) return []; | |
| const s = r[0], o = r[r.length - 1], a = -1 === e ? s.base : ptr(e), i = -1 === t ? o.base.add(o.size) : ptr(t); | |
| return r.filter((e => e.base.compare(i) <= 0 && e.base.add(e.size).compare(a) >= 0)).map((e => { | |
| const t = _ptrMax(e.base, a), n = _ptrMin(e.base.add(e.size), i); | |
| return { | |
| address: t, | |
| size: uint64(n.sub(t).toString()).toNumber() | |
| }; | |
| })); | |
| } | |
| function _ptrMax(e, t) { | |
| return e.compare(t) > 0 ? e : t; | |
| } | |
| function _ptrMin(e, t) { | |
| return e.compare(t) < 0 ? e : t; | |
| } | |
| function _toHexPairs(e) { | |
| const t = "string" == typeof e, n = []; | |
| for (let r = 0; r !== e.length; r += 1) { | |
| const s = (255 & (t ? e.charCodeAt(r) : e[r])).toString(16); | |
| n.push(2 === s.length ? s : `0${s}`); | |
| } | |
| return n.join(" "); | |
| } | |
| function _toWidePairs(e) { | |
| const t = []; | |
| for (let n = 0; n !== e.length; n += 1) { | |
| const r = (255 & e.charCodeAt(n)).toString(16); | |
| t.push(2 === r.length ? r : `0${r}`), t.push("00"); | |
| } | |
| return t.join(" "); | |
| } | |
| function _normHexPairs(e) { | |
| const t = e.replace(/ /g, ""); | |
| if (_isHex(t)) return _toPairs(t.replace(/\./g, "?")); | |
| throw new Error("Invalid hex string"); | |
| } | |
| function _toPairs(e) { | |
| if (e.length % 2 != 0) throw new Error("Odd-length string"); | |
| const t = []; | |
| for (let n = 0; n !== e.length; n += 2) t.push(e.substr(n, 2)); | |
| return t.join(" ").toLowerCase(); | |
| } | |
| function _isHex(e) { | |
| const t = new Set(Array.from("abcdefABCDEF0123456789?.")), n = new Set(Array.from(e)); | |
| for (const e of t) n.delete(e); | |
| return 0 === n.size; | |
| } | |
| function fsList(e) { | |
| return fs.ls(e[0] || Gcwd); | |
| } | |
| function fsGet(e) { | |
| return fs.cat(e[0] || "", "*", e[1] || 0, e[2] || null); | |
| } | |
| function fsCat(e) { | |
| return fs.cat(e[0] || ""); | |
| } | |
| function fsOpen(e) { | |
| return fs.open(e[0] || Gcwd); | |
| } | |
| function javaPerform(e) { | |
| return config.getBoolean("java.wait") ? Java.perform(e) : Java.performNow(e); | |
| } | |
| function performOnJavaVM(e) { | |
| return new Promise(((t, n) => { | |
| javaPerform((function() { | |
| try { | |
| const n = e(); | |
| t(n); | |
| } catch (e) { | |
| n(e); | |
| } | |
| })); | |
| })); | |
| } | |
| function getModuleAt(e) { | |
| if (null === e) return null; | |
| const t = Process.enumerateModules().filter((t => { | |
| const n = t.base, r = t.base.add(t.size); | |
| return e.compare(n) >= 0 && e.compare(r) < 0; | |
| })); | |
| return t.length > 0 ? t[0] : null; | |
| } | |
| let onceStanza = !1; | |
| function onStanza(e, t) { | |
| const n = requestHandlers[e.type]; | |
| if (void 0 !== n) try { | |
| const r = n(e.payload, t); | |
| if (r instanceof Promise) r.then((([e, t]) => { | |
| send(wrapStanza("reply", e), t); | |
| })).catch((e => { | |
| send(wrapStanza("reply", { | |
| error: e.message | |
| })); | |
| })); else { | |
| const [e, t] = r; | |
| send(wrapStanza("reply", e), t); | |
| } | |
| } catch (e) { | |
| send(wrapStanza("reply", { | |
| error: e.message | |
| })); | |
| } else "bp" === e.type ? console.error("Breakpoint handler") : "cmd" === e.type ? onCmdResp(e.payload) : console.error("Unhandled stanza: " + e.type); | |
| onceStanza || recv(onStanza); | |
| } | |
| let cmdSerial = 0; | |
| function hostCmds(e) { | |
| let t = 0; | |
| return function n() { | |
| return t < e.length ? hostCmd(e[t]).then((() => (t += 1, n()))) : Promise.resolve(); | |
| }(); | |
| } | |
| function hostCmdj(e) { | |
| return hostCmd(e).then((e => JSON.parse(e))); | |
| } | |
| function hostCmd(e) { | |
| return new Promise((t => { | |
| const n = cmdSerial; | |
| cmdSerial++, pendingCmds[n] = t, sendCommand(e, n); | |
| })); | |
| } | |
| function sendCommand(e, t) { | |
| function n() { | |
| sendingCommand = !0, send(wrapStanza("cmd", { | |
| cmd: e, | |
| serial: t | |
| })); | |
| } | |
| sendingCommand ? pendingCmdSends.push(n) : n(); | |
| } | |
| function onCmdResp(e) { | |
| const {serial: t, output: n} = e; | |
| if (sendingCommand = !1, !(t in pendingCmds)) throw new Error("Command response out of sync"); | |
| { | |
| const e = pendingCmds[t]; | |
| delete pendingCmds[t], process.nextTick((() => e(n))); | |
| } | |
| return process.nextTick((() => { | |
| if (!sendingCommand) { | |
| const e = pendingCmdSends.shift(); | |
| void 0 !== e && e(); | |
| } | |
| })), [ {}, null ]; | |
| } | |
| function wrapStanza(e, t) { | |
| return { | |
| name: e, | |
| stanza: t | |
| }; | |
| } | |
| global.r2frida.hostCmd = hostCmd, global.r2frida.hostCmdj = hostCmdj, global.r2frida.logs = logs, | |
| global.r2frida.log = traceLog, global.r2frida.emit = traceEmit, global.r2frida.safeio = NeedsSafeIo, | |
| global.r2frida.module = "", recv(onStanza); | |
| }).call(this)}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer) | |
| },{"./config":9,"./fs":10,"./io":12,"./isobjc":13,"./stalker":15,"./strings":16,"./utils":17,"_process":5,"buffer":3,"path":7}],12:[function(require,module,exports){ | |
| "use strict"; | |
| const e = require("./plugin"), r = require("./config"); | |
| let t = []; | |
| function o(r) { | |
| const {offset: o, count: n, fast: s} = r; | |
| if (null !== e.hookedRead) return e.hookedRead(o, n); | |
| if (e.safeio) { | |
| 0 === t.length && (t = Process.enumerateRanges("").map((e => [ e.base, ptr(e.base).add(e.size) ]))); | |
| const e = ptr(o); | |
| for (const r of t) if (e.compare(r[0]) >= 0 && e.compare(r[1]) < 0) { | |
| let t = n; | |
| if (e.add(n).compare(r[1]) > 0) { | |
| const o = e.add(n).sub(r[1]); | |
| t = t.sub(o); | |
| } | |
| const o = Memory.readByteArray(e, t); | |
| return [ {}, null !== o ? o : [] ]; | |
| } | |
| return [ {}, [] ]; | |
| } | |
| if (o < 0) return [ {}, [] ]; | |
| try { | |
| const e = Memory.readByteArray(ptr(o), n); | |
| return [ {}, null !== e ? e : [] ]; | |
| } catch (e) { | |
| if (!s) try { | |
| const e = ptr(o), r = e.add(n), t = Process.getRangeByAddress(e), s = t.base.add(t.size), a = (r.compare(s) > 0 ? r : s).sub(o), c = Memory.readByteArray(ptr(o), +a); | |
| return [ {}, null !== c ? c : [] ]; | |
| } catch (e) {} | |
| } | |
| return [ {}, [] ]; | |
| } | |
| function n(e) { | |
| return -1 !== Process.getRangeByAddress(e).protection.indexOf("x"); | |
| } | |
| function s(t, o) { | |
| return "function" == typeof e.hookedWrite ? e.hookedWrite(t.offset, o) : (r.getBoolean("patch.code") && n(ptr(t.offset)) && "function" == typeof Memory.patchCode ? Memory.patchCode(ptr(t.offset), 1, (function(e) { | |
| Memory.writeByteArray(e, o); | |
| })) : Memory.writeByteArray(ptr(t.offset), o), [ {}, null ]); | |
| } | |
| module.exports = { | |
| read: o, | |
| write: s | |
| }; | |
| },{"./config":9,"./plugin":14}],13:[function(require,module,exports){ | |
| "use strict"; | |
| const r = ptr("0x100000000"), t = ptr("0x0000000ffffffff8"), n = ptr("0x000003f000000001"), e = ptr("0x000001a000000001"); | |
| function f(r) { | |
| return !u(r).isNull(); | |
| } | |
| function u(r) { | |
| if (!c(r)) return NULL; | |
| const f = r.readPointer(); | |
| let u = f; | |
| return u.and(n).equals(e) && (u = f.and(t)), c(u) ? u : NULL; | |
| } | |
| function c(t) { | |
| return t.compare(r) >= 0 && o(t); | |
| } | |
| function o(r) { | |
| try { | |
| return r.readU8(r), !0; | |
| } catch (r) { | |
| return !1; | |
| } | |
| } | |
| module.exports = f; | |
| },{}],14:[function(require,module,exports){ | |
| (function (global){(function (){ | |
| const n = {}; | |
| function e(e, o) { | |
| return n.hasOwnProperty(e) ? (console.log("Cannot register the same handler twice"), | |
| !1) : (n[e] = o, !0); | |
| } | |
| function o(e) { | |
| return !!n.hasOwnProperty(e) && (delete n[e], !0); | |
| } | |
| function r(e) { | |
| for (const o of Object.keys(n)) { | |
| const r = n[o]; | |
| if ("function" == typeof r) { | |
| const n = r(e); | |
| if (void 0 !== n) return n; | |
| } | |
| } | |
| } | |
| function t() { | |
| return Object.keys(n).join("\n"); | |
| } | |
| global.r2frida = { | |
| version: require("../../package.json").version, | |
| commandHandler: r, | |
| pluginRegister: e, | |
| pluginUnregister: o, | |
| pluginList: t, | |
| hookedRead: null, | |
| hookedWrite: null, | |
| hookedRanges: null, | |
| hookedScan: null | |
| }, module.exports = global.r2frida; | |
| }).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) | |
| },{"../../package.json":8}],15:[function(require,module,exports){ | |
| "use strict"; | |
| const e = {}, t = []; | |
| function n(t, n) { | |
| return new Promise(((o, a) => { | |
| const u = {}, d = new Set, h = new Set; | |
| let m = null; | |
| s(), f(t); | |
| const T = Interceptor.attach(n, { | |
| onEnter() { | |
| y(), this.myThreadId = Process.getCurrentThreadId(); | |
| let e = u[this.myThreadId] || 0; | |
| e++, u[this.myThreadId] = e, 1 === e && (d.add(this.myThreadId), c(t)); | |
| }, | |
| onLeave() { | |
| y(); | |
| let e = u[this.myThreadId]; | |
| e--, u[this.myThreadId] = e, 0 === e && (d.delete(this.myThreadId), h.add(this.myThreadId), | |
| i(), 0 === d.size && (T.detach(), null !== m && (clearTimeout(m), m = null), r(h, o))); | |
| } | |
| }); | |
| function y() { | |
| if (0 === t.timeout) return; | |
| null !== m && clearTimeout(m); | |
| const e = 1e3 * (t.timeout >> 0); | |
| m = setTimeout(k, e); | |
| } | |
| function k() { | |
| T.detach(), l(), Stalker.garbageCollect(); | |
| Object.keys(e).forEach((t => { | |
| delete e[t]; | |
| })), a(new Error("Stalker timeout reached")); | |
| } | |
| y(); | |
| })); | |
| } | |
| function o(e, t) { | |
| return new Promise(((n, o) => { | |
| s(), f(e); | |
| const c = Process.enumerateThreadsSync(); | |
| for (const t of c) a(e, t.id); | |
| let i = t || e.timeout; | |
| 0 === i && (i = 30), setTimeout((() => { | |
| for (const e of c) Stalker.unfollow(e.id); | |
| r(c.map((e => e.id)), n); | |
| }), 1e3 * (i >> 0)); | |
| })); | |
| } | |
| function r(t, n) { | |
| Stalker.garbageCollect(), setTimeout((() => { | |
| const o = {}; | |
| for (const n of t) n in e && (o[n] = e[n], delete e[n]); | |
| n(o); | |
| }), 1e3); | |
| } | |
| function s() { | |
| const t = Object.keys(e); | |
| for (const n of t) delete e[n]; | |
| } | |
| function c(e) { | |
| const t = Process.getCurrentThreadId(); | |
| return a(e, t), t; | |
| } | |
| function a(t, n) { | |
| Stalker.follow(n, { | |
| events: u(t), | |
| onReceive: function(t) { | |
| const o = Stalker.parse(t, { | |
| annotate: !1 | |
| }).filter(d); | |
| 0 !== o.length && (n in e ? e[n].push(...o) : e[n] = o); | |
| } | |
| }); | |
| } | |
| function i() { | |
| Stalker.unfollow(); | |
| } | |
| function l() { | |
| const e = Process.enumerateThreadsSync(); | |
| for (const t of e) Stalker.unfollow(t.id); | |
| } | |
| function u(e) { | |
| const t = { | |
| call: !1, | |
| ret: !1, | |
| exec: !1, | |
| block: !1, | |
| compile: !1 | |
| }; | |
| return t[e.event] = !0, t; | |
| } | |
| function d(e) { | |
| if (0 === t.length) return !0; | |
| const n = e[0]; | |
| return t.some((([e, t]) => n.compare(e) >= 0 && n.compare(t) <= 0)); | |
| } | |
| function f(e) { | |
| switch (t.splice(0, -1), e.stalkin) { | |
| case "app": | |
| const e = Process.enumerateModulesSync()[0]; | |
| return void t.push([ e.base, e.base.add(e.size) ]); | |
| case "modules": | |
| t.push(...Process.enumerateModulesSync().map((e => [ e.base, e.base.add(e.size) ]))); | |
| } | |
| } | |
| module.exports = { | |
| stalkFunction: n, | |
| stalkEverything: o | |
| }; | |
| },{}],16:[function(require,module,exports){ | |
| function n(n) { | |
| return n >= 32 && n <= 126; | |
| } | |
| function e(n) { | |
| const e = { | |
| minLength: 15, | |
| maxLength: 128, | |
| filter: !1, | |
| urls: !1, | |
| base: 0 | |
| }; | |
| if ("object" == typeof n) for (const t of Object.keys(n)) e[t] = n[t]; | |
| return e; | |
| } | |
| function t(t, o) { | |
| const i = e(o), u = []; | |
| let s = "", c = 0, l = 0; | |
| return t.forEach((e => { | |
| if (n(e)) "" === s && (l = c), s += String.fromCharCode(e); else { | |
| if (s.length > i.minLength && s.length < i.maxLength) { | |
| let n = !0; | |
| i.filter && !r(s) && (n = !1), i.urls && !f(s) && (n = !1), n && u.push({ | |
| base: i.base.add(l), | |
| text: s | |
| }); | |
| } | |
| s = ""; | |
| } | |
| c++; | |
| })), u; | |
| } | |
| function r(n) { | |
| if (-1 !== n.indexOf("://")) return !1; | |
| if (+n) return !1; | |
| for (const e of "<\\)?@)>{~}^()=/!-\"*:]%';` $") if (-1 !== n.indexOf(e)) return !1; | |
| return !0; | |
| } | |
| function f(n) { | |
| if (-1 === n.indexOf("://")) return !1; | |
| for (const e of "<\\)?)>{~}^()=!-\"*]'` $") if (-1 !== n.indexOf(e)) return !1; | |
| return !0; | |
| } | |
| module.exports = t; | |
| },{}],17:[function(require,module,exports){ | |
| function e(e) { | |
| return e.replace(/[\s-\/\\()\[\]<>!?$;%@`|&"+,]/g, "_"); | |
| } | |
| module.exports = { | |
| flagify: e | |
| }; | |
| },{}]},{},[11]); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment