赞
踩
之前为了搞微信机器人我造了个双开工具,这个双开工具就是基于LSPosed框架开发的,LSPosed框架本身就是兼容支持XPosed接口的开发的模块。于是微信机器人模块,我也是基于Xposed框架开发的,因为这样更方便一些。
原理:通过LSPosed 提供的Hook能力,Hook了微信代码里,接收消息的函数,和发送消息的函数。当收到消息时,将消息内容,通过封装的讯飞星火GPT接口发送给讯飞GPT,等到接口回调回来内容,则将内容通过发射调用微信发送代码,将消息发送出去。
基础知识:
1.Android Apk基础逆向知识。
2.Android及Websocket开发知识。
工具:
1.jadx反编译工具。
2.AndroidStudio。
组件:
1.XposedAPI java包,用于Hook微信代码里的接收消息。
2.OKHttp框架,用于和讯飞GPT通信,因为讯飞给的SDK里包含Native代码,但是Xposed模块不支持native开发,所以需要自己写一个。
XPosed工程配置
配置好XPosed开发工程,这里就不展开了,了解点逆向的人都知道。
可以根据这篇文章进行配置。
讯飞GPT库搭建
由于Xposed框架不支持lib库的加载,但是讯飞的Android版本API包是将网络请求部分封装到Native层,无法直接调用,所以我就基于OKHttp框架,实现一个简单的Java Websocket功能,用来和讯飞GPT交互。
发送消息函数
private void sendWebSocket(String msg) { try { JSONObject requestJson = new JSONObject(); JSONObject header = new JSONObject(); // header参数 header.put("app_id", appid); header.put("uid", userId); JSONObject parameter = new JSONObject(); // parameter参数 JSONObject chat = new JSONObject(); chat.put("domain", "generalv3"); chat.put("temperature", 0.5); chat.put("max_tokens", 4096); parameter.put("chat", chat); JSONObject payload = new JSONObject(); // payload参数 JSONObject message = new JSONObject(); JSONArray text = new JSONArray(); List<RoleContent> historyList = getHistoryList(userId); // 历史问题获取 if (historyList.size() > 0) { for (RoleContent tempRoleContent : historyList) { text.add(JSON.toJSON(tempRoleContent)); } } // 最新问题 RoleContent roleContent = new RoleContent(); roleContent.role = "user"; roleContent.content = msg; text.add(JSON.toJSON(roleContent)); historyList.add(roleContent); message.put("text", text); payload.put("message", message); requestJson.put("header", header); requestJson.put("parameter", parameter); requestJson.put("payload", payload); // System.err.println(requestJson); // 可以打印看每次的传参明细 webSocket.send(requestJson.toString()); } catch (Exception e) { e.printStackTrace(); } }
接收消息解析函数
public void onMessage(WebSocket webSocket, String text) { // Log.e("SparkChat", userId + "用来区分那个用户的结果" + text); JsonParse myJsonParse = gson.fromJson(text, JsonParse.class); if (myJsonParse.header.code != 0) { Log.e("SparkChat","发生错误,错误码为:" + myJsonParse.header.code); Log.e("SparkChat","本次请求的sid为:" + myJsonParse.header.sid); webSocket.close(1000, ""); } Log.d("SparkChat","*************************************************************************************"); List<Text> textList = myJsonParse.payload.choices.text; for (Text temp : textList) { Log.d("SparkChatx", temp.content); totalAnswer=totalAnswer+temp.content; } Log.d("SparkChat","*************************************************************************************"); if (myJsonParse.header.status == 2) { // 可以关闭连接,释放资源 List<RoleContent> historyList = getHistoryList(userId); if(canAddHistory(userId)){ RoleContent roleContent=new RoleContent(); roleContent.setRole("assistant"); roleContent.setContent(totalAnswer); historyList.add(roleContent); }else{ historyList.remove(0); RoleContent roleContent=new RoleContent(); roleContent.setRole("assistant"); roleContent.setContent(totalAnswer); historyList.add(roleContent); } totalFlag = true; webSocket.close(1000, null); } }
WX接收Hook和发送代码
// Log.e("SparkChat","t11.c hook"); Method getMsgIdMethod = ReflectUtils.getDeclaredMethod(param.args[1], "getMsgId"); long MsgId = (long) getMsgIdMethod.invoke(param.args[1]); String strMsgId = String.valueOf(MsgId); Log.d("SparkChat","receiver msg id " + strMsgId); Method getContentMethod = ReflectUtils.getDeclaredMethod(param.args[1], "getContent"); String content = (String) getContentMethod.invoke(param.args[1]); Log.d("SparkChat","receiver content " + content); // sendMsg(); UHandler.getHandler().postDelayed(new Runnable() { @Override public void run() { try { BigModelNew talkerModel; if (talkerModels.containsKey(strMsgId)) { talkerModel = talkerModels.get(strMsgId); } else { talkerModel = new BigModelNew(); talkerModel.init(strMsgId, new BigModelNew.IMessageCallback() { @Override public void onMessage(String msg) { UHandler.getHandler().postDelayed(new Runnable() { @Override public void run() { try { Log.d("SparkChat","UI show result text"); Method method = ReflectUtils.getDeclaredMethod(r1Obj, "c", String.class); method.invoke(r1Obj, msg); } catch (Throwable e) { e.printStackTrace(); } } }, 3000); } }); talkerModels.put(strMsgId, talkerModel); } Log.d("SparkChat","tos Send msg to GPT"); talkerModel.sendMsg(content); } catch (Throwable e) { e.printStackTrace(); } } }, 3000); } catch (Throwable e) { e.printStackTrace(); } } });
上面代码中,通过Java Hook,hook 微信Java代码的"t11.c" 类的z1方法,这个方法是收到消息时的分发函数。通过解析参数,就可以获得发送的消息内容,基于微信8.0.43版本。
我也是逆向小白,分享些基础的内容,详细可以去https://github.com/ziyunzhifeng/WeChatGPT 下载Demo源码。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。