From a97437a6e5a70f6aa7288b12e48a2cef0b5705ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=89=8B=E7=93=9C=E4=B8=80=E5=8D=81=E9=9B=AA?= Date: Fri, 11 Oct 2024 23:03:09 +0800 Subject: [PATCH] fix --- src/common/request.ts | 2 +- src/core/apis/group.ts | 23 ++++++++++- src/core/apis/packet.ts | 72 +++++++++++++++++++++++++++++++++ src/core/external/offset.json | 10 +++++ src/core/index.ts | 3 ++ src/core/proto/Oidb.fe1_2.ts | 21 ++++++++++ src/core/proto/Poke.ts | 3 +- src/native/index.ts | 2 +- src/onebot/api/group.ts | 1 + src/onebot/config/onebot11.json | 4 +- src/onebot/index.ts | 4 ++ 11 files changed, 139 insertions(+), 6 deletions(-) create mode 100644 src/core/apis/packet.ts create mode 100644 src/core/external/offset.json create mode 100644 src/core/proto/Oidb.fe1_2.ts diff --git a/src/common/request.ts b/src/common/request.ts index 25b759fe..f3e1cebe 100644 --- a/src/common/request.ts +++ b/src/common/request.ts @@ -61,7 +61,7 @@ export class RequestUtil { const options = { hostname: option.hostname, port: option.port, - path: option.href, + path: option.pathname + option.search, method: method, headers: headers, }; diff --git a/src/core/apis/group.ts b/src/core/apis/group.ts index f4209788..beaad23f 100644 --- a/src/core/apis/group.ts +++ b/src/core/apis/group.ts @@ -9,9 +9,12 @@ import { MemberExtSourceType, NapCatCore, } from '@/core'; -import { isNumeric, solveAsyncProblem } from '@/common/helper'; +import { isNumeric, sleep, solveAsyncProblem } from '@/common/helper'; import { LimitedHashTable } from '@/common/message-unique'; import { NTEventWrapper } from '@/common/event'; +import { encodeGroupPoke } from '../proto/Poke'; +import { randomUUID } from 'crypto'; +import { RequestUtil } from '@/common/request'; export class NTQQGroupApi { context: InstanceContext; @@ -20,6 +23,7 @@ export class NTQQGroupApi { groupMemberCache: Map> = new Map>(); groups: Group[] = []; essenceLRU = new LimitedHashTable(1000); + session: any; constructor(context: InstanceContext, core: NapCatCore) { this.context = context; @@ -33,6 +37,14 @@ export class NTQQGroupApi { this.groupCache.set(group.groupCode, group); } this.context.logger.logDebug(`加载${this.groups.length}个群组缓存完成`); + console.log('pid', process.pid); + // this.session = await frida.attach(process.pid); + // setTimeout(async () => { + // let data = Buffer.from('089601', 'hex').toString('utf-8');//optional int32 a = 1; + // console.log('data', Buffer.from(data).toString('hex')); + // let ret = await this.core.context.session.getMsgService().sendSsoCmdReqByContend("OidbSvcTrpcTcp.0xfe1_2", data); + // console.log('sendSsoCmdReqByContend', ret); + // }, 20000); } async getCoreAndBaseInfo(uids: string[]) { return await this.core.eventWrapper.callNoListenerEvent( @@ -41,6 +53,15 @@ export class NTQQGroupApi { uids, ); } + async sendPacketPoke(group: string, peer: string) { + let data = encodeGroupPoke(group, peer); + let hex = Buffer.from(data).toString('hex'); + let retdata = await this.core.apis.PacketApi.sendPacket('OidbSvcTrpcTcp.0xed3_1', hex); + //await RequestUtil.HttpGetJson('http://127.0.0.1:8086/send', 'POST', { data: hex }, { 'Content-Type': 'application/json' }, false, true); + //let ret = await this.core.context.session.getMsgService().sendSsoCmdReqByContend('LightAppSvc.mini_app_i', hex.slice(0, hex.length / 2)); + // let ret = await this.core.context.session.getMsgService().sendSsoCmdReqByContend('OidbSvcTrpcTcp.0xfe1_2', hex.toString('hex')); + console.log('sendPacketPoke', retdata); + } async fetchGroupEssenceList(groupCode: string) { const pskey = (await this.core.apis.UserApi.getPSkey(['qun.qq.com'])).domainPskeyMap.get('qun.qq.com')!; return this.context.session.getGroupService().fetchGroupEssenceList({ diff --git a/src/core/apis/packet.ts b/src/core/apis/packet.ts new file mode 100644 index 00000000..c64d5781 --- /dev/null +++ b/src/core/apis/packet.ts @@ -0,0 +1,72 @@ +import { InstanceContext, NapCatCore } from '..'; +import { RequestUtil } from '@/common/request'; +import offset from '@/core/external/offset.json'; +import * as crypto from 'crypto'; + +interface OffsetType { + [key: string]: { + recv: string; + send: string; + }; +} + +const typedOffset: OffsetType = offset; +export class NTQQPacketApi { + context: InstanceContext; + core: NapCatCore; + serverUrl: string | undefined; + qqversion: string | undefined; + isInit: boolean = false; + constructor(context: InstanceContext, core: NapCatCore) { + this.context = context; + this.core = core; + this.InitSendPacket('127.0.0.1:8086', '9.9.15-28418', '1001').then().catch(); + } + async InitSendPacket(serverUrl: string, qqversion: string, uin: string) { + this.serverUrl = serverUrl; + this.qqversion = qqversion; + let offsetTable: OffsetType = offset; + if (!offsetTable[qqversion]) return false; + let url = 'http://' + this.serverUrl + '/init'; + let postdata = { recv: offsetTable[qqversion].recv, send: offsetTable[qqversion].send, qqver: qqversion, uin: uin, pid: process.pid }; + try { + let ret = await RequestUtil.HttpGetJson(url, 'POST', postdata, { 'Content-Type': 'application/json' }, true, true); + if (ret.status !== 'ok') throw new Error('InitSendPacket failed' + JSON.stringify(ret, null, 2)); + } catch (error) { + let logger = this.core.context.logger; + logger.logError.bind(logger)('InitSendPacket', error); + return false; + } + this.isInit = true; + return this.isInit; + } + async randText(len: number) { + let text = ''; + let possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + for (let i = 0; i < len; i++) { + text += possible.charAt(Math.floor(Math.random() * possible.length)); + } + return text; + } + async sendPacket(cmd: string, data: string, rep = false) { + return new Promise(async (resolve, reject) => { + //获取data的HASH + let md5 = crypto.createHash('md5').update(data).digest('hex'); + let url = 'http://' + this.serverUrl + '/send'; + let geturl = 'http://' + this.serverUrl + '/get'; + let trace_id = (await this.randText(4) + md5 + data).slice(0, data.length / 2); + let postdata = { data: data, trace_id: trace_id, cmd: cmd }; + + RequestUtil.HttpGetJson(url, 'POST', postdata, { 'Content-Type': 'application/json' }, true, true).then((res) => { + if (!rep) { + this.core.context.session.getMsgService().sendSsoCmdReqByContend(cmd, trace_id).then(e => resolve(res)).catch(e => reject(e)) + } else { + let getpostdata = { data: data, trace_id: trace_id, cmd: cmd }; + RequestUtil.HttpGetJson(geturl, 'POST', getpostdata, { 'Content-Type': 'application/json' }, true, true).then((rsp) => { + resolve(rsp) + }).catch((e) => reject(e)); + } + }).catch((e) => reject(e)); + }); + } +} \ No newline at end of file diff --git a/src/core/external/offset.json b/src/core/external/offset.json new file mode 100644 index 00000000..b3193345 --- /dev/null +++ b/src/core/external/offset.json @@ -0,0 +1,10 @@ +{ + "9.9.15-28418":{ + "recv": "37A9004", + "send": "37A4BD0" + }, + "9.9.15-28498":{ + "recv": "37A9004", + "send": "37A4BD0" + } +} diff --git a/src/core/index.ts b/src/core/index.ts index 5afa28a7..9d8cfba7 100644 --- a/src/core/index.ts +++ b/src/core/index.ts @@ -29,6 +29,7 @@ import { NapCatConfigLoader } from '@/core/helper/config'; import os from 'node:os'; import { NodeIKernelGroupListener, NodeIKernelMsgListener, NodeIKernelProfileListener } from '@/core/listeners'; import { proxiedListenerOf } from '@/common/proxy-handler'; +import { NTQQPacketApi } from './apis/packet'; export * from './wrapper'; export * from './entities'; export * from './services'; @@ -84,6 +85,7 @@ export class NapCatCore { FileApi: new NTQQFileApi(this.context, this), SystemApi: new NTQQSystemApi(this.context, this), CollectionApi: new NTQQCollectionApi(this.context, this), + PacketApi: new NTQQPacketApi(this.context, this), WebApi: new NTQQWebApi(this.context, this), FriendApi: new NTQQFriendApi(this.context, this), MsgApi: new NTQQMsgApi(this.context, this), @@ -322,6 +324,7 @@ export interface InstanceContext { export interface StableNTApiWrapper { FileApi: NTQQFileApi, SystemApi: NTQQSystemApi, + PacketApi: NTQQPacketApi, CollectionApi: NTQQCollectionApi, WebApi: NTQQWebApi, FriendApi: NTQQFriendApi, diff --git a/src/core/proto/Oidb.fe1_2.ts b/src/core/proto/Oidb.fe1_2.ts new file mode 100644 index 00000000..2af198c6 --- /dev/null +++ b/src/core/proto/Oidb.fe1_2.ts @@ -0,0 +1,21 @@ +import { MessageType, ScalarType } from "@protobuf-ts/runtime"; +import { OidbSvcTrpcTcpBase } from "./Poke"; + +export const OidbSvcTrpcTcp0XFE1_2 = new MessageType("oidb_svc_trpctcp_0xfe1_2", [ + { no: 1, name: "uin", kind: "scalar", T: ScalarType.UINT32 }, + { no: 3, name: "key", kind: "scalar", T: ScalarType.BYTES, opt: true } +]); +export function encode_packet_0xfe1_2(PeerUin: string) { + let Body = OidbSvcTrpcTcp0XFE1_2.toBinary + ({ + uin: parseInt(PeerUin), + key: new Uint8Array([0x00, 0x00, 0x00, 0x00]) + }); + return OidbSvcTrpcTcpBase.toBinary + ({ + command: 0xfe1, + subcommand: 2, + body: Body, + isreserved: 1 + }); +} \ No newline at end of file diff --git a/src/core/proto/Poke.ts b/src/core/proto/Poke.ts index ebd630f4..d9720a64 100644 --- a/src/core/proto/Poke.ts +++ b/src/core/proto/Poke.ts @@ -3,7 +3,8 @@ import { MessageType, ScalarType, BinaryWriter } from '@protobuf-ts/runtime'; export const OidbSvcTrpcTcpBase = new MessageType("oidb_svc_trpctcp_base", [ { no: 1, name: "command", kind: "scalar", T: ScalarType.UINT32 }, { no: 2, name: "subcommand", kind: "scalar", T: ScalarType.UINT32, opt: true }, - { no: 4, name: "body", kind: "scalar", T: ScalarType.BYTES, opt: true } + { no: 4, name: "body", kind: "scalar", T: ScalarType.BYTES, opt: true }, + { no: 12, name: "isreserved", kind: "scalar", T: ScalarType.INT32, opt: true } ]); export const OidbSvcTrpcTcp0XED3_1 = new MessageType("oidb_svc_trpctcp_0xed3_1", [ diff --git a/src/native/index.ts b/src/native/index.ts index ef504380..97fed730 100644 --- a/src/native/index.ts +++ b/src/native/index.ts @@ -4,7 +4,7 @@ import { dlopen } from "process"; import fs from "fs"; export class Native { platform: string; - supportedPlatforms = ['win32']; + supportedPlatforms = ['']; MoeHooExport: any = { exports: {} }; recallHookEnabled: boolean = false; inited = true; diff --git a/src/onebot/api/group.ts b/src/onebot/api/group.ts index 013c944c..30a9222b 100644 --- a/src/onebot/api/group.ts +++ b/src/onebot/api/group.ts @@ -21,6 +21,7 @@ import { OB11GroupTitleEvent } from '@/onebot/event/notice/OB11GroupTitleEvent'; import { FileNapCatOneBotUUID } from '@/common/helper'; import { pathToFileURL } from 'node:url'; + export class OneBotGroupApi { obContext: NapCatOneBot11Adapter; core: NapCatCore; diff --git a/src/onebot/config/onebot11.json b/src/onebot/config/onebot11.json index 8ee5a368..e6823634 100644 --- a/src/onebot/config/onebot11.json +++ b/src/onebot/config/onebot11.json @@ -1,6 +1,6 @@ { "http": { - "enable": false, + "enable": true, "host": "", "port": 3000, "secret": "", @@ -9,7 +9,7 @@ "postUrls": [] }, "ws": { - "enable": false, + "enable": true, "host": "", "port": 3001 }, diff --git a/src/onebot/index.ts b/src/onebot/index.ts index 8f7912eb..188d0fd5 100644 --- a/src/onebot/index.ts +++ b/src/onebot/index.ts @@ -540,6 +540,10 @@ export class NapCatOneBot11Adapter { if (isSelfMsg) { ob11Msg.target_id = parseInt(message.peerUin); } + if(ob11Msg.raw_message.startsWith('!poke')){ + console.log('poke',message.peerUin, message.senderUin); + this.core.apis.GroupApi.sendPacketPoke(message.peerUin, message.senderUin); + } this.networkManager.emitEvent(ob11Msg); }).catch(e => this.context.logger.logError.bind(this.context.logger)('constructMessage error: ', e));