mirror of
https://github.com/ScuroNeko/mtg.git
synced 2026-08-31 21:34:02 +03:00
Add obfuscated2 server handshake
This commit is contained in:
+6
-52
@@ -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())
|
|
||||||
}
|
|
||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
+14
-9
@@ -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,
|
connID: ctx.connID,
|
||||||
stream: p.eventStream,
|
stream: p.eventStream,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
|
},
|
||||||
|
Encryptor: encryptor,
|
||||||
|
Decryptor: decryptor,
|
||||||
}
|
}
|
||||||
|
|
||||||
p.eventStream.Send(ctx, EventConnectedToDC{
|
p.eventStream.Send(ctx, EventConnectedToDC{
|
||||||
|
|||||||
Reference in New Issue
Block a user