之前为了搞微信机器人我造了个双开工具,这个双开工具就是基于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源码。