client spoof back
This commit is contained in:
		
							parent
							
								
									0b20d3e9a7
								
							
						
					
					
						commit
						50e44abaff
					
				
					 2 changed files with 106 additions and 53 deletions
				
			
		
							
								
								
									
										97
									
								
								src/index.js
									
										
									
									
									
								
							
							
						
						
									
										97
									
								
								src/index.js
									
										
									
									
									
								
							| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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};
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue