前言
使用 frida + sekiro 远程 rpc 调用淘宝 sgmain 70102 之前写过一篇类似的,可以参考一下 androidAsync fridaManager 实现某宝 sgmain 70102 rpc 远程调用
frida + sekiro 环境搭建
参考之前的文章: frida 加载 sekiro dex 文件 实现与服务端交互
sekiro java demo
public static void main(String[] args) {
String group = "testJava";
String clientId = "clientId";
String host = "127.0.0.1";
int port = 5620;
SekiroClient sekiroClient = new SekiroClient(group, clientId, host, port);
sekiroClient.setupSekiroRequestInitializer(new SekiroRequestInitializer() {
@Override
public void onSekiroRequest(SekiroRequest sekiroRequest, HandlerRegistry handlerRegistry) {
handlerRegistry.registerSekiroHandler(new ActionHandler() {
@Override
public String action() {
return "time";
}
@Override
public void handleRequest(SekiroRequest sekiroRequest, SekiroResponse sekiroResponse) {
sekiroResponse.success(System.currentTimeMillis());
}
});
}
});
sekiroClient.start();
}
注册了一个 time action 返回当前系统的时间戳 ![](https://img-blog.csdnimg.cn/img_convert/9536bbd61d6dc26860f4dbf1ce52af5f.png) 请求 http://127.0.0.1:5620/business-demo/groupList 结果正常返回 ![](https://img-blog.csdnimg.cn/img_convert/937edc3940a329eda6a1eda486f27ca7.png) 在请求 http://127.0.0.1:5620/business-demo/invoke?group=testJava&action=time 成功返回了时间戳
sekiro frida demo
使用 frida 就是把 java 使用 frida js 重新写一遍
function initSekiro() {
const SekiroClient = Java.use('com.virjar.sekiro.business.api.SekiroClient');
const ActionHandler = Java.use('com.virjar.sekiro.business.api.interfaze.ActionHandler');
const SekiroRequestInitializer = Java.use('com.virjar.sekiro.business.api.interfaze.SekiroRequestInitializer');
const TimeHandler = Java.registerClass({
name: 'TimeHandler',
implements: [ActionHandler],
methods: {
action: function () {
return 'time';
},
handleRequest: function (sekiroRequest, sekiroResponse) {
sekiroResponse.success(String(new Date().getTime()));
}
}
})
const SekiroRequestDefault = Java.registerClass({
name: "SekiroRequestDefault",
implements: [SekiroRequestInitializer],
methods: {
onSekiroRequest: function (sekiroRequest, handlerRegistry) {
handlerRegistry.registerSekiroHandler(TimeHandler.$new());
}
}
});
const clientID = 'XiaoMiK30Pro';
const group = 'fridaHook_' + clientID;
const ip = '192.168.1.108';
const sekiro = SekiroClient.$new(group, clientID, ip, 5620);
sekiro.setupSekiroRequestInitializer(SekiroRequestDefault.$new());
sekiro.start();
}
function main() {
Java.perform(function () {
Java.openClassFile('/data/local/tmp/dexfile/sekiro-business-api-1.4-jar-with-dependencies.dex').load();
Java.openClassFile('/data/local/tmp/dexfile/sekiro-business-api-1.4.dex').load();
initSekiro();
});
}
setImmediate(main);
代码写完,跑起来 ![](https://img-blog.csdnimg.cn/img_convert/5ac1f4a344640e57b8d4f2a77ce84470.png) 请求 http://127.0.0.1:5620/business-demo/groupList 可以看到 group 注册成功了 ![](https://img-blog.csdnimg.cn/img_convert/966fd8d95345b7ea51e3b3e42efdcfad.png) 在请求 http://127.0.0.1:5620/business-demo/invoke?group=fridaHook_XiaoMiK30Pro&action=time 时间戳也正常返回了
sekiro frida hook logger
sekiro frida demo 可以正常跑起来了,但是没有 log 输出 ![](https://img-blog.csdnimg.cn/img_convert/a5e858019e93b4a0f2e744e0a08fc550.png) java demo 这里是有 log 输出的,去看下 java 代码的具体实现 ![](https://img-blog.csdnimg.cn/img_convert/c687049f6deaf33657c7bf88e80e45a4.png)
这里是有 info warn error 多个输出函数,分别会调用 format 拼接字符串,我们直接使用 frida hook 这些函数就行了
function getLocalDateTime() {
const myDate = new Date();
const year = myDate.getFullYear();
const month = myDate.getMonth() + 1;
const month1 = month < 10 ? '0' + month : month;
const date = myDate.getDate();
const date1 = date < 10 ? '0' + date : date;
const hours = myDate.getHours();
const minutes = myDate.getMinutes();
const seconds = myDate.getSeconds();
return year + '-' + month1 + '-' + date1 + ' ' + hours + ':' + minutes + ':' + seconds;
}
function logFormat(levenNum, msg, msg1) {
const leven = {
0: 'info',
1: 'warn',
2: 'error',
};
const androidProcess = Java.use('android.os.Process');
var groupId = msg1.match(/\[sekiroGroup:(.*?)\]/i);
var clientId = msg1.match(/\[clientId:(.*?)\]/i);
var action = msg1.match(/\[action:(.*?)\]/i);
var host = msg1.match(/\[KEY_SERVER_HOST:(.*?)\]/i);
groupId = groupId ? groupId[1] : '';
clientId = clientId ? clientId[1] : '';
action = action ? action[1] : '';
host = host ? host[1] : '';
var string = '';
string += '[leven:' + leven[levenNum] + '] ';
string += '---> [processId: ' + androidProcess.myTid() + '] ';
string += '[' + getLocalDateTime() + '] ';
string += '[groupId:' + groupId + '] ';
string += '[clientId:' + clientId + '] ';
if (action) string += '[action:' + action + '] ';
if (host) string += '[host:' + host + '] -> ';
string += msg;
return string;
}
function hookLoggerMethod() {
const androidLog = Java.use('android.util.Log');
const SekiroLogger = Java.use('com.virjar.sekiro.business.api.log.SekiroLogger');
SekiroLogger.info.overload('java.lang.String').implementation = function (msg) {
console.log(logFormat(0, msg, this.format(msg)));
}
SekiroLogger.info.overload('java.lang.String', 'java.lang.Throwable').implementation = function (msg, throwable) {
console.log(logFormat(0, msg, this.format(msg)), '\n', androidLog.getStackTraceString(throwable));
}
SekiroLogger.warn.overload('java.lang.String').implementation = function (msg) {
console.warn(logFormat(1, msg, this.format(msg)));
}
SekiroLogger.warn.overload('java.lang.String', 'java.lang.Throwable').implementation = function (msg, throwable) {
console.warn(logFormat(1, msg, this.format(msg)), '\n', androidLog.getStackTraceString(throwable));
}
SekiroLogger.error.overload('java.lang.String').implementation = function (msg) {
console.error(logFormat(2, msg, this.format(msg)));
}
SekiroLogger.error.overload('java.lang.String', 'java.lang.Throwable').implementation = function (msg, throwable) {
console.error(logFormat(2, msg, this.format(msg)), '\n', androidLog.getStackTraceString(throwable));
}
}
以上是 hook 实现代码,因为不喜欢他的输出格式,我就自己重新拼接的 ![](https://img-blog.csdnimg.cn/img_convert/0c0580aa0e7d1e6567a7baf50c72eaf1.png) 在 main 函数里加上调用继续跑起来 ![](https://img-blog.csdnimg.cn/img_convert/159284fc7a911f7d23e2b066c755f3b0.png) 我使用了 tee 把日志重定向到了 log 文件里,我加上了 leven processId 跟当前时间
sekiro frida call JNICLibrary.doCommandNative 70102
![](https://img-blog.csdnimg.cn/img_convert/384772fcc8240d354453b7516e728737.png)
先创建一个 taobao Handler 然后在注册,action 是 callTaoBao ,打开淘宝 app 启动 frida 脚本
python 请求测试
![](https://img-blog.csdnimg.cn/img_convert/36dc497b2a47a0c360b9d1b343fd8643.png) python requests 请求获取加密参数 ![](https://img-blog.csdnimg.cn/img_convert/997d08b22f7f7420d50f8e3e3276541f.png) 在请求淘宝详情页接口 ![](https://img-blog.csdnimg.cn/img_convert/c13d686396577840732960b7893a4dc9.png) 请求成功 x-sign x-mini-wua 等参数正常返回,淘宝接口也调用成功正常返回数据了
最后
sekiro + xposed 是最佳方案,奈何使用 xposed 没搞定淘宝的 JNICLibrary.doCommandNative 无奈只能使用 frida + sekiro 主动调用 JNICLibrary.doCommandNative 获取加密结果了
更多精彩内容,源码文件下载等,原文链接,博主个人站点:http://www.qinless.com/400
|