mtcute/packages/core/tests/fuzz/fuzz-packet.spec.ts

102 lines
3.2 KiB
TypeScript
Raw Normal View History

import { describe, after, it } from 'mocha'
import { expect } from 'chai'
import {
BaseTelegramClient, BinaryReader,
BinaryWriter,
defaultDcs,
randomBytes,
} from '../../src'
import { sleep } from '../../src/utils/misc-utils'
import { createAesIgeForMessage } from '../../src/utils/crypto/mtproto'
require('dotenv-flow').config()
describe('fuzz : packet', async function () {
if (!process.env.API_ID || !process.env.API_HASH) {
console.warn(
'Warning: skipping fuzz packet test (no API_ID or API_HASH)'
)
return
}
this.timeout(45000)
it('random packet', async () => {
const client = new BaseTelegramClient({
apiId: process.env.API_ID!,
apiHash: process.env.API_HASH!,
primaryDc: defaultDcs.defaultTestDc,
})
await client.connect()
await client.waitUntilUsable()
const errors: Error[] = []
const errorHandler = (err: Error) => {
errors.push(err)
}
client.onError(errorHandler)
const conn = client.primaryConnection
const mtproto = conn['_mtproto']
const createFakeMtprotoPacket = async (payload: Buffer): Promise<Buffer> => {
// create a fake mtproto packet
const messageId = conn['_getMessageId']().minus(1) // must be odd
const innerWriter = BinaryWriter.alloc(payload.length + 32)
innerWriter.raw(mtproto.serverSalt)
innerWriter.raw(mtproto._sessionId)
innerWriter.long(messageId)
innerWriter.int32(0) // seqno
innerWriter.int32(payload.length)
innerWriter.raw(payload)
const innerData = innerWriter.result()
const messageKey = (
await mtproto._crypto.sha256(
Buffer.concat([mtproto._authKeyServerSalt!, innerData])
)
).slice(8, 24)
const ige = await createAesIgeForMessage(
mtproto._crypto,
mtproto._authKey!,
messageKey,
false
)
const encryptedData = await ige.encrypt(innerData)
const writer = BinaryWriter.alloc(24 + encryptedData.length)
writer.raw(mtproto._authKeyId!)
writer.raw(messageKey)
return Buffer.concat([mtproto._authKeyId!, messageKey, encryptedData])
}
for (let i = 0; i < 100; i++) {
const payload = randomBytes(Math.round(Math.random() * 16) * 16)
await conn['onMessage'](await createFakeMtprotoPacket(payload))
await sleep(100)
}
// similar test, but this time only using object ids that do exist
const objectIds = Object.keys(new BinaryReader(Buffer.alloc(0))._objectsMap)
for (let i = 0; i < 100; i++) {
const payload = randomBytes((Math.round(Math.random() * 16) + 1) * 16)
const objectId = parseInt(objectIds[Math.round(Math.random() * objectIds.length)])
payload.writeUInt32LE(objectId, 0)
await conn['onMessage'](await createFakeMtprotoPacket(payload))
await sleep(100)
}
await client.close()
expect(errors.length).gt(0)
})
})