'use strict'; /** * MariBank 注册 trace — attach 模式优先,聚焦 Java 层(OkHttp / Gson / 加密包装) */ const TAG = '[MB-TRACE]'; const MAX_STR = 2000; function log(msg) { console.log(TAG + ' ' + msg); } function shouldLogUrl(url) { if (!url) return false; const u = String(url).toLowerCase(); return u.indexOf('register') >= 0 || u.indexOf('dfp') >= 0 || u.indexOf('risk') >= 0 || u.indexOf('uapi') >= 0; } function hexPreview(arr, limit) { const n = Math.min(arr.length, limit || 64); let hex = ''; for (let i = 0; i < n; i++) { const b = (arr[i] & 0xff).toString(16); hex += (b.length === 1 ? '0' : '') + b; } if (arr.length > n) hex += '...'; return hex; } function dumpJava(tag, obj) { if (obj === null || obj === undefined) { log(tag + ' = null'); return; } try { const cls = obj.getClass().getName(); if (cls === '[B') { const arr = Java.cast(obj, Java.use('[B')); let text = ''; try { text = Java.use('java.lang.String').$new(arr, 'UTF-8').toString(); } catch (e) { text = ''; } const show = text.length > MAX_STR ? text.substring(0, MAX_STR) + '...' : text; log(tag + ' byte[' + arr.length + '] hex=' + hexPreview(arr, 48) + ' text=' + show); return; } if (cls === 'java.lang.String') { const s = Java.cast(obj, Java.use('java.lang.String')).toString(); const show = s.length > MAX_STR ? s.substring(0, MAX_STR) + '...' : s; log(tag + ' String(' + s.length + ') ' + show); return; } log(tag + ' ' + cls + ' = ' + obj.toString()); } catch (e) { log(tag + ' err=' + e); } } function hookOkHttp() { const RealCall = Java.use('okhttp3.RealCall'); const orig = RealCall.execute; RealCall.execute.implementation = function () { const req = this.request(); const url = req.url().toString(); const method = req.method(); if (shouldLogUrl(url)) { log('HTTP >> ' + method + ' ' + url); try { const body = req.body(); if (body) { const Buffer = Java.use('okio.Buffer'); const buf = Buffer.$new(); body.writeTo(buf); const bytes = buf.readByteArray(); if (bytes) dumpJava(' reqBody', Java.array('byte', bytes)); } } catch (e) { log(' reqBody err: ' + e); } } const resp = orig.call(this); if (shouldLogUrl(url)) { try { const peek = resp.peekBody(Java.use('java.lang.Long').parseLong('1048576')); const s = peek.string(); const show = s.length > MAX_STR ? s.substring(0, MAX_STR) + '...' : s; log('HTTP << ' + resp.code() + ' ' + show); } catch (e) { log('HTTP resp err: ' + e); } } return resp; }; log('hooked RealCall.execute'); } function hookGson() { const Gson = Java.use('com.google.gson.Gson'); Gson.toJson.overload('java.lang.Object').implementation = function (obj) { const ret = this.toJson(obj); if (ret) { const low = ret.toLowerCase(); if (low.indexOf('mobile') >= 0 || low.indexOf('phone') >= 0 || low.indexOf('risktoken') >= 0 || low.indexOf('register') >= 0 || low.indexOf('4067') >= 0) { const show = ret.length > MAX_STR ? ret.substring(0, MAX_STR) + '...' : ret; log('Gson.toJson ' + show); } } return ret; }; log('hooked Gson.toJson'); } function hookRisk() { const vv = Java.use('com.shopee.shpssdkbank.uwuvuvvww.vvuuuuvvv'); vv.wwvuwuwvu.overload('android.content.Context').implementation = function (ctx) { const ret = this.wwvuwuwvu(ctx); dumpJava('riskToken', ret); return ret; }; log('hooked vvuuuuvvv.wwvuwuwvu'); } function hookEncryptWrapper() { const D = Java.use('com.shopee.bke.lib.jni.utils.d'); const methods = D.class.getDeclaredMethods(); for (let i = 0; i < methods.length; i++) { const m = methods[i]; const name = m.getName(); if (m.getModifiers() & 0x0100) continue; try { D[name].overloads.forEach(function (ovl) { ovl.implementation = function () { const args = [].slice.call(arguments); log('>> EncryptWrapper.' + name); args.forEach(function (a, idx) { dumpJava(' in' + idx, a); }); const ret = ovl.apply(this, args); if (ret && ret.getClass) { const cn = ret.getClass().getName(); if (cn === '[Ljava.lang.String;') { const arr = Java.cast(ret, Java.use('[Ljava.lang.String;')); for (let j = 0; j < arr.length; j++) dumpJava(' out' + j, arr[j]); } else { dumpJava(' ret', ret); } } return ret; }; }); } catch (e) {} } log('hooked NativeEncryptUtilsWrapper (utils.d)'); } function installAll() { Java.perform(function () { log('Java.perform OK pid=' + Process.id); try { hookOkHttp(); } catch (e) { log('okhttp fail: ' + e); } try { hookGson(); } catch (e) { log('gson fail: ' + e); } try { hookRisk(); } catch (e) { log('risk fail: ' + e); } try { hookEncryptWrapper(); } catch (e) { log('encrypt fail: ' + e); } log('READY — 请在 App 输入号码点 Next'); }); } function waitForJava(n) { n = n || 0; if (typeof Java === 'undefined' || !Java.available) { if (n % 5 === 0) log('waiting Java.available attempt=' + n); setTimeout(function () { waitForJava(n + 1); }, 500); return; } installAll(); } setImmediate(function () { log('script loaded pid=' + Process.id); waitForJava(0); });