1
0
mirror of https://github.com/Mrs4s/MiraiGo.git synced 2025-05-03 18:47:41 +08:00

client: implement query personal sign

This commit is contained in:
wdvxdr 2023-02-09 22:28:32 +08:00
parent 727686e453
commit f56bcbe326
5 changed files with 144 additions and 49 deletions

View File

@ -17,8 +17,6 @@ type NetworkReader struct {
conn net.Conn
}
type TlvMap map[uint16][]byte
// --- ByteStream reader ---
func NewReader(data []byte) *Reader {
@ -92,33 +90,6 @@ func (r *Reader) ReadAvailable() []byte {
return r.ReadBytes(r.buf.Len())
}
func (r *Reader) ReadTlvMap(tagSize int) (m TlvMap) {
defer func() {
if r := recover(); r != nil {
// TODO: error
}
}()
m = make(map[uint16][]byte)
for {
if r.Len() < tagSize {
return m
}
var k uint16
switch tagSize {
case 1:
k = uint16(r.ReadByte())
case 2:
k = r.ReadUInt16()
case 4:
k = uint16(r.ReadInt32())
}
if k == 255 {
return m
}
m[k] = r.ReadBytes(int(r.ReadUInt16()))
}
}
func (r *Reader) Len() int {
return r.buf.Len()
}
@ -127,11 +98,6 @@ func (r *Reader) Index() int64 {
return r.buf.Size()
}
func (tlv TlvMap) Exists(key uint16) bool {
_, ok := tlv[key]
return ok
}
// --- Network reader ---
func NewNetworkReader(conn net.Conn) *NetworkReader {

View File

@ -15,6 +15,7 @@ import (
"github.com/Mrs4s/MiraiGo/binary/jce"
"github.com/Mrs4s/MiraiGo/client/internal/auth"
"github.com/Mrs4s/MiraiGo/client/internal/network"
"github.com/Mrs4s/MiraiGo/client/internal/tlv"
"github.com/Mrs4s/MiraiGo/client/pb"
"github.com/Mrs4s/MiraiGo/client/pb/cmd0x352"
"github.com/Mrs4s/MiraiGo/client/pb/cmd0x6ff"
@ -37,7 +38,10 @@ func decodeLoginResponse(c *QQClient, _ *network.IncomingPacketInfo, payload []b
reader.ReadUInt16() // sub command
t := reader.ReadByte()
reader.ReadUInt16()
m := reader.ReadTlvMap(2)
m, err := tlv.NewDecoder(2, 2).DecodeRecordMap(reader.ReadAvailable())
if err != nil {
return nil, err
}
if m.Exists(0x402) {
c.sig.Dpwd = []byte(utils.RandomString(16))
c.sig.T402 = m[0x402]
@ -45,9 +49,7 @@ func decodeLoginResponse(c *QQClient, _ *network.IncomingPacketInfo, payload []b
c.sig.G = h[:]
}
if m.Exists(0x546) {
c.debug("pow start")
c.sig.T547 = auth.CalcPow(m[0x546])
c.debug("pow end")
}
if t == 0 { // login success
// if t150, ok := m[0x150]; ok {
@ -208,7 +210,10 @@ func decodeExchangeEmpResponse(c *QQClient, _ *network.IncomingPacketInfo, paylo
cmd := reader.ReadUInt16()
t := reader.ReadByte()
reader.ReadUInt16()
m := reader.ReadTlvMap(2)
m, err := tlv.NewDecoder(2, 2).DecodeRecordMap(reader.ReadAvailable())
if err != nil {
return nil, err
}
if t != 0 {
return nil, errors.Errorf("exchange_emp failed: %v", t)
}
@ -248,7 +253,10 @@ func decodeTransEmpResponse(c *QQClient, _ *network.IncomingPacketInfo, payload
}
sig := body.ReadBytesShort()
body.ReadUInt16()
m := body.ReadTlvMap(2)
m, err := tlv.NewDecoder(2, 2).DecodeRecordMap(reader.ReadAvailable())
if err != nil {
return nil, err
}
if m.Exists(0x17) {
return &QRCodeLoginResponse{
State: QRCodeImageFetch,
@ -291,7 +299,10 @@ func decodeTransEmpResponse(c *QQClient, _ *network.IncomingPacketInfo, payload
c.highwaySession.Uin = strconv.FormatInt(c.Uin, 10)
body.ReadInt32() // sig create time
body.ReadUInt16()
m := body.ReadTlvMap(2)
m, err := tlv.NewDecoder(2, 2).DecodeRecordMap(reader.ReadAvailable())
if err != nil {
return nil, err
}
if !m.Exists(0x18) || !m.Exists(0x1e) || !m.Exists(0x19) {
return nil, errors.New("wtlogin.trans_emp sub cmd 0x12 error: tlv error")
}
@ -447,6 +458,15 @@ func decodeSummaryCardResponse(_ *QQClient, _ *network.IncomingPacketInfo, paylo
info.VipLevel = fmt.Sprintf("svip%d", v3.Level)
}
}
richSign := rsp.ReadBytes(32)
records, _ := tlv.NewDecoder(1, 1).Decode(richSign)
for _, r := range records {
if r.Tag == 3 {
info.Sign = string(r.Value)
}
}
info.LoginDays = rsp.ReadInt64(36)
services := rsp.ReadByteArrArr(46)
readService := func(buf []byte) (*profilecard.BusiComm, []byte) {

View File

@ -0,0 +1,107 @@
package tlv
import (
"encoding/binary"
"github.com/pkg/errors"
)
// Record represents a Tag-Length-Value record.
type Record struct {
Tag int
Length int
Value []byte
}
type RecordMap map[int][]byte
func (rm RecordMap) Exists(key int) bool {
_, ok := rm[key]
return ok
}
var (
ErrMessageTooShort = errors.New("tlv: message too short")
)
// Decoder is a configurable TLV decoder.
type Decoder struct {
tagSize uint8
lenSize uint8
headSize uint8
}
func NewDecoder(tagSize, lenSize uint8) *Decoder {
check := func(t string, s uint8) {
switch s {
case 1, 2, 4:
// ok
default:
panic("invalid " + t)
}
}
check("tag size", tagSize)
check("len size", lenSize)
return &Decoder{tagSize: tagSize, lenSize: lenSize, headSize: tagSize + lenSize}
}
func (d *Decoder) decodeRecord(data []byte) (r Record, err error) {
tagSize := d.tagSize
lenSize := d.lenSize
headSize := int(tagSize + lenSize)
if len(data) < headSize {
err = ErrMessageTooShort
return
}
r.Tag = d.read(tagSize, data)
r.Length = d.read(lenSize, data[tagSize:])
if len(data) < headSize+r.Length {
err = ErrMessageTooShort
return
}
r.Value = data[headSize : headSize+r.Length : headSize+r.Length]
return
}
func (d *Decoder) read(size uint8, data []byte) int {
switch size {
case 1:
return int(data[0])
case 2:
return int(binary.BigEndian.Uint16(data))
case 4:
return int(binary.BigEndian.Uint32(data))
default:
panic("invalid size")
}
}
func (d *Decoder) Decode(data []byte) ([]Record, error) {
var records []Record
for len(data) > 0 {
r, err := d.decodeRecord(data)
if err != nil {
return nil, err
}
records = append(records, r)
data = data[int(d.headSize)+r.Length:]
}
return records, nil
}
func (d *Decoder) DecodeRecordMap(data []byte) (RecordMap, error) {
records, err := d.Decode(data)
if err != nil {
return nil, err
}
rm := make(RecordMap, len(records))
for _, record := range records {
rm[record.Tag] = record.Value
}
return rm, nil
}

View File

@ -5,6 +5,7 @@ import (
"fmt"
"time"
"github.com/Mrs4s/MiraiGo/client/internal/tlv"
"github.com/Mrs4s/MiraiGo/utils"
"github.com/Mrs4s/MiraiGo/binary"
@ -25,9 +26,7 @@ func (c *QQClient) decodeT161(data []byte) {
func (c *QQClient) decodeT119(data, ek []byte) {
tea := binary.NewTeaCipher(ek)
reader := binary.NewReader(tea.Decrypt(data))
reader.ReadBytes(2)
m := reader.ReadTlvMap(2)
m, _ := tlv.NewDecoder(2, 2).DecodeRecordMap(tea.Decrypt(data)[2:])
if t130, ok := m[0x130]; ok {
c.decodeT130(t130)
}
@ -133,9 +132,7 @@ func (c *QQClient) decodeT119(data, ek []byte) {
// wtlogin.exchange_emp
func (c *QQClient) decodeT119R(data []byte) {
tea := binary.NewTeaCipher(c.deviceInfo.TgtgtKey)
reader := binary.NewReader(tea.Decrypt(data))
reader.ReadBytes(2)
m := reader.ReadTlvMap(2)
m, _ := tlv.NewDecoder(2, 2).DecodeRecordMap(tea.Decrypt(data)[2:])
if t120, ok := m[0x120]; ok {
c.sig.SKey = t120
c.sig.SKeyExpiredTime = time.Now().Unix() + 21600
@ -223,8 +220,7 @@ func readT512(data []byte) (psKeyMap map[string][]byte, pt4TokenMap map[string][
}
func readT531(data []byte) (a1, noPicSig []byte) {
reader := binary.NewReader(data)
m := reader.ReadTlvMap(2)
m, _ := tlv.NewDecoder(2, 2).DecodeRecordMap(data)
if m.Exists(0x103) && m.Exists(0x16a) && m.Exists(0x113) && m.Exists(0x10c) {
a1 = append(m[0x106], m[0x10c]...)
noPicSig = m[0x16a]

8
go.sum
View File

@ -7,6 +7,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fumiama/imgsz v0.0.2 h1:fAkC0FnIscdKOXwAxlyw3EUba5NzxZdSxGaq3Uyfxak=
github.com/fumiama/imgsz v0.0.2/go.mod h1:dR71mI3I2O5u6+PCpd47M9TZptzP+39tRBcbdIkoqM4=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/pierrec/lz4/v4 v4.1.15 h1:MO0/ucJhngq7299dKLwIMtgTfbkoSPF6AoMYDd8Q4q0=
github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@ -26,8 +31,9 @@ github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde h1:ejfdSekXMDxDLbRrJMwUk6KnSLZ2McaUCVcIKM+N6jc=
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=