1
0
mirror of https://github.com/Mrs4s/MiraiGo.git synced 2025-05-04 11:07:40 +08:00

client: remove SystemDeviceInfo [break]

This commit is contained in:
wdvxdr 2023-02-14 23:23:09 +08:00
parent 3ff1fee1b6
commit cfd7d92d1f
6 changed files with 131 additions and 121 deletions

View File

@ -137,9 +137,8 @@ func (c *QQClient) buildDeviceLockLoginPacket() (uint16, []byte) {
} }
func (c *QQClient) buildQRCodeFetchRequestPacket(size, margin, ecLevel uint32) (uint16, []byte) { func (c *QQClient) buildQRCodeFetchRequestPacket(size, margin, ecLevel uint32) (uint16, []byte) {
version := c.transport.Version
watch := auth.AndroidWatch.Version() watch := auth.AndroidWatch.Version()
c.transport.Version = watch c.transport.Version = &watch
seq := c.nextSeq() seq := c.nextSeq()
req := oicq.Message{ req := oicq.Message{
Command: 0x0812, Command: 0x0812,
@ -173,13 +172,13 @@ func (c *QQClient) buildQRCodeFetchRequestPacket(size, margin, ecLevel uint32) (
Body: c.oicq.Marshal(&req), Body: c.oicq.Marshal(&req),
} }
payload := c.transport.PackPacket(&r) payload := c.transport.PackPacket(&r)
c.transport.Version = version c.transport.Version = &c.version
return seq, payload return seq, payload
} }
func (c *QQClient) buildQRCodeResultQueryRequestPacket(sig []byte) (uint16, []byte) { func (c *QQClient) buildQRCodeResultQueryRequestPacket(sig []byte) (uint16, []byte) {
version := c.transport.Version watch := auth.AndroidWatch.Version()
c.transport.Version = auth.AndroidWatch.Version() c.transport.Version = &watch
seq := c.nextSeq() seq := c.nextSeq()
req := oicq.Message{ req := oicq.Message{
Command: 0x0812, Command: 0x0812,
@ -209,7 +208,7 @@ func (c *QQClient) buildQRCodeResultQueryRequestPacket(sig []byte) (uint16, []by
Body: c.oicq.Marshal(&req), Body: c.oicq.Marshal(&req),
} }
payload := c.transport.PackPacket(&r) payload := c.transport.PackPacket(&r)
c.transport.Version = version c.transport.Version = &c.version
return seq, payload return seq, payload
} }

View File

@ -4,7 +4,6 @@ import (
"crypto/md5" "crypto/md5"
"fmt" "fmt"
"math/rand" "math/rand"
"net"
"net/netip" "net/netip"
"sort" "sort"
"strconv" "strconv"
@ -62,6 +61,7 @@ type QQClient struct {
// internal state // internal state
handlers syncx.Map[uint16, *handlerInfo] handlers syncx.Map[uint16, *handlerInfo]
waiters syncx.Map[string, func(any, error)] waiters syncx.Map[string, func(any, error)]
initServerOnce sync.Once
servers []netip.AddrPort servers []netip.AddrPort
currServerIndex int currServerIndex int
retryTimes int retryTimes int
@ -197,15 +197,12 @@ func NewClientMd5(uin int64, passwordMd5 [16]byte) *QQClient {
onlinePushCache: utils.NewCache[unit](time.Second * 15), onlinePushCache: utils.NewCache[unit](time.Second * 15),
alive: true, alive: true,
highwaySession: new(highway.Session), highwaySession: new(highway.Session),
version: new(auth.AppVersion),
device: new(auth.Device),
} }
cli.transport = &network.Transport{ cli.transport = &network.Transport{
Sig: cli.sig, Sig: cli.sig,
Version: cli.version, Version: &cli.version,
Device: cli.device, Device: &cli.device,
} }
cli.oicq = oicq.NewCodec(cli.Uin) cli.oicq = oicq.NewCodec(cli.Uin)
{ // init atomic values { // init atomic values
@ -217,62 +214,18 @@ func NewClientMd5(uin int64, passwordMd5 [16]byte) *QQClient {
} }
cli.highwaySession.Uin = strconv.FormatInt(cli.Uin, 10) cli.highwaySession.Uin = strconv.FormatInt(cli.Uin, 10)
cli.GuildService = &GuildService{c: cli} cli.GuildService = &GuildService{c: cli}
cli.UseDevice(SystemDeviceInfo)
sso, err := getSSOAddress()
if err == nil && len(sso) > 0 {
cli.servers = append(sso, cli.servers...)
}
adds, err := net.LookupIP("msfwifi.3g.qq.com") // host servers
if err == nil && len(adds) > 0 {
var hostAddrs []netip.AddrPort
for _, addr := range adds {
ip, ok := netip.AddrFromSlice(addr.To4())
if ok {
hostAddrs = append(hostAddrs, netip.AddrPortFrom(ip, 8080))
}
}
cli.servers = append(hostAddrs, cli.servers...)
}
if len(cli.servers) == 0 {
cli.servers = []netip.AddrPort{ // default servers
netip.AddrPortFrom(netip.AddrFrom4([4]byte{42, 81, 172, 81}), 80),
netip.AddrPortFrom(netip.AddrFrom4([4]byte{114, 221, 148, 59}), 14000),
netip.AddrPortFrom(netip.AddrFrom4([4]byte{42, 81, 172, 147}), 443),
netip.AddrPortFrom(netip.AddrFrom4([4]byte{125, 94, 60, 146}), 80),
netip.AddrPortFrom(netip.AddrFrom4([4]byte{114, 221, 144, 215}), 80),
netip.AddrPortFrom(netip.AddrFrom4([4]byte{42, 81, 172, 22}), 80),
}
}
pings := make([]int64, len(cli.servers))
wg := sync.WaitGroup{}
wg.Add(len(cli.servers))
// println(len(cli.servers))
for i := range cli.servers {
go func(index int) {
defer wg.Done()
p, err := qualityTest(cli.servers[index].String())
if err != nil {
pings[index] = 9999
return
}
pings[index] = p
}(i)
}
wg.Wait()
sort.Slice(cli.servers, func(i, j int) bool {
return pings[i] < pings[j]
})
if len(cli.servers) > 3 {
cli.servers = cli.servers[0 : len(cli.servers)/2] // 保留ping值中位数以上的server
}
cli.TCP.PlannedDisconnect(cli.plannedDisconnect) cli.TCP.PlannedDisconnect(cli.plannedDisconnect)
cli.TCP.UnexpectedDisconnect(cli.unexpectedDisconnect) cli.TCP.UnexpectedDisconnect(cli.unexpectedDisconnect)
return cli return cli
} }
func (c *QQClient) Device() *DeviceInfo {
return c.device
}
func (c *QQClient) UseDevice(info *auth.Device) { func (c *QQClient) UseDevice(info *auth.Device) {
*c.version = *info.Protocol.Version() c.version = info.Protocol.Version()
*c.device = *info c.device = info
c.highwaySession.AppID = int32(c.version.AppId) c.highwaySession.AppID = int32(c.version.AppId)
c.sig.Ksid = []byte(fmt.Sprintf("|%s|A8.2.7.27f6ea96", info.IMEI)) c.sig.Ksid = []byte(fmt.Sprintf("|%s|A8.2.7.27f6ea96", info.IMEI))
} }

View File

@ -31,15 +31,20 @@ type (
Version = auth.OSVersion Version = auth.OSVersion
) )
var SystemDeviceInfo = &DeviceInfo{ var EmptyBytes = make([]byte, 0)
Display: []byte("MIRAI.123456.001"),
func GenRandomDevice() *DeviceInfo {
r := make([]byte, 16)
crand.Read(r)
const numberRange = "0123456789"
var device = &DeviceInfo{
Product: []byte("mirai"), Product: []byte("mirai"),
Device: []byte("mirai"), Device: []byte("mirai"),
Board: []byte("mirai"), Board: []byte("mirai"),
Brand: []byte("mamoe"), Brand: []byte("mamoe"),
Model: []byte("mirai"), Model: []byte("mirai"),
Bootloader: []byte("unknown"), Bootloader: []byte("unknown"),
FingerPrint: []byte("mamoe/mirai/mirai:10/MIRAI.200122.001/1234567:user/release-keys"),
BootId: []byte("cb886ae2-00b6-4d68-a230-787f111d12c7"), BootId: []byte("cb886ae2-00b6-4d68-a230-787f111d12c7"),
ProcVersion: []byte("Linux version 3.0.31-cb886ae2 (android-build@xxx.xxx.xxx.xxx.com)"), ProcVersion: []byte("Linux version 3.0.31-cb886ae2 (android-build@xxx.xxx.xxx.xxx.com)"),
BaseBand: EmptyBytes, BaseBand: EmptyBytes,
@ -63,34 +68,20 @@ var SystemDeviceInfo = &DeviceInfo{
}, },
} }
var EmptyBytes = make([]byte, 0) device.Display = []byte("MIRAI." + utils.RandomStringRange(6, numberRange) + ".001")
device.FingerPrint = []byte("mamoe/mirai/mirai:10/MIRAI.200122.001/" + utils.RandomStringRange(7, numberRange) + ":user/release-keys")
func init() { device.BootId = binary.GenUUID(r)
r := make([]byte, 16) device.ProcVersion = []byte("Linux version 3.0.31-" + utils.RandomString(8) + " (android-build@xxx.xxx.xxx.xxx.com)")
crand.Read(r) crand.Read(r)
t := md5.Sum(r) t := md5.Sum(r)
SystemDeviceInfo.IMSIMd5 = t[:] device.IMSIMd5 = t[:]
SystemDeviceInfo.GenNewGuid() device.IMEI = GenIMEI()
SystemDeviceInfo.GenNewTgtgtKey()
}
func GenRandomDevice() {
r := make([]byte, 16)
crand.Read(r)
const numberRange = "0123456789"
SystemDeviceInfo.Display = []byte("MIRAI." + utils.RandomStringRange(6, numberRange) + ".001")
SystemDeviceInfo.FingerPrint = []byte("mamoe/mirai/mirai:10/MIRAI.200122.001/" + utils.RandomStringRange(7, numberRange) + ":user/release-keys")
SystemDeviceInfo.BootId = binary.GenUUID(r)
SystemDeviceInfo.ProcVersion = []byte("Linux version 3.0.31-" + utils.RandomString(8) + " (android-build@xxx.xxx.xxx.xxx.com)")
crand.Read(r)
t := md5.Sum(r)
SystemDeviceInfo.IMSIMd5 = t[:]
SystemDeviceInfo.IMEI = GenIMEI()
r = make([]byte, 8) r = make([]byte, 8)
crand.Read(r) crand.Read(r)
hex.Encode(SystemDeviceInfo.AndroidId, r) hex.Encode(device.AndroidId, r)
SystemDeviceInfo.GenNewGuid() device.GenNewGuid()
SystemDeviceInfo.GenNewTgtgtKey() device.GenNewTgtgtKey()
return device
} }
func GenIMEI() string { func GenIMEI() string {
@ -114,13 +105,13 @@ func GenIMEI() string {
return final.String() return final.String()
} }
func getSSOAddress() ([]netip.AddrPort, error) { func getSSOAddress(device *auth.Device) ([]netip.AddrPort, error) {
protocol := SystemDeviceInfo.Protocol.Version() protocol := device.Protocol.Version()
key, _ := hex.DecodeString("F0441F5FF42DA58FDCF7949ABA62D411") key, _ := hex.DecodeString("F0441F5FF42DA58FDCF7949ABA62D411")
payload := jce.NewJceWriter(). // see ServerConfig.d payload := jce.NewJceWriter(). // see ServerConfig.d
WriteInt64(0, 1).WriteInt64(0, 2).WriteByte(1, 3). WriteInt64(0, 1).WriteInt64(0, 2).WriteByte(1, 3).
WriteString("00000", 4).WriteInt32(100, 5). WriteString("00000", 4).WriteInt32(100, 5).
WriteInt32(int32(protocol.AppId), 6).WriteString(SystemDeviceInfo.IMEI, 7). WriteInt32(int32(protocol.AppId), 6).WriteString(device.IMEI, 7).
WriteInt64(0, 8).WriteInt64(0, 9).WriteInt64(0, 10). WriteInt64(0, 8).WriteInt64(0, 9).WriteInt64(0, 10).
WriteInt64(0, 11).WriteByte(0, 12).WriteInt64(0, 13).Bytes() WriteInt64(0, 11).WriteByte(0, 12).WriteInt64(0, 13).Bytes()
buf := &jce.RequestDataVersion3{ buf := &jce.RequestDataVersion3{

View File

@ -139,6 +139,14 @@ func (info *Device) ReadJson(d []byte) error {
default: default:
info.Protocol = IPad info.Protocol = IPad
} }
v := new(OSVersion)
v.SDK = f.Version.Sdk
v.Release = []byte(f.Version.Release)
v.CodeName = []byte(f.Version.Codename)
v.Incremental = []byte(f.Version.Incremental)
info.Version = v
info.GenNewGuid() info.GenNewGuid()
info.GenNewTgtgtKey() info.GenNewTgtgtKey()
return nil return nil

View File

@ -10,8 +10,8 @@ import (
// Transport is a network transport. // Transport is a network transport.
type Transport struct { type Transport struct {
Sig *auth.SigInfo Sig *auth.SigInfo
Version *auth.AppVersion Version **auth.AppVersion
Device *auth.Device Device **auth.Device
// connection // connection
// conn *TCPClient // conn *TCPClient
@ -21,8 +21,8 @@ func (t *Transport) packBody(req *Request, w *binary.Writer) {
pos := w.FillUInt32() pos := w.FillUInt32()
if req.Type == RequestTypeLogin { if req.Type == RequestTypeLogin {
w.WriteUInt32(uint32(req.SequenceID)) w.WriteUInt32(uint32(req.SequenceID))
w.WriteUInt32(t.Version.AppId) w.WriteUInt32((*t.Version).AppId)
w.WriteUInt32(t.Version.SubAppId) w.WriteUInt32((*t.Version).SubAppId)
w.Write([]byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00}) w.Write([]byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00})
tgt := t.Sig.TGT tgt := t.Sig.TGT
if len(tgt) == 0 || len(tgt) == 4 { if len(tgt) == 0 || len(tgt) == 4 {
@ -36,7 +36,7 @@ func (t *Transport) packBody(req *Request, w *binary.Writer) {
w.WriteUInt32(uint32(len(t.Sig.OutPacketSessionID) + 4)) w.WriteUInt32(uint32(len(t.Sig.OutPacketSessionID) + 4))
w.Write(t.Sig.OutPacketSessionID) w.Write(t.Sig.OutPacketSessionID)
if req.Type == RequestTypeLogin { if req.Type == RequestTypeLogin {
w.WriteString(t.Device.IMEI) w.WriteString((*t.Device).IMEI)
w.WriteUInt32(0x04) w.WriteUInt32(0x04)
w.WriteUInt16(uint16(len(t.Sig.Ksid)) + 2) w.WriteUInt16(uint16(len(t.Sig.Ksid)) + 2)

View File

@ -2,7 +2,9 @@ package client
import ( import (
"net" "net"
"net/netip"
"runtime/debug" "runtime/debug"
"sort"
"sync" "sync"
"time" "time"
@ -86,8 +88,65 @@ func (c *QQClient) ConnectionQualityTest() *ConnectionQualityInfo {
return r return r
} }
func (c *QQClient) initServers() {
if c.device == nil {
// must have device. Use c.UseDevice to set it!
panic("client device is nil")
}
sso, err := getSSOAddress(c.device)
if err == nil && len(sso) > 0 {
c.servers = append(sso, c.servers...)
}
adds, err := net.LookupIP("msfwifi.3g.qq.com") // host servers
if err == nil && len(adds) > 0 {
var hostAddrs []netip.AddrPort
for _, addr := range adds {
ip, ok := netip.AddrFromSlice(addr.To4())
if ok {
hostAddrs = append(hostAddrs, netip.AddrPortFrom(ip, 8080))
}
}
c.servers = append(hostAddrs, c.servers...)
}
if len(c.servers) == 0 {
c.servers = []netip.AddrPort{ // default servers
netip.AddrPortFrom(netip.AddrFrom4([4]byte{42, 81, 172, 81}), 80),
netip.AddrPortFrom(netip.AddrFrom4([4]byte{114, 221, 148, 59}), 14000),
netip.AddrPortFrom(netip.AddrFrom4([4]byte{42, 81, 172, 147}), 443),
netip.AddrPortFrom(netip.AddrFrom4([4]byte{125, 94, 60, 146}), 80),
netip.AddrPortFrom(netip.AddrFrom4([4]byte{114, 221, 144, 215}), 80),
netip.AddrPortFrom(netip.AddrFrom4([4]byte{42, 81, 172, 22}), 80),
}
}
pings := make([]int64, len(c.servers))
wg := sync.WaitGroup{}
wg.Add(len(c.servers))
for i := range c.servers {
go func(index int) {
defer wg.Done()
p, err := qualityTest(c.servers[index].String())
if err != nil {
pings[index] = 9999
return
}
pings[index] = p
}(i)
}
wg.Wait()
sort.Slice(c.servers, func(i, j int) bool {
return pings[i] < pings[j]
})
if len(c.servers) > 3 {
c.servers = c.servers[0 : len(c.servers)/2] // 保留ping值中位数以上的server
}
}
// connect 连接到 QQClient.servers 中的服务器 // connect 连接到 QQClient.servers 中的服务器
func (c *QQClient) connect() error { func (c *QQClient) connect() error {
// init qq servers
c.initServerOnce.Do(c.initServers)
addr := c.servers[c.currServerIndex].String() addr := c.servers[c.currServerIndex].String()
c.info("connect to server: %v", addr) c.info("connect to server: %v", addr)
err := c.TCP.Connect(addr) err := c.TCP.Connect(addr)