Add obfuscated2 server handshake

This commit is contained in:
9seconds
2021-03-23 10:27:22 +03:00
parent f7c33ee333
commit 66c45dc83b
6 changed files with 123 additions and 99 deletions
+6 -52
View File
@@ -2,66 +2,20 @@ package mtglib
import ( import (
"context" "context"
"fmt"
"net" "net"
"time" "time"
) )
type connStandard struct { type connTelegramTraffic struct {
conn net.Conn net.Conn
idleTimeout time.Duration
}
func (c connStandard) Read(b []byte) (int, error) {
if err := c.conn.SetReadDeadline(time.Now().Add(c.idleTimeout)); err != nil {
return 0, fmt.Errorf("cannot set read deadline: %w", err)
}
return c.conn.Read(b)
}
func (c connStandard) Write(b []byte) (int, error) {
if err := c.conn.SetWriteDeadline(time.Now().Add(c.idleTimeout)); err != nil {
return 0, fmt.Errorf("cannot set write deadline: %w", err)
}
return c.conn.Write(b)
}
func (c connStandard) Close() error {
return c.conn.Close()
}
func (c connStandard) LocalAddr() net.Addr {
return c.conn.LocalAddr()
}
func (c connStandard) RemoteAddr() net.Addr {
return c.conn.RemoteAddr()
}
func (c connStandard) SetDeadline(t time.Time) error {
return c.conn.SetDeadline(t)
}
func (c connStandard) SetReadDeadline(t time.Time) error {
return c.conn.SetReadDeadline(t)
}
func (c connStandard) SetWriteDeadline(t time.Time) error {
return c.conn.SetWriteDeadline(t)
}
type connEventTraffic struct {
connStandard
connID string connID string
stream EventStream stream EventStream
ctx context.Context ctx context.Context
} }
func (c connEventTraffic) Read(b []byte) (int, error) { func (c connTelegramTraffic) Read(b []byte) (int, error) {
n, err := c.connStandard.Read(b) n, err := c.Conn.Read(b)
if n > 0 { if n > 0 {
c.stream.Send(c.ctx, EventTraffic{ c.stream.Send(c.ctx, EventTraffic{
@@ -75,8 +29,8 @@ func (c connEventTraffic) Read(b []byte) (int, error) {
return n, err return n, err
} }
func (c connEventTraffic) Write(b []byte) (int, error) { func (c connTelegramTraffic) Write(b []byte) (int, error) {
n, err := c.connStandard.Write(b) n, err := c.Conn.Write(b)
if n > 0 { if n > 0 {
c.stream.Send(c.ctx, EventTraffic{ c.stream.Send(c.ctx, EventTraffic{
@@ -8,6 +8,33 @@ import (
"io" "io"
) )
type clientHandhakeFrame struct {
handshakeFrame
}
func (c *clientHandhakeFrame) decryptor(secret []byte) cipher.Stream {
hasher := acquireSha256Hasher()
defer releaseSha256Hasher(hasher)
hasher.Write(c.key()) // nolint: errcheck
hasher.Write(secret) // nolint: errcheck
return makeAesCtr(hasher.Sum(nil), c.iv())
}
func (c *clientHandhakeFrame) encryptor(secret []byte) cipher.Stream {
arr := clientHandhakeFrame{}
invertByteSlices(arr.data[:], c.data[:])
hasher := acquireSha256Hasher()
defer releaseSha256Hasher(hasher)
hasher.Write(arr.key()) // nolint: errcheck
hasher.Write(secret) // nolint: errcheck
return makeAesCtr(hasher.Sum(nil), arr.iv())
}
func ClientHandshake(secret []byte, reader io.Reader) (int, cipher.Stream, cipher.Stream, error) { func ClientHandshake(secret []byte, reader io.Reader) (int, cipher.Stream, cipher.Stream, error) {
handshake := clientHandhakeFrame{} handshake := clientHandhakeFrame{}
@@ -1,30 +0,0 @@
package obfuscated2
import "crypto/cipher"
type clientHandhakeFrame struct {
handshakeFrame
}
func (c *clientHandhakeFrame) decryptor(secret []byte) cipher.Stream {
hasher := acquireSha256Hasher()
defer releaseSha256Hasher(hasher)
hasher.Write(c.key()) // nolint: errcheck
hasher.Write(secret) // nolint: errcheck
return makeAesCtr(hasher.Sum(nil), c.iv())
}
func (c *clientHandhakeFrame) encryptor(secret []byte) cipher.Stream {
arr := clientHandhakeFrame{}
invertByteSlices(arr.data[:], c.data[:])
hasher := acquireSha256Hasher()
defer releaseSha256Hasher(hasher)
hasher.Write(arr.key()) // nolint: errcheck
hasher.Write(secret) // nolint: errcheck
return makeAesCtr(hasher.Sum(nil), arr.iv())
}
+3 -3
View File
@@ -14,7 +14,7 @@ type Conn struct {
writeBuf []byte writeBuf []byte
} }
func (c Conn) Read(p []byte) (int, error) { func (c *Conn) Read(p []byte) (int, error) {
n, err := c.Conn.Read(p) n, err := c.Conn.Read(p)
if err != nil { if err != nil {
return n, err // nolint: wrapcheck return n, err // nolint: wrapcheck
@@ -25,9 +25,9 @@ func (c Conn) Read(p []byte) (int, error) {
return n, nil return n, nil
} }
func (c Conn) Write(p []byte) (int, error) { func (c *Conn) Write(p []byte) (int, error) {
c.writeBuf = append(c.writeBuf[:0], p...) c.writeBuf = append(c.writeBuf[:0], p...)
c.Encryptor.XORKeyStream(c.writeBuf, c.writeBuf) c.Encryptor.XORKeyStream(c.writeBuf, p)
return c.Conn.Write(c.writeBuf) return c.Conn.Write(c.writeBuf)
} }
@@ -0,0 +1,68 @@
package obfuscated2
import (
"crypto/cipher"
"crypto/rand"
"encoding/binary"
"fmt"
"net"
)
type serverHandshakeFrame struct {
handshakeFrame
}
func (s *serverHandshakeFrame) decryptor() cipher.Stream {
return makeAesCtr(s.key(), s.iv())
}
func (s *serverHandshakeFrame) encryptor() cipher.Stream {
arr := serverHandshakeFrame{}
invertByteSlices(arr.data[:], s.data[:])
return makeAesCtr(arr.key(), arr.iv())
}
func ServerHandshake(conn net.Conn) (cipher.Stream, cipher.Stream, error) {
handshake := generateServerHanshakeFrame()
copyHandshake := handshake
encryptor := handshake.encryptor()
decryptor := handshake.decryptor()
encryptor.XORKeyStream(handshake.data[:], handshake.data[:])
copy(handshake.key(), copyHandshake.key())
copy(handshake.iv(), copyHandshake.iv())
if _, err := conn.Write(handshake.data[:]); err != nil {
return nil, nil, fmt.Errorf("cannot send a handshake frame to telegram: %w", err)
}
return encryptor, decryptor, nil
}
func generateServerHanshakeFrame() serverHandshakeFrame {
frame := serverHandshakeFrame{}
for {
if _, err := rand.Read(frame.data[:]); err != nil {
panic(err)
}
if frame.data[0] == 0xef {
continue
}
switch binary.LittleEndian.Uint32(frame.data[:4]) {
case 0x44414548, 0x54534f50, 0x20544547, 0x4954504f, 0xeeeeeeee:
continue
}
if (frame.data[4] | frame.data[5] | frame.data[6] | frame.data[7]) == 0 {
continue
}
copy(frame.connectionType(), handshakeConnectionType)
return frame
}
}
+19 -14
View File
@@ -111,13 +111,10 @@ func (p *Proxy) doObfuscated2Handshake(ctx *streamContext) error {
ctx.dc = dc ctx.dc = dc
ctx.logger = ctx.logger.BindInt("dc", dc) ctx.logger = ctx.logger.BindInt("dc", dc)
ctx.clientConn = connStandard{ ctx.clientConn = &obfuscated2.Conn{
conn: obfuscated2.Conn{ Conn: ctx.clientConn,
Conn: ctx.clientConn, Encryptor: encryptor,
Encryptor: encryptor, Decryptor: decryptor,
Decryptor: decryptor,
},
idleTimeout: p.idleTimeout,
} }
return nil return nil
@@ -129,14 +126,22 @@ func (p *Proxy) doTelegramCall(ctx *streamContext) error {
return fmt.Errorf("cannot dial to Telegram: %w", err) return fmt.Errorf("cannot dial to Telegram: %w", err)
} }
ctx.telegramConn = connEventTraffic{ encryptor, decryptor, err := obfuscated2.ServerHandshake(conn)
connStandard: connStandard{ if err != nil {
conn: conn, conn.Close()
idleTimeout: p.idleTimeout,
return fmt.Errorf("cannot perform obfuscated2 handshake: %w", err)
}
ctx.telegramConn = &obfuscated2.Conn{
Conn: connTelegramTraffic{
Conn: conn,
connID: ctx.connID,
stream: p.eventStream,
ctx: ctx,
}, },
connID: ctx.connID, Encryptor: encryptor,
stream: p.eventStream, Decryptor: decryptor,
ctx: ctx,
} }
p.eventStream.Send(ctx, EventConnectedToDC{ p.eventStream.Send(ctx, EventConnectedToDC{