client spoof back

This commit is contained in:
Cynthia Foxwell 2023-06-20 17:30:35 -06:00
parent 0b20d3e9a7
commit 50e44abaff
2 changed files with 106 additions and 53 deletions

View File

@ -83,9 +83,9 @@ process.stdin.setEncoding("utf8");
client.once("ready", function () { client.once("ready", function () {
console.log( console.log(
"Logged in as: " + "Logged in as: " +
chalk.yellow(`${client.user.username} (${client.user.id})`) chalk.yellow(`${client.user?.username} (${client.user?.id})`)
); );
comcord.state.nameLength = client.user.username.length + 2; comcord.state.nameLength = (client.user?.username?.length ?? 0) + 2;
listGuilds(); listGuilds();
@ -242,10 +242,7 @@ if (
config.allowUserAccounts == "true" && config.allowUserAccounts == "true" &&
!(token ?? config.token).startsWith("Bot ") !(token ?? config.token).startsWith("Bot ")
) { ) {
console.log("User account support pending rewrite."); if (fetch == null) {
process.exit(1);
/*if (fetch == null) {
console.log("Node v18+ needed for user account support."); console.log("Node v18+ needed for user account support.");
process.exit(1); process.exit(1);
} }
@ -253,48 +250,78 @@ if (
(async function () { (async function () {
comcord.clientSpoof = require("./lib/clientSpoof"); comcord.clientSpoof = require("./lib/clientSpoof");
const superProperties = await comcord.clientSpoof.getSuperProperties(); const superProperties = await comcord.clientSpoof.getSuperProperties();
comcord.clientSpoof.superProperties = superProperties;
comcord.clientSpoof.superPropertiesBase64 = Buffer.from(
JSON.stringify(superProperties)
).toString("base64");
console.log("% Allowing non-bot tokens to connect"); // FIXME: is there a way we can string patch functions without having to
const connectLines = client.connect.toString().split("\n"); // dump locals into global
connectLines.splice(0, 4); global.MultipartData = require("@projectdysnomia/dysnomia/lib/util/MultipartData.js");
connectLines.splice(-1, 1); global.SequentialBucket = require("@projectdysnomia/dysnomia/lib/util/SequentialBucket.js");
global.DiscordHTTPError = require("@projectdysnomia/dysnomia/lib/errors/DiscordHTTPError.js");
global.DiscordRESTError = require("@projectdysnomia/dysnomia/lib/errors/DiscordRESTError.js");
global.Zlib = require("node:zlib");
global.HTTPS = require("node:https");
global.HTTP = require("node:http");
global.GatewayOPCodes = Constants.GatewayOPCodes;
global.GATEWAY_VERSION = Constants.GATEWAY_VERSION;
const newConnect = new client.connect.constructor(connectLines.join("\n")); client.getGateway = async function getGateway() {
client.connect = newConnect.bind(client); return {url: "wss://gateway.discord.gg"};
};
console.log("% Injecting headers into request handler"); console.log("% Injecting headers into request handler");
client.rest.handler.options.userAgent = `Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) discord/${superProperties.client_version} Chrome/91.0.4472.164 Electron/13.6.6 Safari/537.36`; client.requestHandler.userAgent = superProperties.browser_user_agent;
client.rest.handler._request = client.rest.handler.request.bind( const requestFunction = client.requestHandler.request.toString();
client.rest.handler const newRequest = requestFunction
); .replace(
client.rest.handler.request = async function (options) { "this.userAgent,",
options.headers = options.headers ?? {}; 'this.userAgent,\n"X-Super-Properties":comcord.clientSpoof.superPropertiesBase64,'
options.headers["X-Super-Properties"] = )
await comcord.clientSpoof.getSuperPropertiesBase64(); .replace("._token", '._token.replace("Bot ","")');
if (requestFunction === newRequest)
throw new Error("Failed to patch request");
client.requestHandler.request = new Function(
"method",
"url",
"auth",
"body",
"file",
"_route",
"short",
`return (function ${newRequest}).apply(this,arguments)`
).bind(client.requestHandler);
return await this._request.apply(this, [options]); console.log("% Injecting shard spawning");
}.bind(client.rest.handler);
console.log("% Setting gateway connection properties");
client.shards.options.connectionProperties = superProperties;
console.log("% Injecting application into READY payload");
client.shards._spawn = client.shards.spawn.bind(client.shards); client.shards._spawn = client.shards.spawn.bind(client.shards);
client.shards.spawn = function (id) { client.shards.spawn = function (id) {
const res = this._spawn.apply(this, [id]); const res = this._spawn.apply(this, [id]);
const shard = this.get(id); const shard = this.get(id);
if (shard) { if (shard) {
shard._onDispatch = shard.onDispatch.bind(shard); const identifyFunction = shard.identify.toString();
shard.onDispatch = async function (packet) { const newIdentify = identifyFunction
.replace(
/properties: {\n\s+.+?\n\s+.+?\n\s+.+?\n\s+}\n/,
"properties: comcord.clientSpoof.superProperties\n"
)
.replace(/\s+intents: this.client.shards.options.intents,/, "");
if (identifyFunction === newIdentify)
throw new Error("Failed to patch identify");
shard.identify = new Function(
`(function ${newIdentify}).apply(this, arguments)`
);
shard._wsEvent = shard.wsEvent;
shard.wsEvent = function (packet) {
if (packet.t == "READY") { if (packet.t == "READY") {
packet.d.application = {id: CLIENT_ID, flags: 565248}; packet.d.application = {id: CLIENT_ID, flags: 565248};
} }
const ret = await this._onDispatch.apply(this, [packet]); const ret = this._wsEvent.apply(this, [packet]);
if (packet.t == "READY") { if (packet.t == "READY") {
for (const guild of packet.d.guilds) { for (const guild of packet.d.guilds) {
await this._onDispatch.apply(this, [ this._wsEvent.apply(this, [
{ {
t: "GUILD_CREATE", t: "GUILD_CREATE",
d: guild, d: guild,
@ -304,15 +331,15 @@ if (
} }
return ret; return ret;
}.bind(shard); };
} }
return res; return res;
}.bind(client.shards); };
console.log("% Connecting to gateway now"); console.log("% Connecting to gateway now");
await client.connect(); await client.connect();
})();*/ })();
} else { } else {
client.connect(); client.connect();
} }
@ -364,7 +391,7 @@ setInterval(function () {
} else { } else {
console.log(timeString); console.log(timeString);
} }
comcord.state.nameLength = client.user.username.length + 2; comcord.state.nameLength = (client.user?.username?.length ?? 0) + 2;
sentTime = true; sentTime = true;
} else if (seconds > 2 && sentTime) { } else if (seconds > 2 && sentTime) {
sentTime = false; sentTime = false;

View File

@ -51,7 +51,7 @@ async function getBuildNumber() {
return buildNumber; return buildNumber;
} }
async function getClientVersion() { /*async function getClientVersion() {
if (comcord.state.cachedClientVersion) { if (comcord.state.cachedClientVersion) {
return comcord.state.cachedClientVersion; return comcord.state.cachedClientVersion;
} }
@ -63,15 +63,43 @@ async function getClientVersion() {
comcord.state.cachedClientVersion = clientVersion; comcord.state.cachedClientVersion = clientVersion;
return clientVersion; return clientVersion;
}*/
async function getBrowserInfo() {
let targetOS;
switch (process.platform) {
case "win32":
default:
targetOS = "windows";
break;
case "darwin":
targetOS = "mac os";
break;
case "linux":
targetOS = "linux";
break;
}
const data = await fetch(
`https://cdn.jsdelivr.net/gh/ray-lothian/UserAgent-Switcher/v2/firefox/data/popup/browsers/firefox-${encodeURIComponent(
targetOS
)}.json`
).then((res) => res.json());
data.sort((a, b) => Number(b.browser.major) - Number(a.browser.major));
const target = data[0];
return {ua: target.ua, version: target.browser.version};
} }
async function getSuperProperties() { async function getSuperProperties() {
const buildNumber = await getBuildNumber(); const buildNumber = await getBuildNumber();
const clientVersion = await getClientVersion(); // const clientVersion = await getClientVersion();
const browserInfo = await getBrowserInfo();
let _os; let _os;
switch (process.platform) { switch (process.platform) {
case "win32": case "win32":
default:
_os = "Windows"; _os = "Windows";
break; break;
case "darwin": case "darwin":
@ -80,28 +108,26 @@ async function getSuperProperties() {
case "linux": case "linux":
_os = "Linux"; _os = "Linux";
break; break;
default:
_os = process.platform;
} }
const props = { const props = {
os: _os, browser: "Firefox",
browser: "Discord Client", browser_user_agent: browserInfo.ua,
releaseChannel: "stable", browser_version: browserInfo.version,
client_version: clientVersion,
os_version: os.release(),
os_arch: os.arch(),
system_locale: "en-US",
client_build_number: buildNumber, client_build_number: buildNumber,
client_event_source: null, client_event_source: null,
device: "",
os: _os,
os_version: os.release(),
//os_arch: os.arch(),
referrer: "",
referrer_current: "",
referring_domain: "",
referring_domain_current: "",
release_channel: "stable",
system_locale: "en-US",
}; };
return props; return props;
} }
async function getSuperPropertiesBase64() { module.exports = {getSuperProperties};
return Buffer.from(JSON.stringify(await getSuperProperties())).toString(
"base64"
);
}
module.exports = {getSuperProperties, getSuperPropertiesBase64};