Sekiro在爬虫JS逆向中的应用

首先先抽取一个幸运儿,找个登陆接口
sekiro1-1.png
可以看到请求参数如下
img.png
其中password明显是通过某种方式加密了(请求参数中其他参数来源不是重点~),所以本文主要内容就是:

  1. 如何在前端找到加密过程
  2. 如何使用Sekiro进行远程RPC调用

第一部分:在前端找到加密的过程

针对前端对password是如何加密的,先列结果:

  1. 通过前序API获得盐+公钥
  2. 对盐+密码原文进行拼接
  3. 通过公钥一并加密
  4. 进行编码

然后来具体地看看
img.png

进到encrypt()方法(我这里的明文密码是222333,前面的是加盐
img.png
getKey()是获取公钥就不看了,看下encrypt()c()

  1. encrypt()
    img_1.png
    里头doPublic就是使用公钥加密
  2. c()
    img.png
    这里出来的r就是我们想要的password了
    对比一下最后的请求参数里的password,嗯确实是一致的
    img.png

第二部分:使用Sekiro进行远程RPC调用

首先说一哈,这个例子的password加密不是仅仅一个函数,分散了很多步骤,还涉及前序请求的盐+公钥,实行起来会麻烦一点。

我们简化一下,假设前端代码是utility.getPwdEncrypt() ,返回一个加密后的字符串。 先贴一下Sekiro的官方文档,如果目标网站是https请根据官方文档下载根证书并安装。

过程:将js代码注入浏览器环境(下面这个是官网的例子)

function SekiroClient(e){if(this.wsURL=e,this.handlers={},this.socket={},!e)throw new Error("wsURL can not be empty!!");this.webSocketFactory=this.resolveWebSocketFactory(),this.connect()}SekiroClient.prototype.resolveWebSocketFactory=function(){if("object"==typeof window){var e=window.WebSocket?window.WebSocket:window.MozWebSocket;return function(o){function t(o){this.mSocket=new e(o)}return t.prototype.close=function(){this.mSocket.close()},t.prototype.onmessage=function(e){this.mSocket.onmessage=e},t.prototype.onopen=function(e){this.mSocket.onopen=e},t.prototype.onclose=function(e){this.mSocket.onclose=e},t.prototype.send=function(e){this.mSocket.send(e)},new t(o)}}if("object"==typeof weex)try{console.log("test webSocket for weex");var o=weex.requireModule("webSocket");return console.log("find webSocket for weex:"+o),function(e){try{o.close()}catch(e){}return o.WebSocket(e,""),o}}catch(e){console.log(e)}if("object"==typeof WebSocket)return function(o){return new e(o)};throw new Error("the js environment do not support websocket")},SekiroClient.prototype.connect=function(){console.log("sekiro: begin of connect to wsURL: "+this.wsURL);var e=this;try{this.socket=this.webSocketFactory(this.wsURL)}catch(o){return console.log("sekiro: create connection failed,reconnect after 2s:"+o),void setTimeout(function(){e.connect()},2e3)}this.socket.onmessage(function(o){e.handleSekiroRequest(o.data)}),this.socket.onopen(function(e){console.log("sekiro: open a sekiro client connection")}),this.socket.onclose(function(o){console.log("sekiro: disconnected ,reconnection after 2s"),setTimeout(function(){e.connect()},2e3)})},SekiroClient.prototype.handleSekiroRequest=function(e){console.log("receive sekiro request: "+e);var o=JSON.parse(e),t=o.__sekiro_seq__;if(o.action){var n=o.action;if(this.handlers[n]){var s=this.handlers[n],i=this;try{s(o,function(e){try{i.sendSuccess(t,e)}catch(e){i.sendFailed(t,"e:"+e)}},function(e){i.sendFailed(t,e)})}catch(e){console.log("error: "+e),i.sendFailed(t,":"+e)}}else this.sendFailed(t,"no action handler: "+n+" defined")}else this.sendFailed(t,"need request param {action}")},SekiroClient.prototype.sendSuccess=function(e,o){var t;if("string"==typeof o)try{t=JSON.parse(o)}catch(e){(t={}).data=o}else"object"==typeof o?t=o:(t={}).data=o;(Array.isArray(t)||"string"==typeof t)&&(t={data:t,code:0}),t.code?t.code=0:(t.status,t.status=0),t.__sekiro_seq__=e;var n=JSON.stringify(t);console.log("response :"+n),this.socket.send(n)},SekiroClient.prototype.sendFailed=function(e,o){"string"!=typeof o&&(o=JSON.stringify(o));var t={};t.message=o,t.status=-1,t.__sekiro_seq__=e;var n=JSON.stringify(t);console.log("sekiro: response :"+n),this.socket.send(n)},SekiroClient.prototype.registerAction=function(e,o){if("string"!=typeof e)throw new Error("an action must be string");if("function"!=typeof o)throw new Error("a handler must be function");return console.log("sekiro: register action: "+e),this.handlers[e]=o,this};
var client = new SekiroClient("wss://sekiro.iinti.cn:5612/business/register?group=test_web&clientId=" + Math.random());
client.registerAction("testAction", function (request, resolve, reject) {
    resolve("ok");
});

resolve里可以写具体的操作,比如收到消息就直接调用源前端代码函数utility.getPwdEncrypt()得到加密参数并发送给服务端

使用Sekiro的好处

  1. 如果不使用Sekiro,需要自己写一个服务端,打开某个端口,建立websocket连接,比较麻烦,并且也不容易扩展。
  2. 目前Sekiro的能力也不只是用于Web场景,可以用于以下多种场景。
    • Frida环境
    • android(Xposed)
    • 浏览器js环境
    • IOS环境
    • python语言
    • go语言
  3. 目前Sekiro提供了丰富的功能:
    • 查看当前系统注册的group和挂载的队列
    • 请求参数扁平化的调用转发
    • 多种访问授权机制
    • 多种调用转发策略