diff --git a/internal/encryption/t544/encryption.go b/internal/encryption/t544/encryption.go index 75c91d2..89b09c0 100644 --- a/internal/encryption/t544/encryption.go +++ b/internal/encryption/t544/encryption.go @@ -50,4 +50,4 @@ func (c *state) init(key []byte, data []byte, counter uint64, nr uint8) { initState(c, key, data, counter) } -func sub_ad([]uint32) +func refreshState(c *state) diff --git a/internal/encryption/t544/encryption_amd64.s b/internal/encryption/t544/encryption_amd64.s index 5ad7b98..2460145 100644 --- a/internal/encryption/t544/encryption_amd64.s +++ b/internal/encryption/t544/encryption_amd64.s @@ -10,8 +10,8 @@ DATA LC0<>+12(SB)/4, $1797285236 GLOBL LC0<>(SB), NOPTR, $16 TEXT ·sub_a(SB), NOSPLIT, $0-48 - MOVQ ·a+0(FP), DI - MOVQ ·b+24(FP), CX + MOVQ a+0(FP), DI + MOVQ b+24(FP), CX MOVQ CX, DX MOVBLZX 3(CX), CX XORB CX, (DI) @@ -48,8 +48,8 @@ TEXT ·sub_a(SB), NOSPLIT, $0-48 RET TEXT ·sub_b(SB), NOSPLIT, $0-48 - MOVQ ·a+0(FP), DI - MOVQ ·b+24(FP), CX + MOVQ a+0(FP), DI + MOVQ b+24(FP), CX MOVQ CX, DX MOVBLZX 3(CX), CX XORB CX, (DI) @@ -87,8 +87,8 @@ TEXT ·sub_b(SB), NOSPLIT, $0-48 TEXT ·sub_c(SB), NOSPLIT, $0-32 - MOVQ ·a+0(FP), DI - MOVQ ·b+8(FP), SI + MOVQ a+0(FP), DI + MOVQ b+8(FP), SI MOVQ SI, AX MOVBLZX (SI), SI MOVL SI, CX @@ -236,26 +236,27 @@ TEXT ·sub_c(SB), NOSPLIT, $0-32 MOVB CX, 15(AX) RET -TEXT ·sub_d(SB), NOSPLIT, $16-32 - MOVQ ·t+0(FP), BX - MOVQ ·s+8(FP), SI - MOVOU (SI), X0 +TEXT ·sub_d(SB), NOSPLIT, $24-32 + MOVQ t+0(FP), BX + MOVQ s+8(FP), DI + MOVOU (DI), X0 MOVOU X0, in-16(SP) - MOVQ SI, DI + MOVQ $16, CX ADDQ $15, DI - MOVB $16, CX + PUSHFQ + STD lop: LEAQ -1(CX), AX XLAT - MOVBLZX in-16(SP)(AX*1), AX - STD - STOSB + LEAQ in-16(SP)(AX*1), SI + MOVSB LOOP lop + POPFQ RET TEXT ·sub_e(SB), NOSPLIT, $0-32 - MOVQ ·a+0(FP), DI - MOVQ ·n+8(FP), SI + MOVQ a+0(FP), DI + MOVQ n+8(FP), SI MOVQ $4, AX lop: MOVBQZX -4(SI)(AX*4), DX @@ -295,9 +296,9 @@ lop: JNZ lop RET -TEXT sub_ab(SB), NOSPLIT, $0-24 - MOVQ ·s+0(FP), DI - MOVQ ·w+8(FP), SI +TEXT sub_ab<>(SB), NOSPLIT, $0-24 + MOVQ s+0(FP), DI + MOVQ w+8(FP), SI MOVL SI, AX MOVL SI, CX MOVL SI, DX @@ -329,14 +330,14 @@ TEXT sub_ab(SB), NOSPLIT, $0-24 MOVBLZX (DI)(DX*1), DX SALL $16, DX ORL DX, AX - MOVQ AX, ·retval+16(FP) + MOVQ AX, retval+16(FP) RET TEXT ·sub_f(SB), NOSPLIT, $24-68 - MOVQ ·k+0(FP), DI - MOVQ ·r+8(FP), SI - MOVQ ·s+16(FP), DX - MOVQ $·w+24(FP), CX + MOVQ k+0(FP), DI + MOVQ r+8(FP), SI + MOVQ s+16(FP), DX + MOVQ $w+24(FP), CX MOVQ CX, R10 MOVQ SI, R9 MOVQ DX, R8 @@ -367,7 +368,7 @@ inner: ROLL $8, AX MOVQ R8, 0(SP) MOVL AX, 8(SP) - CALL sub_ab(SB) + CALL sub_ab<>(SB) MOVQ 16(SP), AX LEAL -1(BX), DX SARL $2, DX @@ -378,10 +379,10 @@ end: RET TEXT ·sub_aa(SB), NOSPLIT, $0-56 - MOVQ ·i+0(FP), DI - MOVQ ·t+8(FP), SI - MOVQ ·b+16(FP), DX - MOVQ ·m+24(FP), CX + MOVQ i+0(FP), DI + MOVQ t+8(FP), SI + MOVQ b+16(FP), DX + MOVQ m+24(FP), CX MOVL DI, AX MOVLQSX DI, DI MOVQ SI, R8 @@ -407,13 +408,13 @@ TEXT ·sub_aa(SB), NOSPLIT, $0-56 MOVBLZX (AX)(DI*1), AX SALL $4, AX ORB 256(SI)(DX*1), AX - MOVQ AX, ·retval+48(FP) + MOVQ AX, retval+48(FP) RET // func transformInner(x *[0x15]byte, tab *[32][16]byte) TEXT ·transformInner(SB), NOSPLIT, $0-16 - MOVQ ·x+0(FP), DI - MOVQ ·tab+8(FP), SI + MOVQ x+0(FP), DI + MOVQ tab+8(FP), SI MOVQ DI, AX MOVL $1, CX MOVQ SI, DI @@ -446,10 +447,10 @@ lop: RET TEXT ·initState(SB), NOSPLIT, $0-64 - MOVQ ·c+0(FP), DI - MOVQ ·key+8(FP), SI - MOVQ ·data+32(FP), R8 - MOVQ ·counter+56(FP), AX + MOVQ c+0(FP), DI + MOVQ key+8(FP), SI + MOVQ data+32(FP), R8 + MOVQ counter+56(FP), AX MOVOA LC0<>(SB), X0 MOVUPS X0, (DI) MOVOU (SI), X1 @@ -467,8 +468,8 @@ TEXT ·initState(SB), NOSPLIT, $0-64 MOVUPS X6,112(DI) RET -TEXT ·sub_ad(SB), NOSPLIT, $8-24 - MOVQ ·a+0(FP), DI +TEXT sub_ad<>(SB), NOSPLIT, $8-8 + MOVQ a+0(FP), DI MOVQ DI, AX MOVL 40(DI), R10 MOVL 12(DI), R12 @@ -610,11 +611,42 @@ TEXT ·sub_ad(SB), NOSPLIT, $8-24 MOVUPS X0, 32(AX) RET +TEXT ·refreshState(SB), NOSPLIT, $16-8 + MOVQ i+0(FP), BX + MOVB 128(BX), CX + JE ad + SHRQ $1, CX +fr: + MOVQ BX, 0(SP) + MOVQ CX, c-8(SP) + CALL sub_ad<>(SB) + MOVQ c-8(SP), CX + MOVQ i+0(FP), BX + LOOP fr +ad: + MOVOU (BX), X0 + MOVOU 64(BX), X1 + MOVOU 80(BX), X2 + MOVOU 96(BX), X3 + PADDD X1, X0 + MOVOU 48(BX), X4 + MOVUPS X0, (BX) + MOVOU 16(BX), X0 + PADDD X2, X0 + MOVUPS X0, 16(BX) + MOVOU 32(BX), X0 + PADDD X3, X0 + MOVUPS X0, 32(BX) + MOVOU 112(BX), X0 + PADDD X4, X0 + MOVUPS X0, 48(BX) + RET + // func tencentCrc32(tab *crc32.Table, b []byte) uint32 TEXT ·tencentCrc32(SB), NOSPLIT, $0-40 - MOVQ ·tab+0(FP), DI - MOVQ ·bptr+8(FP), SI - MOVQ ·bngas+16(FP), DX + MOVQ tab+0(FP), DI + MOVQ bptr+8(FP), SI + MOVQ bngas+16(FP), DX TESTQ DX, DX JE quickend ADDQ SI, DX @@ -629,7 +661,7 @@ lop: CMPQ SI, DX JNE lop NOTL AX - MOVQ AX, ·bngas+32(FP) + MOVQ AX, bngas+32(FP) RET quickend: XORL AX, AX diff --git a/internal/encryption/t544/encryption_generic.go b/internal/encryption/t544/encryption_generic.go index e74c351..cd3b4f0 100644 --- a/internal/encryption/t544/encryption_generic.go +++ b/internal/encryption/t544/encryption_generic.go @@ -91,12 +91,7 @@ func (c *state) encrypt(data []byte) { dataLen := uint32(len(data)) for dataLen > 0 { if c.p == 0 { - for i := uint8(0); i < c.nr; i += 2 { - sub_ad(c.state[:]) - } - for i := 0; i < 16; i++ { - c.state[i] += c.orgstate[i] - } + refreshState(c) } var sb [16 * 4]byte for i, v := range c.state { diff --git a/internal/encryption/t544/t544.go b/internal/encryption/t544/t544.go index 321fcb1..34ab5b7 100644 --- a/internal/encryption/t544/t544.go +++ b/internal/encryption/t544/t544.go @@ -7,7 +7,6 @@ import ( "crypto/rc4" "encoding/binary" "math/rand" - "unsafe" "github.com/Mrs4s/go-cqhttp/internal/encryption" ) @@ -31,8 +30,10 @@ func init() { // sign t544 algorithm // special thanks to the anonymous contributor who provided the algorithm func sign(curr int64, input []byte) []byte { + var crcData [0x15]byte curr %= 1000000 - input = append(input, []byte{byte(curr >> 24), byte(curr >> 16), byte(curr >> 8), byte(curr)}...) + binary.BigEndian.PutUint32(crcData[:4], uint32(curr)) + input = append(input, crcData[:4]...) var kt [4 + 32 + 4]byte r := rand.New(rand.NewSource(curr)) for i := 0; i < 2; i++ { @@ -51,8 +52,7 @@ func sign(curr int64, input []byte) []byte { k3calc[6], k3calc[7] = 0, 0 rc4Cipher, _ := rc4.NewCipher(key3) rc4Cipher.XORKeyStream(key3, key3) - var crcData [0x15]byte - copy(crcData[4:4+8], (*[8]byte)(unsafe.Pointer(&magic))[:]) + binary.LittleEndian.PutUint64(crcData[4:4+8], magic) tencentEncryptionA(input, kt[4:4+32], crcData[4:4+8]) result := md5.Sum(input) crcData[2] = 1 @@ -61,7 +61,7 @@ func sign(curr int64, input []byte) []byte { binary.BigEndian.PutUint32(crcData[9:13], uint32(curr)) copy(crcData[13:], result[:8]) calcCrc := tencentCrc32(&crc32Table, crcData[2:]) - copy(kt[4+32:4+32+4], (*[4]byte)(unsafe.Pointer(&calcCrc))[:]) + binary.LittleEndian.PutUint32(kt[4+32:4+32+4], calcCrc) crcData[0] = kt[4+32] crcData[1] = kt[4+32+3] nonce := uint32(r.Int() ^ r.Int() ^ r.Int()) diff --git a/internal/encryption/t544/t544_test.go b/internal/encryption/t544/t544_test.go new file mode 100755 index 0000000..1f0f184 --- /dev/null +++ b/internal/encryption/t544/t544_test.go @@ -0,0 +1,22 @@ +package t544 + +import ( + "crypto/rand" + "encoding/hex" + "testing" +) + +func TestT544(t *testing.T) { + r := hex.EncodeToString(sign(0, []byte{})) + if r != "0c05d28b405bce1595c70ffa694ff163d4b600f229482e07de32c8000000003525382c00000000" { + t.Fatal(r) + } +} + +func TestCrash(t *testing.T) { + brand := make([]byte, 4096) + for i := 1; i <= 1024; i++ { + rand.Reader.Read(brand) + sign(123, brand) + } +}