603 lines
20 KiB
JavaScript
603 lines
20 KiB
JavaScript
/*
|
||
* 深度闭环抓证脚本:
|
||
*
|
||
* /f/a/p response -> wcfg["a_y_q_z"] 写入 -> WeaponHI.dd(21) 读取
|
||
* -> passport_account_image
|
||
*
|
||
* 用法:
|
||
* 先把 APP 打开到登录页,再按主进程 PID 附加:
|
||
* powershell -NoProfile -ExecutionPolicy Bypass `
|
||
* -File tools\frida_attach_nebula_main_wcfg.ps1
|
||
*
|
||
* 说明:
|
||
* deep 版会读取 /f/a/p 请求体和响应体;仍不推荐直接 -f 包名。部分设备上 spawn 可能落到 :push_v3 等子进程,
|
||
* 本脚本 MAIN_ONLY=true 时会正确跳过这些子进程。
|
||
*
|
||
* 设计原则:每个 hook 独立 try/catch,单点失败不影响后续 hook。
|
||
*/
|
||
|
||
'use strict';
|
||
|
||
(function () {
|
||
const SCRIPT = 'frida_probe_passport_wcfg_deep.js';
|
||
const CFG = {
|
||
// 默认安全模式:只抓关键业务链,不碰一次性 body,不在热路径打堆栈。
|
||
MAIN_ONLY: true,
|
||
STACK: false,
|
||
REQUEST_BODY: true,
|
||
RESPONSE_BODY_STRING: true,
|
||
SP_EDITOR_INTERFACE: true
|
||
};
|
||
const MAIN_PROCESS = 'com.kuaishou.nebula';
|
||
let seq = 0;
|
||
|
||
function now() {
|
||
return new Date().toISOString();
|
||
}
|
||
|
||
function shortValue(v, n) {
|
||
const s = (v === null || v === undefined) ? '' : String(v);
|
||
const limit = n || 160;
|
||
if (s.length <= limit) return s;
|
||
return s.slice(0, limit) + '...(len=' + s.length + ')';
|
||
}
|
||
|
||
function valueFields(key, value, n) {
|
||
const s = (value === null || value === undefined) ? '' : String(value);
|
||
const out = { value: shortValue(s, n || 260) };
|
||
if (isInterestingKey(key) || isInterestingValue(s)) {
|
||
out.value_full = s;
|
||
out.value_len = s.length;
|
||
}
|
||
return out;
|
||
}
|
||
|
||
function namedValueFields(primary, value, n, forceFull) {
|
||
const s = (value === null || value === undefined) ? '' : String(value);
|
||
const out = {};
|
||
out[primary] = shortValue(s, n || 260);
|
||
if (forceFull || isInterestingValue(s) || s.indexOf('a_y_q_z') >= 0 || s.indexOf('passport_account_image') >= 0) {
|
||
out[primary + '_full'] = s;
|
||
out[primary + '_len'] = s.length;
|
||
}
|
||
return out;
|
||
}
|
||
|
||
function emit(tag, obj) {
|
||
try {
|
||
obj = obj || {};
|
||
obj.tag = tag;
|
||
obj.seq = ++seq;
|
||
obj.ts = now();
|
||
obj.pid = Process.id;
|
||
console.log('@@WCFG ' + JSON.stringify(obj));
|
||
} catch (e) {
|
||
console.log('@@WCFG {"tag":"EMIT_ERR","err":"' + String(e) + '"}');
|
||
}
|
||
}
|
||
|
||
function safeHook(name, fn) {
|
||
try {
|
||
fn();
|
||
emit('HOOK_OK', { name: name });
|
||
} catch (e) {
|
||
emit('HOOK_FAIL', { name: name, err: String(e), stack: String(e && e.stack || '') });
|
||
}
|
||
}
|
||
|
||
function javaStack() {
|
||
if (!CFG.STACK) return '';
|
||
try {
|
||
const Log = Java.use('android.util.Log');
|
||
const Exception = Java.use('java.lang.Exception');
|
||
return String(Log.getStackTraceString(Exception.$new()));
|
||
} catch (e) {
|
||
return '[stack_err] ' + String(e);
|
||
}
|
||
}
|
||
|
||
function withStack(obj) {
|
||
if (CFG.STACK) obj.stack = javaStack();
|
||
return obj;
|
||
}
|
||
|
||
function objId(o) {
|
||
try {
|
||
return String(o.hashCode());
|
||
} catch (e) {
|
||
return '[hash_err]';
|
||
}
|
||
}
|
||
|
||
function isInterestingKey(k) {
|
||
const s = String(k || '');
|
||
return s === 'a_y_q_z' || s.indexOf('a_y_q_z') >= 0 || s === 'passport_account_image';
|
||
}
|
||
|
||
function isInterestingValue(v) {
|
||
const s = String(v || '');
|
||
return s.indexOf('VIMG_') >= 0 || s.indexOf('$AI_') >= 0;
|
||
}
|
||
|
||
function isTrafficUrl(url) {
|
||
const s = String(url || '');
|
||
return s.indexOf('/f/a/p') >= 0 ||
|
||
s.indexOf('mobile/checker') >= 0 ||
|
||
s.indexOf('requestMobileCode') >= 0 ||
|
||
s.indexOf('mobileVerifyCode') >= 0;
|
||
}
|
||
|
||
function summarizeArgs(argsLike) {
|
||
const out = [];
|
||
for (let i = 0; i < argsLike.length; i++) {
|
||
out.push(shortValue(argsLike[i], 220));
|
||
}
|
||
return out;
|
||
}
|
||
|
||
function r1EndpointHint(argsLike) {
|
||
try {
|
||
if (argsLike.length === 2) return '/f/a/p';
|
||
if (argsLike.length >= 4) return String(argsLike[2]) + String(argsLike[3]);
|
||
} catch (e) {}
|
||
return '';
|
||
}
|
||
|
||
emit('SCRIPT_START', { script: SCRIPT, cfg: CFG });
|
||
|
||
Java.perform(function () {
|
||
const prefsByHash = {};
|
||
const requestUrlByHash = {};
|
||
const responseBodyUrlByHash = {};
|
||
let processName = '';
|
||
|
||
safeHook('process name probe', function () {
|
||
try {
|
||
const Application = Java.use('android.app.Application');
|
||
processName = String(Application.getProcessName());
|
||
} catch (e) {
|
||
try {
|
||
const ActivityThread = Java.use('android.app.ActivityThread');
|
||
processName = String(ActivityThread.currentProcessName());
|
||
} catch (ignored) {
|
||
processName = '';
|
||
}
|
||
}
|
||
emit('PROCESS_NAME', { process_name: processName });
|
||
});
|
||
|
||
if (CFG.MAIN_ONLY && processName && processName !== MAIN_PROCESS) {
|
||
emit('PROCESS_SKIP', { process_name: processName, reason: 'main_only', main_process: MAIN_PROCESS });
|
||
return;
|
||
}
|
||
|
||
function requestBodyToString(req) {
|
||
if (!CFG.REQUEST_BODY) return '';
|
||
try {
|
||
const body = req.body();
|
||
if (body === null || body === undefined) return '';
|
||
const Buffer = Java.use('okio.Buffer');
|
||
const buffer = Buffer.$new();
|
||
body.writeTo(buffer);
|
||
return String(buffer.readUtf8());
|
||
} catch (e) {
|
||
return '[body_err] ' + String(e);
|
||
}
|
||
}
|
||
|
||
function emitFormField(tag, name, value) {
|
||
try {
|
||
const key = String(name || '');
|
||
const val = String(value || '');
|
||
if (isInterestingKey(key) || isInterestingValue(val)) {
|
||
emit(tag, {
|
||
name: key,
|
||
...valueFields(key, val, 320),
|
||
stack: javaStack()
|
||
});
|
||
}
|
||
} catch (e) {
|
||
emit(tag + '_ERR', { err: String(e) });
|
||
}
|
||
}
|
||
|
||
function k1Info(k1) {
|
||
const out = { url: '', body: '' };
|
||
try {
|
||
if (k1 === null || k1 === undefined) return out;
|
||
try {
|
||
out.url = String(k1.a.value || '');
|
||
} catch (e1) {
|
||
out.url = '';
|
||
}
|
||
try {
|
||
const bodyObj = k1.c();
|
||
out.body = bodyObj ? String(bodyObj.toString()) : '';
|
||
} catch (e2) {
|
||
out.body = '';
|
||
}
|
||
} catch (e) {}
|
||
return out;
|
||
}
|
||
|
||
safeHook('ContextImpl.getSharedPreferences', function () {
|
||
const ContextImpl = Java.use('android.app.ContextImpl');
|
||
const ov = ContextImpl.getSharedPreferences.overload('java.lang.String', 'int');
|
||
ov.implementation = function (name, mode) {
|
||
const ret = ov.call(this, name, mode);
|
||
try {
|
||
prefsByHash[objId(ret)] = String(name);
|
||
if (String(name) === 'wcfg') {
|
||
emit('PREFS_OPEN', { name: String(name), mode: mode, prefs_hash: objId(ret) });
|
||
}
|
||
} catch (e) {}
|
||
return ret;
|
||
};
|
||
});
|
||
|
||
safeHook('SharedPreferencesImpl.getString', function () {
|
||
const SPI = Java.use('android.app.SharedPreferencesImpl');
|
||
const ov = SPI.getString.overload('java.lang.String', 'java.lang.String');
|
||
ov.implementation = function (key, defValue) {
|
||
const ret = ov.call(this, key, defValue);
|
||
const prefsName = prefsByHash[objId(this)] || '';
|
||
if (prefsName === 'wcfg' || isInterestingKey(key) || isInterestingValue(ret)) {
|
||
emit('PREFS_GET_STRING', {
|
||
prefs: prefsName,
|
||
prefs_hash: objId(this),
|
||
key: String(key),
|
||
def: shortValue(defValue, 120),
|
||
...valueFields(key, ret, 220),
|
||
stack: javaStack()
|
||
});
|
||
}
|
||
return ret;
|
||
};
|
||
});
|
||
|
||
if (CFG.SP_EDITOR_INTERFACE) {
|
||
safeHook('SharedPreferences.Editor.putString', function () {
|
||
const Editor = Java.use('android.content.SharedPreferences$Editor');
|
||
const ov = Editor.putString.overload('java.lang.String', 'java.lang.String');
|
||
ov.implementation = function (key, value) {
|
||
if (isInterestingKey(key) || isInterestingValue(value)) {
|
||
emit('EDITOR_PUT_STRING_IFACE', {
|
||
editor_class: String(this.getClass().getName()),
|
||
key: String(key),
|
||
...valueFields(key, value, 260),
|
||
stack: javaStack()
|
||
});
|
||
}
|
||
return ov.call(this, key, value);
|
||
};
|
||
});
|
||
} else {
|
||
emit('HOOK_SKIPPED', { name: 'SharedPreferences.Editor.putString', reason: 'interface_hook_disabled' });
|
||
}
|
||
|
||
safeHook('SharedPreferencesImpl.EditorImpl.putString', function () {
|
||
const EditorImpl = Java.use('android.app.SharedPreferencesImpl$EditorImpl');
|
||
const ov = EditorImpl.putString.overload('java.lang.String', 'java.lang.String');
|
||
ov.implementation = function (key, value) {
|
||
if (isInterestingKey(key) || isInterestingValue(value)) {
|
||
emit('EDITOR_PUT_STRING_IMPL', {
|
||
key: String(key),
|
||
...valueFields(key, value, 260),
|
||
stack: javaStack()
|
||
});
|
||
}
|
||
return ov.call(this, key, value);
|
||
};
|
||
});
|
||
|
||
safeHook('com.kuaishou.weapon.ks.z0 read/write wrappers', function () {
|
||
const Z0 = Java.use('com.kuaishou.weapon.ks.z0');
|
||
|
||
const read = Z0.a.overload('java.lang.String', 'java.lang.String');
|
||
read.implementation = function (key, defValue) {
|
||
const ret = read.call(this, key, defValue);
|
||
if (isInterestingKey(key) || isInterestingValue(ret)) {
|
||
emit('Z0_READ_A_STRING_STRING', {
|
||
key: String(key),
|
||
def: shortValue(defValue, 120),
|
||
...valueFields(key, ret, 260),
|
||
stack: javaStack()
|
||
});
|
||
}
|
||
return ret;
|
||
};
|
||
|
||
const write3 = Z0.a.overload('boolean', 'java.lang.String', 'java.lang.String');
|
||
write3.implementation = function (applyNow, key, value) {
|
||
if (isInterestingKey(key) || isInterestingValue(value)) {
|
||
emit('Z0_WRITE_A_BOOL_STRING_STRING', {
|
||
apply_now: !!applyNow,
|
||
key: String(key),
|
||
...valueFields(key, value, 260),
|
||
stack: javaStack()
|
||
});
|
||
}
|
||
return write3.call(this, applyNow, key, value);
|
||
};
|
||
|
||
const writeB = Z0.b.overload('java.lang.String', 'java.lang.String', 'boolean');
|
||
writeB.implementation = function (key, value, encode) {
|
||
if (isInterestingKey(key) || isInterestingValue(value)) {
|
||
emit('Z0_WRITE_B_STRING_STRING_BOOL', {
|
||
key: String(key),
|
||
...valueFields(key, value, 260),
|
||
encode: !!encode,
|
||
stack: javaStack()
|
||
});
|
||
}
|
||
return writeB.call(this, key, value, encode);
|
||
};
|
||
});
|
||
|
||
safeHook('WeaponHI.dd/db/b', function () {
|
||
const WeaponHI = Java.use('com.kuaishou.weapon.i.WeaponHI');
|
||
|
||
if (WeaponHI.dd) {
|
||
const dd = WeaponHI.dd.overload('int');
|
||
dd.implementation = function (type) {
|
||
const ret = dd.call(this, type);
|
||
if (type === 21 || isInterestingValue(ret)) {
|
||
emit('WEAPON_DD', {
|
||
type: type,
|
||
...valueFields('a_y_q_z', ret, 260),
|
||
stack: javaStack()
|
||
});
|
||
}
|
||
return ret;
|
||
};
|
||
}
|
||
|
||
if (WeaponHI.b) {
|
||
const b = WeaponHI.b.overload('java.lang.String');
|
||
b.implementation = function (input) {
|
||
const ret = b.call(this, input);
|
||
emit('WEAPON_B_UPLOAD_ENCRYPT', {
|
||
input: shortValue(input, 180),
|
||
...valueFields('weaponhi_b', ret, 220),
|
||
stack: javaStack()
|
||
});
|
||
return ret;
|
||
};
|
||
}
|
||
});
|
||
|
||
safeHook('com.kuaishou.weapon.ks.r1 upload wrappers', function () {
|
||
const R1 = Java.use('com.kuaishou.weapon.ks.r1');
|
||
R1.a.overloads.forEach(function (ov, idx) {
|
||
ov.implementation = function () {
|
||
const endpointHint = r1EndpointHint(arguments);
|
||
emit('R1_A_BEFORE', {
|
||
overload: idx,
|
||
argc: arguments.length,
|
||
endpoint_hint: endpointHint,
|
||
args: summarizeArgs(arguments),
|
||
stack: javaStack()
|
||
});
|
||
const ret = ov.apply(this, arguments);
|
||
emit('R1_A_AFTER', {
|
||
overload: idx,
|
||
endpoint_hint: endpointHint,
|
||
...namedValueFields('ret', ret, 600, endpointHint.indexOf('/f/a/p') >= 0 || isInterestingValue(ret))
|
||
});
|
||
return ret;
|
||
};
|
||
});
|
||
R1.b.overloads.forEach(function (ov, idx) {
|
||
ov.implementation = function () {
|
||
emit('R1_B_BEFORE', { overload: idx, argc: arguments.length, args: summarizeArgs(arguments), stack: javaStack() });
|
||
const ret = ov.apply(this, arguments);
|
||
emit('R1_B_AFTER', {
|
||
overload: idx,
|
||
...namedValueFields('ret', ret, 600, isInterestingValue(ret))
|
||
});
|
||
return ret;
|
||
};
|
||
});
|
||
});
|
||
|
||
safeHook('com.kuaishou.weapon.ks.i/y0 dispatch returns', function () {
|
||
const I = Java.use('com.kuaishou.weapon.ks.i');
|
||
const Y0 = Java.use('com.kuaishou.weapon.ks.y0');
|
||
|
||
const iStatic = I.a.overload('com.kuaishou.weapon.ks.k1');
|
||
iStatic.implementation = function (k1) {
|
||
const info = k1Info(k1);
|
||
if (isTrafficUrl(info.url) || isInterestingValue(info.body)) {
|
||
emit('I_A_K1_BEFORE', {
|
||
url: shortValue(info.url, 700),
|
||
...namedValueFields('body', info.body, 1000, info.url.indexOf('/f/a/p') >= 0 || isInterestingValue(info.body)),
|
||
stack: javaStack()
|
||
});
|
||
}
|
||
const ret = iStatic.call(this, k1);
|
||
if (isTrafficUrl(info.url) || isInterestingValue(ret)) {
|
||
emit('I_A_K1_AFTER', {
|
||
url: shortValue(info.url, 700),
|
||
...namedValueFields('ret', ret, 1200, info.url.indexOf('/f/a/p') >= 0 || isInterestingValue(ret))
|
||
});
|
||
}
|
||
return ret;
|
||
};
|
||
|
||
const iCtx = I.a.overload('android.content.Context', 'com.kuaishou.weapon.ks.k1');
|
||
iCtx.implementation = function (ctx, k1) {
|
||
const info = k1Info(k1);
|
||
if (isTrafficUrl(info.url) || isInterestingValue(info.body)) {
|
||
emit('I_A_CTX_K1_BEFORE', {
|
||
url: shortValue(info.url, 700),
|
||
...namedValueFields('body', info.body, 1000, info.url.indexOf('/f/a/p') >= 0 || isInterestingValue(info.body)),
|
||
stack: javaStack()
|
||
});
|
||
}
|
||
const ret = iCtx.call(this, ctx, k1);
|
||
if (isTrafficUrl(info.url) || isInterestingValue(ret)) {
|
||
emit('I_A_CTX_K1_AFTER', {
|
||
url: shortValue(info.url, 700),
|
||
...namedValueFields('ret', ret, 1200, info.url.indexOf('/f/a/p') >= 0 || isInterestingValue(ret))
|
||
});
|
||
}
|
||
return ret;
|
||
};
|
||
|
||
const y0a = Y0.a.overload('com.kuaishou.weapon.ks.k1');
|
||
y0a.implementation = function (k1) {
|
||
const info = k1Info(k1);
|
||
if (isTrafficUrl(info.url) || isInterestingValue(info.body)) {
|
||
emit('Y0_A_K1_BEFORE', {
|
||
url: shortValue(info.url, 700),
|
||
...namedValueFields('body', info.body, 1000, info.url.indexOf('/f/a/p') >= 0 || isInterestingValue(info.body)),
|
||
stack: javaStack()
|
||
});
|
||
}
|
||
const ret = y0a.call(this, k1);
|
||
if (isTrafficUrl(info.url) || isInterestingValue(ret)) {
|
||
emit('Y0_A_K1_AFTER', {
|
||
url: shortValue(info.url, 700),
|
||
...namedValueFields('ret', ret, 1200, info.url.indexOf('/f/a/p') >= 0 || isInterestingValue(ret))
|
||
});
|
||
}
|
||
return ret;
|
||
};
|
||
});
|
||
|
||
safeHook('okhttp3.Request.Builder.url', function () {
|
||
const Builder = Java.use('okhttp3.Request$Builder');
|
||
Builder.url.overloads.forEach(function (ov, idx) {
|
||
ov.implementation = function () {
|
||
const arg0 = arguments.length > 0 ? String(arguments[0]) : '';
|
||
if (arg0.indexOf('/f/a/p') >= 0 || arg0.indexOf('mobile/checker') >= 0) {
|
||
emit('OKHTTP_BUILDER_URL', { overload: idx, url: shortValue(arg0, 500), stack: javaStack() });
|
||
}
|
||
return ov.apply(this, arguments);
|
||
};
|
||
});
|
||
});
|
||
|
||
safeHook('okhttp3.Request.Builder.build', function () {
|
||
const Builder = Java.use('okhttp3.Request$Builder');
|
||
const build = Builder.build.overload();
|
||
build.implementation = function () {
|
||
const req = build.call(this);
|
||
try {
|
||
const url = String(req.url());
|
||
if (isTrafficUrl(url)) {
|
||
const body = requestBodyToString(req);
|
||
requestUrlByHash[objId(req)] = url;
|
||
emit('OKHTTP_REQUEST_BUILD', {
|
||
request_hash: objId(req),
|
||
method: String(req.method()),
|
||
url: shortValue(url, 700),
|
||
...namedValueFields('body', body, 700, url.indexOf('/f/a/p') >= 0 || isInterestingValue(body)),
|
||
stack: javaStack()
|
||
});
|
||
}
|
||
} catch (e) {
|
||
emit('OKHTTP_REQUEST_BUILD_ERR', { err: String(e) });
|
||
}
|
||
return req;
|
||
};
|
||
});
|
||
|
||
safeHook('okhttp3.OkHttpClient.newCall', function () {
|
||
const Client = Java.use('okhttp3.OkHttpClient');
|
||
const ov = Client.newCall.overload('okhttp3.Request');
|
||
ov.implementation = function (req) {
|
||
try {
|
||
const url = String(req.url());
|
||
if (isTrafficUrl(url)) {
|
||
requestUrlByHash[objId(req)] = url;
|
||
emit('OKHTTP_NEWCALL', {
|
||
request_hash: objId(req),
|
||
method: String(req.method()),
|
||
url: shortValue(url, 700)
|
||
});
|
||
}
|
||
} catch (e) {}
|
||
return ov.call(this, req);
|
||
};
|
||
});
|
||
|
||
safeHook('okhttp3.FormBody.Builder.add/addEncoded', function () {
|
||
const FormBuilder = Java.use('okhttp3.FormBody$Builder');
|
||
|
||
const add = FormBuilder.add.overload('java.lang.String', 'java.lang.String');
|
||
add.implementation = function (name, value) {
|
||
emitFormField('OKHTTP_FORM_ADD', name, value);
|
||
return add.call(this, name, value);
|
||
};
|
||
|
||
const addEncoded = FormBuilder.addEncoded.overload('java.lang.String', 'java.lang.String');
|
||
addEncoded.implementation = function (name, value) {
|
||
emitFormField('OKHTTP_FORM_ADD_ENCODED', name, value);
|
||
return addEncoded.call(this, name, value);
|
||
};
|
||
});
|
||
|
||
safeHook('com.squareup.okhttp.FormEncodingBuilder.add/addEncoded', function () {
|
||
const FormBuilder = Java.use('com.squareup.okhttp.FormEncodingBuilder');
|
||
|
||
const add = FormBuilder.add.overload('java.lang.String', 'java.lang.String');
|
||
add.implementation = function (name, value) {
|
||
emitFormField('OKHTTP2_FORM_ADD', name, value);
|
||
return add.call(this, name, value);
|
||
};
|
||
|
||
const addEncoded = FormBuilder.addEncoded.overload('java.lang.String', 'java.lang.String');
|
||
addEncoded.implementation = function (name, value) {
|
||
emitFormField('OKHTTP2_FORM_ADD_ENCODED', name, value);
|
||
return addEncoded.call(this, name, value);
|
||
};
|
||
});
|
||
|
||
if (CFG.RESPONSE_BODY_STRING) {
|
||
safeHook('okhttp3.Response.body -> ResponseBody.string', function () {
|
||
const Response = Java.use('okhttp3.Response');
|
||
const bodyOv = Response.body.overload();
|
||
bodyOv.implementation = function () {
|
||
const body = bodyOv.call(this);
|
||
try {
|
||
const req = this.request();
|
||
const url = requestUrlByHash[objId(req)] || String(req.url());
|
||
if (body !== null && body !== undefined && isTrafficUrl(url)) {
|
||
responseBodyUrlByHash[objId(body)] = url;
|
||
emit('OKHTTP_RESPONSE_BODY', {
|
||
body_hash: objId(body),
|
||
request_hash: objId(req),
|
||
code: this.code(),
|
||
url: shortValue(url, 700)
|
||
});
|
||
}
|
||
} catch (e) {}
|
||
return body;
|
||
};
|
||
|
||
const ResponseBody = Java.use('okhttp3.ResponseBody');
|
||
const stringOv = ResponseBody.string.overload();
|
||
stringOv.implementation = function () {
|
||
const ret = stringOv.call(this);
|
||
try {
|
||
const url = responseBodyUrlByHash[objId(this)] || '';
|
||
if (isTrafficUrl(url) || isInterestingValue(ret) || String(ret).indexOf('a_y_q_z') >= 0) {
|
||
emit('OKHTTP_RESPONSE_BODY_STRING', {
|
||
body_hash: objId(this),
|
||
url: shortValue(url, 700),
|
||
...namedValueFields('body', ret, 1000, isTrafficUrl(url) || isInterestingValue(ret))
|
||
});
|
||
}
|
||
} catch (e) {
|
||
emit('OKHTTP_RESPONSE_BODY_STRING_ERR', { err: String(e) });
|
||
}
|
||
return ret;
|
||
};
|
||
});
|
||
} else {
|
||
emit('HOOK_SKIPPED', { name: 'okhttp3.Response.body -> ResponseBody.string', reason: 'response_body_string_disabled' });
|
||
}
|
||
});
|
||
})();
|