Skip to content

Instantly share code, notes, and snippets.

@wfjsw
Created March 30, 2019 12:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wfjsw/a1e894c5a1093526efa9e465afaa7b10 to your computer and use it in GitHub Desktop.
Save wfjsw/a1e894c5a1093526efa9e465afaa7b10 to your computer and use it in GitHub Desktop.
Script snippet used to check MTProxy availability.
var Uint64BE, Int64BE, Uint64LE, Int64LE; !function (E) { var g, A = "undefined", U = A !== typeof Buffer && Buffer, I = A !== typeof Uint8Array && Uint8Array, L = A !== typeof ArrayBuffer && ArrayBuffer, d = [0, 0, 0, 0, 0, 0, 0, 0], n = Array.isArray || function (t) { return !!t && "[object Array]" == Object.prototype.toString.call(t) }, w = 4294967296; function t(t, r, a) { var c = r ? 0 : 4, y = r ? 4 : 0, n = r ? 0 : 3, e = r ? 1 : 2, o = r ? 2 : 1, i = r ? 3 : 0, u = r ? k : J, s = r ? O : _, f = l.prototype, h = "is" + t, v = "_" + h; return f.buffer = void 0, f.offset = 0, f[v] = !0, f.toNumber = p, f.toString = function (t) { var r = this.buffer, f = this.offset, n = B(r, f + c), e = B(r, f + y), o = "", i = !a && 2147483648 & n; i && (n = ~n, e = w - e); t = t || 10; for (; ;) { var u = n % t * w + e; if (n = Math.floor(n / t), e = Math.floor(u / t), o = (u % t).toString(t) + o, !n && !e) break } i && (o = "-" + o); return o }, f.toJSON = p, f.toArray = m, U && (f.toBuffer = S), I && (f.toArrayBuffer = j), l[h] = function (t) { return !(!t || !t[v]) }, E[t] = l; function l(t, r, f, n) { return this instanceof l ? function (t, r, f, n, e) { I && L && (r instanceof L && (r = new I(r)), n instanceof L && (n = new I(n))); if (!(r || f || n || g)) return void (t.buffer = N(d, 0)); if (!x(r, f)) { var o = g || Array; e = f, n = r, f = 0, r = new o(8) } if (t.buffer = r, t.offset = f |= 0, A === typeof n) return; "string" == typeof n ? function (t, r, f, n) { var e = 0, o = f.length, i = 0, u = 0; "-" === f[0] && e++; var a = e; for (; e < o;) { var s = parseInt(f[e++], n); if (!(0 <= s)) break; u = u * n + s, i = i * n + Math.floor(u / w), u %= w } a && (i = ~i, u ? u = w - u : i++); b(t, r + c, i), b(t, r + y, u) }(r, f, n, e || 10) : x(n, e) ? M(r, f, n, e) : "number" == typeof e ? (b(r, f + c, n), b(r, f + y, e)) : 0 < n ? u(r, f, n) : n < 0 ? s(r, f, n) : M(r, f, d, 0) }(this, t, r, f, n) : new l(t, r, f, n) } function p() { var t = this.buffer, r = this.offset, f = B(t, r + c), n = B(t, r + y); return a || (f |= 0), f ? f * w + n : n } function b(t, r, f) { t[r + i] = 255 & f, f >>= 8, t[r + o] = 255 & f, f >>= 8, t[r + e] = 255 & f, f >>= 8, t[r + n] = 255 & f } function B(t, r) { return 16777216 * t[r + n] + (t[r + e] << 16) + (t[r + o] << 8) + t[r + i] } } function m(t) { var r = this.buffer, f = this.offset; return g = null, !1 !== t && n(r) ? 8 === r.length ? r : r.slice(f, f + 8) : N(r, f) } function S(t) { var r = this.buffer, f = this.offset; return g = U, !1 !== t && U.isBuffer(r) ? 8 === r.length ? r : r.slice(f, f + 8) : U.from(j.call(this, t)) } function j(t) { var r = this.buffer, f = this.offset, n = r.buffer; if (g = I, !1 !== t && !r.offset && n instanceof L) return 8 === n.byteLength ? n : n.slice(f, f + 8); var e = new I(8); return M(e, 0, r, f), e.buffer } function x(t, r) { var f = t && t.length; return r |= 0, f && r + 8 <= f && "string" != typeof t[r] } function M(t, r, f, n) { r |= 0, n |= 0; for (var e = 0; e < 8; e++)t[r++] = 255 & f[n++] } function N(t, r) { return Array.prototype.slice.call(t, r, r + 8) } function k(t, r, f) { for (var n = r + 8; r < n;)t[--n] = 255 & f, f /= 256 } function O(t, r, f) { var n = r + 8; for (f++; r < n;)t[--n] = 255 & -f ^ 255, f /= 256 } function J(t, r, f) { for (var n = r + 8; r < n;)t[r++] = 255 & f, f /= 256 } function _(t, r, f) { var n = r + 8; for (f++; r < n;)t[r++] = 255 & -f ^ 255, f /= 256 } Uint64BE = t("Uint64BE", !0, !0), Int64BE = t("Int64BE", !0, !1), Uint64LE = t("Uint64LE", !1, !0), Int64LE = t("Int64LE", !1, !1) }("object" == typeof exports && "string" != typeof exports.nodeName ? exports : this || {});
const net = require('net')
const crypto = require('crypto')
exports.pingDirect = () => new Promise((rs, rj) => {
try {
const start_time = Date.now()
let pack_creation_time
const client = net.connect(443, '149.154.167.50')
client.on('ready', () => {
const intermediate_time = Date.now()
let msg_id_num = Date.now() / 1000 * Math.pow(2, 32)
while (msg_id_num % 4 !== 0) {
msg_id_num++
}
const msg_id_raw = new Uint64LE(msg_id_num)
const msg_id = msg_id_raw.toBuffer()
const msg = Buffer.concat([Buffer.from('78974660', 'hex'), Buffer.allocUnsafe(16)])
const msg_data_length = Buffer.from('14000000', 'hex')
const auth_key_id = Buffer.allocUnsafe(8).fill(0)
const data_pack = Buffer.concat([auth_key_id, msg_id, msg_data_length, msg])
const intermediate_header = Buffer.from('eeeeeeee', 'hex')
const data_length = Buffer.alloc(4)
data_length.writeUInt32LE(data_pack.length)
const data = Buffer.concat([intermediate_header, data_length, data_pack])
pack_creation_time = Date.now() - intermediate_time
client.write(data)
})
client.setTimeout(10000, () => {
client.destroy(new Error('timeout'))
})
client.on('data', (chunk) => {
const time_lapse = Date.now() - start_time - pack_creation_time
const res_str = chunk.toString('hex')
client.end()
if (res_str.indexOf('63241605') > -1) {
console.log(time_lapse)
rs(time_lapse)
} else {
rj(new Error('invalid response'))
}
})
client.on('error', e => rj(e))
} catch (e) {
rj(e)
}
})
exports.pingIntermediate = (ip, port, secret) => new Promise((rs, rj) => {
// plain[8 + 32(prekey) + 16(iv)] + enc[4(tag) + 2(dc_idx, signed le)]
try {
const secbin = Buffer.from(secret, 'hex')
const encprekey = crypto.randomBytes(32)
const enciv = crypto.randomBytes(16)
const enc_key = crypto.createHash('sha256').update(Buffer.concat([encprekey, secbin])).digest()
const revmix = Buffer.concat([encprekey, enciv]).reverse()
const decprekey = revmix.slice(0, 32)
const deciv = revmix.slice(32, 48)
const dec_key = crypto.createHash('sha256').update(Buffer.concat([decprekey, secbin])).digest()
const handshake_pkg = Buffer.concat([crypto.randomBytes(8), encprekey, enciv, Buffer.from('eeeeeeee', 'hex'), Buffer.from('02000000', 'hex')])
const encryptor = crypto.createCipheriv('aes-256-ctr', enc_key, enciv)
const decryptor = crypto.createDecipheriv('aes-256-ctr', dec_key, deciv)
const encrypted_handshake_pkg = encryptor.update(handshake_pkg)
const real_handshake_pkg = Buffer.concat([handshake_pkg.slice(0, 56), encrypted_handshake_pkg.slice(56, 64)])
const start_time = Date.now()
let pack_creation_time
const client = net.connect(port, ip)
client.setTimeout(5000)
client.on('timeout', () => {
client.destroy(new Error('timeout'))
})
client.on('ready', () => {
const intermediate_time = Date.now()
let msg_id_num = Date.now() / 1000 * Math.pow(2, 32)
while (msg_id_num % 4 !== 0) {
msg_id_num++
}
const msg_id_raw = new Uint64LE(msg_id_num)
const msg_id = msg_id_raw.toBuffer()
const msg = Buffer.concat([Buffer.from('78974660', 'hex'), Buffer.allocUnsafe(16)])
const msg_data_length = Buffer.from('14000000', 'hex')
const auth_key_id = Buffer.allocUnsafe(8).fill(0)
const data_pack = Buffer.concat([auth_key_id, msg_id, msg_data_length, msg])
const data_length = Buffer.alloc(4)
data_length.writeUInt32LE(data_pack.length)
const data = Buffer.concat([data_length, data_pack])
const enc_data = encryptor.update(data)
const pack = Buffer.concat([real_handshake_pkg, enc_data])
pack_creation_time = Date.now() - intermediate_time
client.write(pack)
})
client.on('data', (chunk) => {
const time_lapse = Date.now() - start_time - pack_creation_time
const raw_data = decryptor.update(chunk)
const res_str = raw_data.toString('hex')
client.end()
try {
encryptor.final()
decryptor.final()
} catch (e) {
//ignore
}
if (res_str.indexOf('63241605') > -1) {
console.log(time_lapse)
rs(time_lapse)
} else {
rj(new Error('invalid response'))
}
})
client.on('error', e => {
try {
encryptor.final()
decryptor.final()
} catch (e) {
//ignore
}
rj(e)
})
} catch (e) {
rj(e)
}
})
exports.pingSecure = (ip, port, secret) => new Promise((rs, rj) => {
// plain[8 + 32(prekey) + 16(iv)] + enc[4(tag) + 2(dc_idx, signed le)]
try {
const secbin = Buffer.from(secret, 'hex')
const encprekey = crypto.randomBytes(32)
const enciv = crypto.randomBytes(16)
const enc_key = crypto.createHash('sha256').update(Buffer.concat([encprekey, secbin])).digest()
const revmix = Buffer.concat([encprekey, enciv]).reverse()
const decprekey = revmix.slice(0, 32)
const deciv = revmix.slice(32, 48)
const dec_key = crypto.createHash('sha256').update(Buffer.concat([decprekey, secbin])).digest()
const handshake_pkg = Buffer.concat([crypto.randomBytes(8), encprekey, enciv, Buffer.from('dddddddd', 'hex'), Buffer.from('02000000', 'hex')])
const encryptor = crypto.createCipheriv('aes-256-ctr', enc_key, enciv)
const decryptor = crypto.createDecipheriv('aes-256-ctr', dec_key, deciv)
const encrypted_handshake_pkg = encryptor.update(handshake_pkg)
const real_handshake_pkg = Buffer.concat([handshake_pkg.slice(0, 56), encrypted_handshake_pkg.slice(56, 64)])
const start_time = Date.now()
let pack_creation_time
const client = net.connect(port, ip)
client.setTimeout(5000)
client.on('timeout', () => {
client.destroy(new Error('timeout'))
})
client.on('ready', () => {
const intermediate_time = Date.now()
let msg_id_num = Date.now() / 1000 * Math.pow(2, 32)
while (msg_id_num % 4 !== 0) {
msg_id_num++
}
const msg_id_raw = new Uint64LE(msg_id_num)
const msg_id = msg_id_raw.toBuffer()
const msg = Buffer.concat([Buffer.from('78974660', 'hex'), Buffer.allocUnsafe(16)])
const msg_data_length = Buffer.from('14000000', 'hex')
const auth_key_id = Buffer.allocUnsafe(8).fill(0)
const data_pack = Buffer.concat([auth_key_id, msg_id, msg_data_length, msg])
const padding_length = Math.floor(Math.random() * 4)
const padding = crypto.randomBytes(padding_length)
const data_length = Buffer.alloc(4)
data_length.writeUInt32LE(data_pack.length + padding_length)
const data = Buffer.concat([data_length, data_pack, padding])
const enc_data = encryptor.update(data)
const pack = Buffer.concat([real_handshake_pkg, enc_data])
pack_creation_time = Date.now() - intermediate_time
client.write(pack)
})
client.on('data', (chunk) => {
const time_lapse = Date.now() - start_time - pack_creation_time
const raw_data = decryptor.update(chunk)
const res_str = raw_data.toString('hex')
client.end()
try {
encryptor.final()
decryptor.final()
} catch (e) {
//ignore
}
if (res_str.indexOf('63241605') > -1) {
console.log(time_lapse)
rs(time_lapse)
} else {
rj(new Error('invalid response'))
}
})
client.on('error', e => {
try {
encryptor.final()
decryptor.final()
} catch (e) {
//ignore
}
rj(e)
})
} catch (e) {
rj(e)
}
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment