mirror of
https://github.com/ScuroNeko/mtg.git
synced 2026-08-31 23:14:02 +03:00
Reworked base
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
package newobfuscated2
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/juju/errors"
|
||||
|
||||
"github.com/9seconds/mtg/newantireplay"
|
||||
"github.com/9seconds/mtg/newconfig"
|
||||
"github.com/9seconds/mtg/newprotocol"
|
||||
"github.com/9seconds/mtg/newwrappers"
|
||||
)
|
||||
|
||||
const clientProtocolHandshakeTimeout = 10 * time.Second
|
||||
|
||||
type ClientProtocol struct {
|
||||
newprotocol.BaseProtocol
|
||||
}
|
||||
|
||||
func (c *ClientProtocol) Handshake(socket newwrappers.StreamReadWriteCloser) (newwrappers.StreamReadWriteCloser, error) {
|
||||
fm, err := c.ReadFrame(socket)
|
||||
if err != nil {
|
||||
return nil, errors.Annotate(err, "Cannot make client handshake")
|
||||
}
|
||||
|
||||
decHasher := sha256.New()
|
||||
decHasher.Write(fm.key()) // nolint: errcheck
|
||||
decHasher.Write(newconfig.C.Secret) // nolint: errcheck
|
||||
decryptor := makeStreamCipher(decHasher.Sum(nil), fm.iv())
|
||||
|
||||
invertedFrame := fm.invert()
|
||||
encHasher := sha256.New()
|
||||
encHasher.Write(invertedFrame.key()) // nolint: errcheck
|
||||
encHasher.Write(newconfig.C.Secret) // nolint: errcheck
|
||||
encryptor := makeStreamCipher(encHasher.Sum(nil), invertedFrame.iv())
|
||||
|
||||
decryptedFrame := frame{}
|
||||
decryptor.XORKeyStream(decryptedFrame.bytes(), fm.bytes())
|
||||
|
||||
magic := decryptedFrame.magic()
|
||||
switch {
|
||||
case bytes.Equal(magic, newprotocol.ConnectionTagAbridged):
|
||||
c.ConnectionType = newprotocol.ConnectionTypeAbridged
|
||||
case bytes.Equal(magic, newprotocol.ConnectionTagIntermediate):
|
||||
c.ConnectionType = newprotocol.ConnectionTypeIntermediate
|
||||
case bytes.Equal(magic, newprotocol.ConnectionTagSecure):
|
||||
c.ConnectionType = newprotocol.ConnectionTypeSecure
|
||||
default:
|
||||
return nil, errors.New("Unknown connection type")
|
||||
}
|
||||
|
||||
c.ConnectionProtocol = newprotocol.ConnectionProtocolIPv4
|
||||
if socket.LocalAddr().IP.To4() == nil {
|
||||
c.ConnectionProtocol = newprotocol.ConnectionProtocolIPv6
|
||||
}
|
||||
|
||||
buf := bytes.NewReader(decryptedFrame.dc())
|
||||
if err := binary.Read(buf, binary.LittleEndian, &c.DC); err != nil {
|
||||
c.DC = 1
|
||||
}
|
||||
|
||||
antiReplayKey := decryptedFrame.unique()
|
||||
if newantireplay.Has(antiReplayKey) {
|
||||
return nil, errors.New("Replay attack is detected")
|
||||
}
|
||||
newantireplay.Add(antiReplayKey)
|
||||
|
||||
return newwrappers.NewObfuscated2(socket, encryptor, decryptor), nil
|
||||
}
|
||||
|
||||
func (c *ClientProtocol) ReadFrame(socket newwrappers.StreamReader) (fm frame, err error) {
|
||||
if _, err := io.ReadFull(handshakeReader{socket}, fm.bytes()); err != nil {
|
||||
err = errors.Annotate(err, "Cannot extract obfuscated2 frame")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type handshakeReader struct {
|
||||
parent newwrappers.StreamReader
|
||||
}
|
||||
|
||||
func (h handshakeReader) Read(p []byte) (int, error) {
|
||||
return h.parent.ReadTimeout(p, clientProtocolHandshakeTimeout)
|
||||
}
|
||||
|
||||
func makeStreamCipher(key, iv []byte) cipher.Stream {
|
||||
block, _ := aes.NewCipher(key) // nolint: gosec
|
||||
return cipher.NewCTR(block, iv)
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package newobfuscated2
|
||||
|
||||
const (
|
||||
frameLenKey = 32
|
||||
frameLenIV = 16
|
||||
frameLenMagic = 4
|
||||
frameLenDC = 2
|
||||
|
||||
frameOffsetFirst = 8
|
||||
frameOffsetKey = frameOffsetFirst + frameLenKey
|
||||
frameOffsetIV = frameOffsetKey + frameLenIV
|
||||
frameOffsetMagic = frameOffsetIV + frameLenMagic
|
||||
frameOffsetDC = frameOffsetMagic + frameLenDC
|
||||
|
||||
frameLen = 64
|
||||
)
|
||||
|
||||
// [frameOffsetFirst:frameOffsetKey:frameOffsetIV:frameOffsetMagic:frameOffsetDC:frameOffsetEnd]
|
||||
type frame struct {
|
||||
data [frameLen]byte
|
||||
}
|
||||
|
||||
func (f *frame) bytes() []byte {
|
||||
return f.data[:]
|
||||
}
|
||||
|
||||
func (f *frame) key() []byte {
|
||||
return f.data[frameOffsetFirst:frameOffsetKey]
|
||||
}
|
||||
|
||||
func (f *frame) iv() []byte {
|
||||
return f.data[frameOffsetKey:frameOffsetIV]
|
||||
}
|
||||
|
||||
func (f *frame) magic() []byte {
|
||||
return f.data[frameOffsetIV:frameOffsetMagic]
|
||||
}
|
||||
|
||||
func (f *frame) dc() []byte {
|
||||
return f.data[frameOffsetMagic:frameOffsetDC]
|
||||
}
|
||||
|
||||
func (f *frame) unique() []byte {
|
||||
return f.data[frameOffsetFirst:frameOffsetDC]
|
||||
}
|
||||
|
||||
func (f *frame) invert() (nf frame) {
|
||||
nf = *f
|
||||
for i := 0; i < frameLenKey+frameLenIV; i++ {
|
||||
nf.data[frameOffsetFirst+i] = nf.data[frameOffsetIV-1-i]
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package newobfuscated2
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
|
||||
"github.com/juju/errors"
|
||||
|
||||
"github.com/9seconds/mtg/newprotocol"
|
||||
"github.com/9seconds/mtg/newwrappers"
|
||||
)
|
||||
|
||||
type TelegramProtocol struct {
|
||||
newprotocol.BaseProtocol
|
||||
}
|
||||
|
||||
func (t *TelegramProtocol) Handshake(socketRaw newwrappers.Wrap, client *ClientProtocol) (newwrappers.StreamReadWriteCloser, error) {
|
||||
socket := socketRaw.(newwrappers.StreamReadWriteCloser)
|
||||
fm := generateFrame(client)
|
||||
data := fm.bytes()
|
||||
|
||||
encryptor := makeStreamCipher(fm.key(), fm.iv())
|
||||
decryptedFrame := fm.invert()
|
||||
decryptor := makeStreamCipher(decryptedFrame.key(), decryptedFrame.iv())
|
||||
|
||||
copyFrame := make([]byte, frameLen)
|
||||
copy(copyFrame[:frameOffsetIV], data[:frameOffsetIV])
|
||||
encryptor.XORKeyStream(data, data)
|
||||
copy(data[:frameOffsetIV], copyFrame[:frameOffsetIV])
|
||||
|
||||
if _, err := socket.Write(data); err != nil {
|
||||
return nil, errors.Annotate(err, "Cannot write handshate frame to Telegram")
|
||||
}
|
||||
|
||||
return newwrappers.NewObfuscated2(socket, encryptor, decryptor), nil
|
||||
}
|
||||
|
||||
func generateFrame(client *ClientProtocol) (fm frame) {
|
||||
for {
|
||||
data := fm.bytes()
|
||||
if _, err := rand.Read(data); err != nil {
|
||||
continue
|
||||
}
|
||||
if data[0] == 0xef {
|
||||
continue
|
||||
}
|
||||
|
||||
val := (uint32(data[3]) << 24) | (uint32(data[2]) << 16) | (uint32(data[1]) << 8) | uint32(data[0])
|
||||
if val == 0x44414548 || val == 0x54534f50 || val == 0x20544547 || val == 0x4954504f || val == 0xeeeeeeee {
|
||||
continue
|
||||
}
|
||||
|
||||
val = (uint32(data[7]) << 24) | (uint32(data[6]) << 16) | (uint32(data[5]) << 8) | uint32(data[4])
|
||||
if val == 0x00000000 {
|
||||
continue
|
||||
}
|
||||
|
||||
copy(fm.magic(), client.ConnectionType.Tag())
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user