mirror of
https://github.com/Mrs4s/MiraiGo.git
synced 2025-05-04 11:07:40 +08:00
client: implement query personal sign
This commit is contained in:
parent
727686e453
commit
f56bcbe326
@ -17,8 +17,6 @@ type NetworkReader struct {
|
|||||||
conn net.Conn
|
conn net.Conn
|
||||||
}
|
}
|
||||||
|
|
||||||
type TlvMap map[uint16][]byte
|
|
||||||
|
|
||||||
// --- ByteStream reader ---
|
// --- ByteStream reader ---
|
||||||
|
|
||||||
func NewReader(data []byte) *Reader {
|
func NewReader(data []byte) *Reader {
|
||||||
@ -92,33 +90,6 @@ func (r *Reader) ReadAvailable() []byte {
|
|||||||
return r.ReadBytes(r.buf.Len())
|
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 {
|
func (r *Reader) Len() int {
|
||||||
return r.buf.Len()
|
return r.buf.Len()
|
||||||
}
|
}
|
||||||
@ -127,11 +98,6 @@ func (r *Reader) Index() int64 {
|
|||||||
return r.buf.Size()
|
return r.buf.Size()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tlv TlvMap) Exists(key uint16) bool {
|
|
||||||
_, ok := tlv[key]
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- Network reader ---
|
// --- Network reader ---
|
||||||
|
|
||||||
func NewNetworkReader(conn net.Conn) *NetworkReader {
|
func NewNetworkReader(conn net.Conn) *NetworkReader {
|
||||||
|
@ -15,6 +15,7 @@ import (
|
|||||||
"github.com/Mrs4s/MiraiGo/binary/jce"
|
"github.com/Mrs4s/MiraiGo/binary/jce"
|
||||||
"github.com/Mrs4s/MiraiGo/client/internal/auth"
|
"github.com/Mrs4s/MiraiGo/client/internal/auth"
|
||||||
"github.com/Mrs4s/MiraiGo/client/internal/network"
|
"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"
|
||||||
"github.com/Mrs4s/MiraiGo/client/pb/cmd0x352"
|
"github.com/Mrs4s/MiraiGo/client/pb/cmd0x352"
|
||||||
"github.com/Mrs4s/MiraiGo/client/pb/cmd0x6ff"
|
"github.com/Mrs4s/MiraiGo/client/pb/cmd0x6ff"
|
||||||
@ -37,7 +38,10 @@ func decodeLoginResponse(c *QQClient, _ *network.IncomingPacketInfo, payload []b
|
|||||||
reader.ReadUInt16() // sub command
|
reader.ReadUInt16() // sub command
|
||||||
t := reader.ReadByte()
|
t := reader.ReadByte()
|
||||||
reader.ReadUInt16()
|
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) {
|
if m.Exists(0x402) {
|
||||||
c.sig.Dpwd = []byte(utils.RandomString(16))
|
c.sig.Dpwd = []byte(utils.RandomString(16))
|
||||||
c.sig.T402 = m[0x402]
|
c.sig.T402 = m[0x402]
|
||||||
@ -45,9 +49,7 @@ func decodeLoginResponse(c *QQClient, _ *network.IncomingPacketInfo, payload []b
|
|||||||
c.sig.G = h[:]
|
c.sig.G = h[:]
|
||||||
}
|
}
|
||||||
if m.Exists(0x546) {
|
if m.Exists(0x546) {
|
||||||
c.debug("pow start")
|
|
||||||
c.sig.T547 = auth.CalcPow(m[0x546])
|
c.sig.T547 = auth.CalcPow(m[0x546])
|
||||||
c.debug("pow end")
|
|
||||||
}
|
}
|
||||||
if t == 0 { // login success
|
if t == 0 { // login success
|
||||||
// if t150, ok := m[0x150]; ok {
|
// if t150, ok := m[0x150]; ok {
|
||||||
@ -208,7 +210,10 @@ func decodeExchangeEmpResponse(c *QQClient, _ *network.IncomingPacketInfo, paylo
|
|||||||
cmd := reader.ReadUInt16()
|
cmd := reader.ReadUInt16()
|
||||||
t := reader.ReadByte()
|
t := reader.ReadByte()
|
||||||
reader.ReadUInt16()
|
reader.ReadUInt16()
|
||||||
m := reader.ReadTlvMap(2)
|
m, err := tlv.NewDecoder(2, 2).DecodeRecordMap(reader.ReadAvailable())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
if t != 0 {
|
if t != 0 {
|
||||||
return nil, errors.Errorf("exchange_emp failed: %v", t)
|
return nil, errors.Errorf("exchange_emp failed: %v", t)
|
||||||
}
|
}
|
||||||
@ -248,7 +253,10 @@ func decodeTransEmpResponse(c *QQClient, _ *network.IncomingPacketInfo, payload
|
|||||||
}
|
}
|
||||||
sig := body.ReadBytesShort()
|
sig := body.ReadBytesShort()
|
||||||
body.ReadUInt16()
|
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) {
|
if m.Exists(0x17) {
|
||||||
return &QRCodeLoginResponse{
|
return &QRCodeLoginResponse{
|
||||||
State: QRCodeImageFetch,
|
State: QRCodeImageFetch,
|
||||||
@ -291,7 +299,10 @@ func decodeTransEmpResponse(c *QQClient, _ *network.IncomingPacketInfo, payload
|
|||||||
c.highwaySession.Uin = strconv.FormatInt(c.Uin, 10)
|
c.highwaySession.Uin = strconv.FormatInt(c.Uin, 10)
|
||||||
body.ReadInt32() // sig create time
|
body.ReadInt32() // sig create time
|
||||||
body.ReadUInt16()
|
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) {
|
if !m.Exists(0x18) || !m.Exists(0x1e) || !m.Exists(0x19) {
|
||||||
return nil, errors.New("wtlogin.trans_emp sub cmd 0x12 error: tlv error")
|
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)
|
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)
|
info.LoginDays = rsp.ReadInt64(36)
|
||||||
services := rsp.ReadByteArrArr(46)
|
services := rsp.ReadByteArrArr(46)
|
||||||
readService := func(buf []byte) (*profilecard.BusiComm, []byte) {
|
readService := func(buf []byte) (*profilecard.BusiComm, []byte) {
|
||||||
|
107
client/internal/tlv/decoder.go
Normal file
107
client/internal/tlv/decoder.go
Normal 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
|
||||||
|
}
|
@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/Mrs4s/MiraiGo/client/internal/tlv"
|
||||||
"github.com/Mrs4s/MiraiGo/utils"
|
"github.com/Mrs4s/MiraiGo/utils"
|
||||||
|
|
||||||
"github.com/Mrs4s/MiraiGo/binary"
|
"github.com/Mrs4s/MiraiGo/binary"
|
||||||
@ -25,9 +26,7 @@ func (c *QQClient) decodeT161(data []byte) {
|
|||||||
|
|
||||||
func (c *QQClient) decodeT119(data, ek []byte) {
|
func (c *QQClient) decodeT119(data, ek []byte) {
|
||||||
tea := binary.NewTeaCipher(ek)
|
tea := binary.NewTeaCipher(ek)
|
||||||
reader := binary.NewReader(tea.Decrypt(data))
|
m, _ := tlv.NewDecoder(2, 2).DecodeRecordMap(tea.Decrypt(data)[2:])
|
||||||
reader.ReadBytes(2)
|
|
||||||
m := reader.ReadTlvMap(2)
|
|
||||||
if t130, ok := m[0x130]; ok {
|
if t130, ok := m[0x130]; ok {
|
||||||
c.decodeT130(t130)
|
c.decodeT130(t130)
|
||||||
}
|
}
|
||||||
@ -133,9 +132,7 @@ func (c *QQClient) decodeT119(data, ek []byte) {
|
|||||||
// wtlogin.exchange_emp
|
// wtlogin.exchange_emp
|
||||||
func (c *QQClient) decodeT119R(data []byte) {
|
func (c *QQClient) decodeT119R(data []byte) {
|
||||||
tea := binary.NewTeaCipher(c.deviceInfo.TgtgtKey)
|
tea := binary.NewTeaCipher(c.deviceInfo.TgtgtKey)
|
||||||
reader := binary.NewReader(tea.Decrypt(data))
|
m, _ := tlv.NewDecoder(2, 2).DecodeRecordMap(tea.Decrypt(data)[2:])
|
||||||
reader.ReadBytes(2)
|
|
||||||
m := reader.ReadTlvMap(2)
|
|
||||||
if t120, ok := m[0x120]; ok {
|
if t120, ok := m[0x120]; ok {
|
||||||
c.sig.SKey = t120
|
c.sig.SKey = t120
|
||||||
c.sig.SKeyExpiredTime = time.Now().Unix() + 21600
|
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) {
|
func readT531(data []byte) (a1, noPicSig []byte) {
|
||||||
reader := binary.NewReader(data)
|
m, _ := tlv.NewDecoder(2, 2).DecodeRecordMap(data)
|
||||||
m := reader.ReadTlvMap(2)
|
|
||||||
if m.Exists(0x103) && m.Exists(0x16a) && m.Exists(0x113) && m.Exists(0x10c) {
|
if m.Exists(0x103) && m.Exists(0x16a) && m.Exists(0x113) && m.Exists(0x10c) {
|
||||||
a1 = append(m[0x106], m[0x10c]...)
|
a1 = append(m[0x106], m[0x10c]...)
|
||||||
noPicSig = m[0x16a]
|
noPicSig = m[0x16a]
|
||||||
|
8
go.sum
8
go.sum
@ -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/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 h1:fAkC0FnIscdKOXwAxlyw3EUba5NzxZdSxGaq3Uyfxak=
|
||||||
github.com/fumiama/imgsz v0.0.2/go.mod h1:dR71mI3I2O5u6+PCpd47M9TZptzP+39tRBcbdIkoqM4=
|
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 h1:MO0/ucJhngq7299dKLwIMtgTfbkoSPF6AoMYDd8Q4q0=
|
||||||
github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
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=
|
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 h1:ejfdSekXMDxDLbRrJMwUk6KnSLZ2McaUCVcIKM+N6jc=
|
||||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
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 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.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 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
Loading…
x
Reference in New Issue
Block a user