| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- 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
- }
- }
|