Remove frame pool for obfuscated2 frames

This commit is contained in:
9seconds
2018-07-01 12:01:56 +03:00
parent 9f90f87758
commit 6253648356
7 changed files with 33 additions and 63 deletions
-1
View File
@@ -29,7 +29,6 @@ func DirectInit(conn net.Conn, conf *config.Config) (*mtproto.ConnectionOpts, io
if err != nil { if err != nil {
return nil, nil, errors.Annotate(err, "Cannot extract frame") return nil, nil, errors.Annotate(err, "Cannot extract frame")
} }
defer obfuscated2.ReturnFrame(frame)
obfs2, connOpts, err := obfuscated2.ParseObfuscated2ClientFrame(conf.Secret, frame) obfs2, connOpts, err := obfuscated2.ParseObfuscated2ClientFrame(conf.Secret, frame)
if err != nil { if err != nil {
+15 -17
View File
@@ -66,57 +66,55 @@ func (f Frame) ConnectionType() (mtproto.ConnectionType, error) {
// Invert inverts frame for extracting encryption keys. Pkease check that link: // Invert inverts frame for extracting encryption keys. Pkease check that link:
// https://blog.susanka.eu/how-telegram-obfuscates-its-mtproto-traffic/ // https://blog.susanka.eu/how-telegram-obfuscates-its-mtproto-traffic/
func (f Frame) Invert() *Frame { func (f Frame) Invert() Frame {
reversed := MakeFrame() reversed := make(Frame, FrameLen)
copy(*reversed, f) copy(reversed, f)
for i := 0; i < frameLenKey+frameLenIV; i++ { for i := 0; i < frameLenKey+frameLenIV; i++ {
(*reversed)[frameOffsetFirst+i] = f[frameOffsetIV-1-i] reversed[frameOffsetFirst+i] = f[frameOffsetIV-1-i]
} }
return reversed return reversed
} }
// ExtractFrame extracts exact obfuscated2 handshake frame from given reader. // ExtractFrame extracts exact obfuscated2 handshake frame from given reader.
func ExtractFrame(conn io.Reader) (*Frame, error) { func ExtractFrame(conn io.Reader) (Frame, error) {
frame := MakeFrame() frame := make(Frame, FrameLen)
buf := bytes.NewBuffer(*frame) buf := bytes.NewBuffer(frame)
buf.Reset() buf.Reset()
if _, err := io.CopyN(buf, conn, FrameLen); err != nil { if _, err := io.CopyN(buf, conn, FrameLen); err != nil {
ReturnFrame(frame)
return nil, errors.Annotate(err, "Cannot extract obfuscated header") return nil, errors.Annotate(err, "Cannot extract obfuscated header")
} }
copy(*frame, buf.Bytes()) copy(frame, buf.Bytes())
return frame, nil return frame, nil
} }
func generateFrame(connectionType mtproto.ConnectionType) *Frame { func generateFrame(connectionType mtproto.ConnectionType) Frame {
frame := MakeFrame() frame := make(Frame, FrameLen)
data := *frame
for { for {
if _, err := rand.Read(data); err != nil { if _, err := rand.Read(frame); err != nil {
continue continue
} }
if data[0] == 0xef { if frame[0] == 0xef {
continue continue
} }
val := (uint32(data[3]) << 24) | (uint32(data[2]) << 16) | (uint32(data[1]) << 8) | uint32(data[0]) val := (uint32(frame[3]) << 24) | (uint32(frame[2]) << 16) | (uint32(frame[1]) << 8) | uint32(frame[0])
if val == 0x44414548 || val == 0x54534f50 || val == 0x20544547 || val == 0x4954504f || val == 0xeeeeeeee { if val == 0x44414548 || val == 0x54534f50 || val == 0x20544547 || val == 0x4954504f || val == 0xeeeeeeee {
continue continue
} }
val = (uint32(data[7]) << 24) | (uint32(data[6]) << 16) | (uint32(data[5]) << 8) | uint32(data[4]) val = (uint32(frame[7]) << 24) | (uint32(frame[6]) << 16) | (uint32(frame[5]) << 8) | uint32(frame[4])
if val == 0x00000000 { if val == 0x00000000 {
continue continue
} }
// error has to be checked before calling this function // error has to be checked before calling this function
tag, _ := connectionType.Tag() // nolint: errcheck tag, _ := connectionType.Tag() // nolint: errcheck
copy(data.Magic(), tag) copy(frame.Magic(), tag)
return frame return frame
} }
-24
View File
@@ -1,24 +0,0 @@
package obfuscated2
import "sync"
var framePool sync.Pool
// MakeFrame returns new pointer to the handshake frame.
func MakeFrame() *Frame {
return framePool.Get().(*Frame)
}
// ReturnFrame returns pointer to the handshake frame back to the pool.
func ReturnFrame(f *Frame) {
framePool.Put(f)
}
func init() {
framePool = sync.Pool{
New: func() interface{} {
data := make(Frame, FrameLen)
return &data
},
}
}
+4 -4
View File
@@ -54,21 +54,21 @@ func TestFrameValid(t *testing.T) {
func TestFrameDoubleInvert(t *testing.T) { func TestFrameDoubleInvert(t *testing.T) {
frame := makeFrame() frame := makeFrame()
assert.True(t, bytes.Equal(frame, *frame.Invert().Invert())) assert.True(t, bytes.Equal(frame, frame.Invert().Invert()))
} }
func TestFrameInvert(t *testing.T) { func TestFrameInvert(t *testing.T) {
frame := makeFrame() frame := makeFrame()
reversed := frame.Invert() reversed := frame.Invert()
assert.Exactly(t, frame[:8], (*reversed)[:8]) assert.Exactly(t, frame[:8], reversed[:8])
assert.Exactly(t, frame[56:], (*reversed)[56:]) assert.Exactly(t, frame[56:], reversed[56:])
toCompare := make([]byte, 48) toCompare := make([]byte, 48)
for i := 0; i < 48; i++ { for i := 0; i < 48; i++ {
toCompare[i] = frame[55-i] toCompare[i] = frame[55-i]
} }
assert.Equal(t, []byte((*reversed)[8:56]), toCompare) assert.Equal(t, []byte(reversed[8:56]), toCompare)
} }
func TestFrameGenerateValid(t *testing.T) { func TestFrameGenerateValid(t *testing.T) {
+8 -10
View File
@@ -21,7 +21,7 @@ type Obfuscated2 struct {
// details: http://telegra.ph/telegram-blocks-wtf-05-26 // details: http://telegra.ph/telegram-blocks-wtf-05-26
// //
// Beware, link above is in russian. // Beware, link above is in russian.
func ParseObfuscated2ClientFrame(secret []byte, frame *Frame) (*Obfuscated2, *mtproto.ConnectionOpts, error) { func ParseObfuscated2ClientFrame(secret []byte, frame Frame) (*Obfuscated2, *mtproto.ConnectionOpts, error) {
decHasher := sha256.New() decHasher := sha256.New()
decHasher.Write(frame.Key()) // nolint: errcheck decHasher.Write(frame.Key()) // nolint: errcheck
decHasher.Write(secret) // nolint: errcheck decHasher.Write(secret) // nolint: errcheck
@@ -33,9 +33,8 @@ func ParseObfuscated2ClientFrame(secret []byte, frame *Frame) (*Obfuscated2, *mt
encHasher.Write(secret) // nolint: errcheck encHasher.Write(secret) // nolint: errcheck
encryptor := makeStreamCipher(encHasher.Sum(nil), invertedFrame.IV()) encryptor := makeStreamCipher(encHasher.Sum(nil), invertedFrame.IV())
decryptedFrame := MakeFrame() decryptedFrame := make(Frame, FrameLen)
defer ReturnFrame(decryptedFrame) decryptor.XORKeyStream(decryptedFrame, frame)
decryptor.XORKeyStream(*decryptedFrame, *frame)
connType, err := decryptedFrame.ConnectionType() connType, err := decryptedFrame.ConnectionType()
if err != nil { if err != nil {
return nil, nil, errors.Annotate(err, "Unknown protocol") return nil, nil, errors.Annotate(err, "Unknown protocol")
@@ -56,18 +55,17 @@ func ParseObfuscated2ClientFrame(secret []byte, frame *Frame) (*Obfuscated2, *mt
// MakeTelegramObfuscated2Frame creates new handshake frame to send to // MakeTelegramObfuscated2Frame creates new handshake frame to send to
// Telegram. // Telegram.
// https://blog.susanka.eu/how-telegram-obfuscates-its-mtproto-traffic/ // https://blog.susanka.eu/how-telegram-obfuscates-its-mtproto-traffic/
func MakeTelegramObfuscated2Frame(opts *mtproto.ConnectionOpts) (*Obfuscated2, *Frame) { func MakeTelegramObfuscated2Frame(opts *mtproto.ConnectionOpts) (*Obfuscated2, Frame) {
frame := generateFrame(opts.ConnectionType) frame := generateFrame(opts.ConnectionType)
encryptor := makeStreamCipher(frame.Key(), frame.IV()) encryptor := makeStreamCipher(frame.Key(), frame.IV())
decryptorFrame := frame.Invert() decryptorFrame := frame.Invert()
decryptor := makeStreamCipher(decryptorFrame.Key(), decryptorFrame.IV()) decryptor := makeStreamCipher(decryptorFrame.Key(), decryptorFrame.IV())
copyFrame := MakeFrame() copyFrame := make(Frame, FrameLen)
defer ReturnFrame(copyFrame) copy(copyFrame[:frameOffsetIV], frame[:frameOffsetIV])
copy((*copyFrame)[:frameOffsetIV], (*frame)[:frameOffsetIV]) encryptor.XORKeyStream(frame, frame)
encryptor.XORKeyStream(*frame, *frame) copy(frame[:frameOffsetIV], copyFrame[:frameOffsetIV])
copy((*frame)[:frameOffsetIV], (*copyFrame)[:frameOffsetIV])
obfs := &Obfuscated2{ obfs := &Obfuscated2{
Decryptor: decryptor, Decryptor: decryptor,
+5 -5
View File
@@ -18,7 +18,7 @@ func TestObfs2TelegramFrameDecrypt(t *testing.T) {
decryptor := makeStreamCipher(frame.Key(), frame.IV()) decryptor := makeStreamCipher(frame.Key(), frame.IV())
decrypted := make(Frame, FrameLen) decrypted := make(Frame, FrameLen)
decryptor.XORKeyStream(decrypted, *frame) decryptor.XORKeyStream(decrypted, frame)
_, err := decrypted.ConnectionType() _, err := decrypted.ConnectionType()
assert.Nil(t, err) assert.Nil(t, err)
@@ -53,8 +53,8 @@ func TestObfs2Full(t *testing.T) {
encryptor := makeStreamCipher(clientKey, clientFrame.IV()) encryptor := makeStreamCipher(clientKey, clientFrame.IV())
encrypted := make(Frame, FrameLen) encrypted := make(Frame, FrameLen)
encryptor.XORKeyStream(encrypted, *clientFrame) encryptor.XORKeyStream(encrypted, clientFrame)
copy(encrypted[:56], (*clientFrame)[:56]) copy(encrypted[:56], clientFrame[:56])
invertedClientFrame := clientFrame.Invert() invertedClientFrame := clientFrame.Invert()
clientHasher = sha256.New() clientHasher = sha256.New()
@@ -63,7 +63,7 @@ func TestObfs2Full(t *testing.T) {
invertedClientKey := clientHasher.Sum(nil) invertedClientKey := clientHasher.Sum(nil)
clientDecryptor := makeStreamCipher(invertedClientKey, invertedClientFrame.IV()) clientDecryptor := makeStreamCipher(invertedClientKey, invertedClientFrame.IV())
clientObfs, _, err := ParseObfuscated2ClientFrame(secret, &encrypted) clientObfs, _, err := ParseObfuscated2ClientFrame(secret, encrypted)
assert.Nil(t, err) assert.Nil(t, err)
connOpts := &mtproto.ConnectionOpts{ connOpts := &mtproto.ConnectionOpts{
@@ -73,7 +73,7 @@ func TestObfs2Full(t *testing.T) {
tgObfs, tgFrame := MakeTelegramObfuscated2Frame(connOpts) tgObfs, tgFrame := MakeTelegramObfuscated2Frame(connOpts)
tgDecryptor := makeStreamCipher(tgFrame.Key(), tgFrame.IV()) tgDecryptor := makeStreamCipher(tgFrame.Key(), tgFrame.IV())
decrypted := make(Frame, FrameLen) decrypted := make(Frame, FrameLen)
tgDecryptor.XORKeyStream(decrypted, *tgFrame) tgDecryptor.XORKeyStream(decrypted, tgFrame)
_, err = decrypted.ConnectionType() _, err = decrypted.ConnectionType()
assert.Nil(t, err) assert.Nil(t, err)
+1 -2
View File
@@ -46,9 +46,8 @@ func (t *directTelegram) Dial(connOpts *mtproto.ConnectionOpts) (io.ReadWriteClo
func (t *directTelegram) Init(connOpts *mtproto.ConnectionOpts, conn io.ReadWriteCloser) (io.ReadWriteCloser, error) { func (t *directTelegram) Init(connOpts *mtproto.ConnectionOpts, conn io.ReadWriteCloser) (io.ReadWriteCloser, error) {
obfs2, frame := obfuscated2.MakeTelegramObfuscated2Frame(connOpts) obfs2, frame := obfuscated2.MakeTelegramObfuscated2Frame(connOpts)
defer obfuscated2.ReturnFrame(frame)
if n, err := conn.Write(*frame); err != nil || n != len(*frame) { if n, err := conn.Write(frame); err != nil || n != obfuscated2.FrameLen {
return nil, errors.Annotate(err, "Cannot write hadnshake frame") return nil, errors.Annotate(err, "Cannot write hadnshake frame")
} }