-
Notifications
You must be signed in to change notification settings - Fork 18
/
oicq.go
117 lines (105 loc) · 3.01 KB
/
oicq.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package client
import (
"fmt"
"github.com/LagrangeDev/LagrangeGo/client/auth"
"github.com/LagrangeDev/LagrangeGo/client/internal/oicq"
"github.com/LagrangeDev/LagrangeGo/client/packets/pb"
"github.com/LagrangeDev/LagrangeGo/utils"
"github.com/LagrangeDev/LagrangeGo/utils/binary"
"github.com/LagrangeDev/LagrangeGo/utils/crypto"
"github.com/RomiChan/protobuf/proto"
tea "github.com/fumiama/gofastTEA"
)
func (c *QQClient) buildCode2dPacket(uin uint32, cmdID int, body []byte) []byte {
return c.buildLoginPacket(
uin,
"wtlogin.trans_emp",
binary.NewBuilder(nil).
WriteU8(0).
WriteU16(uint16(len(body))+53).
WriteU32(uint32(c.version().AppID)).
WriteU32(0x72).
WriteBytes(make([]byte, 3)).
WriteU32(uint32(utils.TimeStamp())).
WriteU8(2).
WriteU16(uint16(len(body)+49)).
WriteU16(uint16(cmdID)).
WriteBytes(make([]byte, 21)).
WriteU8(3).
WriteU32(50).
WriteBytes(make([]byte, 14)).
WriteU32(uint32(c.version().AppID)).
WriteBytes(body).
ToBytes(),
)
}
func (c *QQClient) buildLoginPacket(uin uint32, cmd string, body []byte) []byte {
var _cmd uint16
if cmd == "wtlogin.login" {
_cmd = 2064
} else {
_cmd = 2066
}
return c.oicq.Marshal(&oicq.Message{
Uin: uin,
Command: _cmd,
EncryptionMethod: oicq.EM_ECDH,
Body: body,
})
}
func (c *QQClient) decodeLoginResponse(buf []byte, sig *auth.SigInfo) error {
reader := binary.NewReader(buf)
reader.SkipBytes(2)
typ := reader.ReadU8()
tlv := reader.ReadTlv()
var title, content string
if typ == 0 {
reader = binary.NewReader(tea.NewTeaCipher(sig.Tgtgt).Decrypt(tlv[0x119]))
tlv = reader.ReadTlv()
if tgt, ok := tlv[0x10A]; ok {
sig.Tgt = tgt
}
if d2, ok := tlv[0x143]; ok {
sig.D2 = d2
}
if d2Key, ok := tlv[0x305]; ok {
sig.D2Key = d2Key
}
if tlv11a, ok := tlv[0x11A]; ok {
c.debug("tlv11a data: %x", tlv11a)
tlvReader := binary.NewReader(tlv11a)
tlvReader.ReadU16()
sig.Age = tlvReader.ReadU8()
sig.Gender = tlvReader.ReadU8()
sig.Nickname = tlvReader.ReadStringWithLength("u8", false)
}
sig.Tgtgt = crypto.MD5Digest(sig.D2Key)
sig.TempPwd = tlv[0x106]
var resp pb.Tlv543
err := proto.Unmarshal(tlv[0x543], &resp)
if err != nil {
err = fmt.Errorf("parsing login response error: %s", err)
c.errorln(err)
return err
}
sig.Uid = resp.Layer1.Layer2.Uid
c.debugln("SigInfo got")
return nil
} else if errData, ok := tlv[0x146]; ok {
errBuf := binary.NewReader(errData)
errBuf.SkipBytes(4)
title = errBuf.ReadString(int(errBuf.ReadU16()))
content = errBuf.ReadString(int(errBuf.ReadU16()))
} else if errData, ok := tlv[0x149]; ok {
errBuf := binary.NewReader(errData)
errBuf.SkipBytes(2)
title = errBuf.ReadString(int(errBuf.ReadU16()))
content = errBuf.ReadString(int(errBuf.ReadU16()))
} else {
title = "未知错误"
content = "无法解析错误原因,请将完整日志提交给开发者"
}
err := fmt.Errorf("login fail on oicq (0x%02x): [%s]>[%s]", typ, title, content)
c.errorln(err)
return err
}