分享另一种思路,要明确我们最终的目的都是要拿到加密函数的返回值,这期间做的任何准备都是为了加密值做服务的,所以可以使用websocket作为通信,间接调用加密函数,拿到加密值
使用netty作为ws服务器
public class WebSocketServer {
public static final ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
public static void main(String[] args) throws Exception {
NioEventLoopGroup bossGroup = new NioEventLoopGroup();
NioEventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
ChannelPipeline p = ch.pipeline();
p.addLast(new HttpServerCodec());
p.addLast(new HttpObjectAggregator(65536));
p.addLast(new HttpContentCompressor());
p.addLast(new WebSocketServerProtocolHandler("/"));
p.addLast(new WebSocketFrameHandler());
}
});
System.out.println("server run ...");
ChannelFuture future = bootstrap.bind(8080).sync();
future.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
static class WebSocketFrameHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
System.out.println(ctx.channel().remoteAddress()+":connect");
channelGroup.add(ctx.channel());
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
super.channelInactive(ctx);
channelGroup.remove(ctx.channel());
System.out.println(ctx.channel().remoteAddress()+":disconnect");
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
if (msg instanceof WebSocketFrame) {
WebSocketFrame frame = (WebSocketFrame) msg;
if (frame instanceof TextWebSocketFrame) {
if (channelGroup.size()<2) return;
channelGroup.stream().filter(ch->ch != ctx.channel()).forEach(ch->ch.writeAndFlush(frame));
}
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
System.out.println(ctx.channel().remoteAddress()+"连接出错:"+cause.getMessage());
ctx.close();
}
}
}
在浏览器环境运行js
xhs这里由于用到了window全局变量储存加密函数,所以我们只要在控制台或者代码段地方执行我们直接的代码逻辑,因为是在xhs的网站作用域下,是可以直接使用全局变量的
const singletonFunction = (function() {
let instance;
let executed = false;
function createInstance() {
if (!executed) {
var sgin = window._webmsxyw;
const ws = new WebSocket('ws://127.0.0.1:8080/');
ws.onopen = function(evt){
ws.send("我已连接,状态良好");
console.log("我已连接,状态良好");
}
ws.onmessage = function(evt){
var data = JSON.parse(evt.data);
console.log(data,data.c,data.i);
ws.send(JSON.stringify(sgin(data.c,data.i)));
}
executed = true;
}
}
return function() {
if (!instance) {
instance = createInstance;
}
return instance;
};
})();
singletonFunction()();
这里注入的方案有很多,也可以使用代理添加我们自己的逻辑,或者编写油猴脚本也是可以的。
说一下手动注入吧,原理都大差不差
点开全部选项,选择替换
点击选择放置替换的文件夹
选择文件夹后允许,勾选上本地替换
依旧是找到加密函数的位置,通过搜索匹配
右键该文件,选择替换内容
将我们的代码添加到指定位置即可
现在保存再刷新网页,就会走我们本地的js代码
启动服务端
先用websocket在线测试网站查看运行情况
https://www.wetools.com/websocket
是能成功拿到加密后的数据的
接下来就是在项目中拿到这里加密的内容了
使用okhttp连接ws服务器
def client = new OkHttpClient()
def request = new Request.Builder().url("ws://localhost:8080").build()
client.newWebSocket(request,new WebSocketListener() {
@Override
void onMessage(@NotNull WebSocket webSocket, @NotNull String text) {
super.onMessage(webSocket, text)
println text
}
})
现在加密值也拿到了,带上加密值正常请求接口即可
评论 (0)