mirror of
https://github.com/ScuroNeko/mtg.git
synced 2026-09-01 00:14:02 +03:00
FILE / ScuroNeko/mtg
mtglib/internal/obfuscation/handshake_frame.go
Исходный файл и его история в репозитории.
112 lines
2.6 KiB
Go
112 lines
2.6 KiB
Go
package obfuscation
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/binary"
|
|
"slices"
|
|
)
|
|
|
|
// https://core.telegram.org/mtproto/mtproto-transports#transport-obfuscation
|
|
const (
|
|
// default DC is nothing is selected
|
|
defaultDC = 2
|
|
|
|
// the length of the handshake frame. Always 64 bytes
|
|
hfLen = 64
|
|
|
|
hfLenKey = 32
|
|
hfLenIV = 16
|
|
hfLenConnectionType = 4
|
|
|
|
// A structure of obfuscated handshake frame is following:
|
|
//
|
|
// [frameOffsetFirst:frameOffsetKey:frameOffsetIV:frameOffsetMagic:frameOffsetDC:frameOffsetEnd].
|
|
//
|
|
// - 8 bytes of noise
|
|
// - 32 bytes of AES Key
|
|
// - 16 bytes of AES IV
|
|
// - 4 bytes of 'connection type' - this has some setting like a connection type
|
|
// - 2 bytes of 'DC'. DC is little endian int16
|
|
// - 2 bytes of noise
|
|
hfOffsetKey = 8
|
|
hfOffsetIV = hfOffsetKey + hfLenKey
|
|
hfOffsetConnectionType = hfOffsetIV + hfLenIV
|
|
hfOffsetDC = hfOffsetConnectionType + hfLenConnectionType
|
|
)
|
|
|
|
// Connection-Type: Secure. We support only fake tls.
|
|
var hfConnectionType = [hfLenConnectionType]byte{0xdd, 0xdd, 0xdd, 0xdd}
|
|
|
|
type handshakeFrame struct {
|
|
data [hfLen]byte
|
|
}
|
|
|
|
func (h *handshakeFrame) key() []byte {
|
|
return h.data[hfOffsetKey : hfOffsetKey+hfLenKey]
|
|
}
|
|
|
|
func (h *handshakeFrame) iv() []byte {
|
|
return h.data[hfOffsetIV : hfOffsetIV+hfLenIV]
|
|
}
|
|
|
|
func (h *handshakeFrame) connectionType() []byte {
|
|
return h.data[hfOffsetConnectionType : hfOffsetConnectionType+hfLenConnectionType]
|
|
}
|
|
|
|
func (h *handshakeFrame) dcSlice() []byte {
|
|
return h.data[hfOffsetDC : hfOffsetDC+2]
|
|
}
|
|
|
|
func (h *handshakeFrame) dc() int {
|
|
idx := int16(binary.LittleEndian.Uint16(h.dcSlice()))
|
|
|
|
switch {
|
|
case idx > 0:
|
|
return int(idx)
|
|
case idx < 0:
|
|
return -int(idx)
|
|
}
|
|
|
|
return defaultDC
|
|
}
|
|
|
|
func (h *handshakeFrame) revert() {
|
|
slices.Reverse(h.data[hfOffsetKey:hfOffsetConnectionType])
|
|
}
|
|
|
|
func generateHandshake(dc int) handshakeFrame {
|
|
frame := handshakeFrame{}
|
|
|
|
for {
|
|
if _, err := rand.Read(frame.data[:]); err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
// https://github.com/tdlib/td/blob/master/td/mtproto/TcpTransport.cpp#L157-L158.
|
|
if frame.data[0] == 0xef { // abridged header
|
|
// https://core.telegram.org/mtproto/mtproto-transports#abridged
|
|
continue
|
|
}
|
|
|
|
switch binary.LittleEndian.Uint32(frame.data[:4]) {
|
|
case 0x44414548, // HEAD
|
|
0x54534f50, // POST
|
|
0x20544547, // GET
|
|
0x4954504f, // OPTI
|
|
0x02010316, // ????
|
|
0xdddddddd, // PaddedIntermediate header
|
|
0xeeeeeeee: // Intermediate header
|
|
continue
|
|
}
|
|
|
|
if frame.data[4]|frame.data[5]|frame.data[6]|frame.data[7] == 0 {
|
|
continue
|
|
}
|
|
|
|
copy(frame.connectionType(), hfConnectionType[:])
|
|
binary.LittleEndian.PutUint16(frame.dcSlice(), uint16(dc))
|
|
|
|
return frame
|
|
}
|
|
}
|