Skip to content

Instantly share code, notes, and snippets.

@MateusAquino
Last active October 4, 2020 16:33
Show Gist options
  • Save MateusAquino/b2ca2ce5aa3de750e4f3080cf87a842c to your computer and use it in GitHub Desktop.
Save MateusAquino/b2ca2ce5aa3de750e4f3080cf87a842c to your computer and use it in GitHub Desktop.
Código para bot de Discord (automute/link) [apenas moderadores]: pacotes udp entre cliente/servidor mais importantes foram mapeados com Regex. (Among Us v.2020.9.9s)
using System;
using System.IO;
using System.Text;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using SharpPcap;
using System.Linq;
namespace Example5
{
public class Program
{
public static void Main(string[] args)
{
var devices = CaptureDeviceList.Instance;
if (devices.Count < 1)
{
Console.WriteLine("No devices were found on this machine");
return;
}
List<SharpPcap.Npcap.NpcapDevice> capturingDevices = new List<SharpPcap.Npcap.NpcapDevice>();
foreach (SharpPcap.Npcap.NpcapDevice device in devices)
{
device.OnPacketArrival += new PacketArrivalEventHandler(device_OnPacketArrival);
int readTimeoutMilliseconds = 500;
device.Open(DeviceMode.Promiscuous, readTimeoutMilliseconds);
string filter = "udp";
device.Filter = filter;
device.StartCapture();
capturingDevices.Add(device);
}
Console.WriteLine("======= AutoAmong started =======");
Console.ReadLine();
foreach (SharpPcap.Npcap.NpcapDevice device in capturingDevices)
{
device.StopCapture();
device.Close();
}
}
private static string GetStringFromByteArray(System.Byte[] byteArray)
{
StringBuilder builder = new StringBuilder();
for (int i = 0; i < byteArray.Length; i++)
{
builder.Append(byteArray[i].ToString("x2"));
}
return builder.ToString();
}
public static byte[] StringToByteArray(String hex)
{
int NumberChars = hex.Length/2;
byte[] bytes = new byte[NumberChars];
using (var sr = new StringReader(hex))
{
for (int i = 0; i < NumberChars; i++)
bytes[i] =
Convert.ToByte(new string(new char[2]{(char)sr.Read(), (char)sr.Read()}), 16);
}
return bytes;
}
public static string Skip(String data, int bytes) {
string hexString = "";
for (int i = bytes*2; i < data.Length; i++) { hexString += data[i]; }
return hexString;
}
public static String getCorById(String id) {
int pos = Convert.ToInt32("0x"+id, 16);
string[] cores = { "vermelho", "azul escuro", "verde escuro", "rosa", "laranja",
"amarelo", "preto", "branco", "roxo", "marrom", "ciano", "verde claro"
};
return cores[pos];
}
public static String getNameFromData(String data, int skip) {
try {
data = Skip(data, skip);
byte[] dBytes = StringToByteArray(data);
string name = System.Text.Encoding.UTF8.GetString(dBytes);
string pattern = @"([\d\w\p{L} _]+)[\s\S]*$";
var match = Regex.Match(name, pattern, RegexOptions.IgnoreCase);
return match.Groups[1].Value;
} catch (Exception) {
return "";
}
}
public static string getNameFromData(String data) {
return getNameFromData(data, 12);
}
private static int logFromPort = 0;
private static List<string> orderedIds = new List<string>();
private static Dictionary<string, string> players = new Dictionary<string, string>();
private static bool logging = true;
// BITS MAPEADOS
static string criouPartida = @"^0800010046d20203..(.*)$";
static string hostJoinColor = @"(?:0005.{6}000c.{16}|^.{8}0005.{6}8012.*?)0001.*08(..)[01]";
static string acaoRealizada = @"0005.{6}80030002";
static string trocouAparencia = @"0005.{6}80030002(..)(..)(..)..0002";
static string matou = @"0005.{6}80030002(.{2})0c(.{2})"; // Grupo 1: id impostor | Grupo 2: id crewmate
static string reportou = @"0005.{6}80030002(.{2})0[be](.{2})$"; // Grupo 1: id reportou | Grupo 2: num morto
static string talvezEntrou = @"^..................80......";
static string talvezRealmenteEntrou = @"....(..)";
static string next0002 = @"^.*?0002";
static string entrou = @"^(..)..(..)((?:..){charCount})......(.*?\2(?:..)?\3(..).*)$";
static string saiu = @"0005.{6}80040002.{8}010005(..).{8}";
static string saiuInGame = @"0005.{6}80010005(..)010005.{10}";
static string fimVotacao = @"0005.{6}80020002";
static string inicioVotacao = @"0005.{6}80030002.{4}ff";
static string comecou = @"feffffff0f0001.{4}0001.{24}0000000.{146}";
static string ejetadoOuSkippado = @"0005.{6}800f0002.{26}(..).{6}"; // Grupo 1: pessoa ejetada (numero), se g1 == 'ff': ent skippou
static string fimPartida = "0008.{6}800[0123]01$";
static string entrouCamera = "500011380100100"; // EndsWith
static string andar = "00120005"; // StartsWith
private static void device_OnPacketArrival(object sender, CaptureEventArgs e) {
var packet = PacketDotNet.Packet.ParsePacket(e.Packet.LinkLayerType, e.Packet.Data);
var ipPacket = packet.Extract<PacketDotNet.IPPacket>();
var udpPacket = packet.Extract<PacketDotNet.UdpPacket>();
if (udpPacket == null || !udpPacket.HasPayloadData) return;
string data = GetStringFromByteArray(udpPacket.PayloadData);
if (data.Length < 11 || data.StartsWith(andar))
return;
if (logging && udpPacket.SourcePort==logFromPort)
Console.WriteLine("☁️->"+data);
else if (logging && udpPacket.DestinationPort==logFromPort)
Console.WriteLine("☁️<-"+data);
//Console.WriteLine("+"+data); // LOGAR TUDO
if (Regex.IsMatch(data, criouPartida)) {
Console.WriteLine("-- Criou Partida --");
var criou = Regex.Match(data, criouPartida, RegexOptions.IgnoreCase);
string hostname = getNameFromData(criou.Groups[1].Value, 0);
orderedIds.Add("HOST");
players["HOST"] = hostname;
Console.WriteLine($" - {hostname} (HOST)");
logFromPort = udpPacket.SourcePort;
}
else if (Regex.IsMatch(data, hostJoinColor)) {
var hjc = Regex.Match(data, hostJoinColor, RegexOptions.IgnoreCase);
string cor = getCorById(hjc.Groups[1].Value);
Console.WriteLine($"Host entrou com a cor {cor}");
}
else if (Regex.IsMatch(data, saiu) || Regex.IsMatch(data, saiuInGame)) {
Match saiuComId;
string ingame = "";
if (Regex.IsMatch(data, saiu))
saiuComId = Regex.Match(data, saiu, RegexOptions.IgnoreCase);
else {
saiuComId = Regex.Match(data, saiuInGame, RegexOptions.IgnoreCase);
ingame = " - ingame";
}
string id = saiuComId.Groups[1].Value;
string nome;
try { nome = players[id]; } catch (Exception) { nome = players["HOST"]; }
Console.WriteLine($" - {nome} saiu ({id}){ingame}");
try { orderedIds.RemoveAll(playerSaiu=>playerSaiu.Equals(id)); } catch (Exception) {}
}
else if (Regex.IsMatch(data, fimPartida)) {
Console.WriteLine("-- Fim da partida --");
string hostname = players["HOST"];
orderedIds = new List<string>();
players = new Dictionary<string, string>();
orderedIds.Add("HOST");
players["HOST"] = hostname;
}
else if (Regex.IsMatch(data, inicioVotacao)) {
Console.WriteLine("-- Início da Votação --");
}
else if (Regex.IsMatch(data, fimVotacao)) {
Console.WriteLine("-- Fim da Votação --");
}
else if (Regex.IsMatch(data, comecou)) {
Console.WriteLine("-- Partida começou --");
orderedIds = orderedIds.Distinct().ToList();
foreach (string id in orderedIds)
Console.WriteLine(players[id] + "->" + id);
}
else if (data.StartsWith(andar)) {
//Console.WriteLine("Alguém andou");
}
else if (data.EndsWith(entrouCamera)) {
Console.WriteLine("Alguém entrou na camera");
}
else if (Regex.IsMatch(data, ejetadoOuSkippado)) {
var eject = Regex.Match(data, ejetadoOuSkippado, RegexOptions.IgnoreCase);
if (eject.Groups[1].Value=="ff")
Console.WriteLine(" - Votação pulada");
else {
int pos = Convert.ToInt32("0x"+eject.Groups[1].Value, 16);
string userejetado = players[orderedIds[pos]];
Console.WriteLine($" - {userejetado} foi ejetado");
}
}
else if (Regex.IsMatch(data, matou)) {
var kill = Regex.Match(data, matou, RegexOptions.IgnoreCase);
string impostor, impostorId = kill.Groups[1].Value;
string crewmate, crewmateId = kill.Groups[2].Value;
try { impostor = players[impostorId]; } catch (KeyNotFoundException) { impostor = players["HOST"]; }
try { crewmate = players[crewmateId]; } catch (KeyNotFoundException) { crewmate = players["HOST"]; }
Console.WriteLine($" - {impostor}({impostorId}) matou {crewmate}({crewmateId})");
}
else if (Regex.IsMatch(data, reportou)) {
var report = Regex.Match(data, reportou, RegexOptions.IgnoreCase);
string impostor, impostorId = report.Groups[1].Value;
try { impostor = players[impostorId]; } catch (KeyNotFoundException) { impostor = players["HOST"]; }
Console.WriteLine($" - {impostor}({impostorId}) reportou um corpo.");
}
else {
didAdd = false;
if (Regex.IsMatch(data, talvezEntrou)) {
string players = Regex.Split(data, talvezEntrou)[1];
getPlayerFromString(players);
}
if (didAdd) return;
if (Regex.IsMatch(data, trocouAparencia)) {
var troca = Regex.Match(data, trocouAparencia, RegexOptions.IgnoreCase);
string id = troca.Groups[1].Value;
string trocaTipo = troca.Groups[2].Value;
string trocaValor = troca.Groups[3].Value;
if (trocaTipo=="08") { // COR
string cor = getCorById(trocaValor);
string name = getNameFromData(data);
Console.WriteLine($" - {name} trocou a cor para: {cor}");
} else if (trocaTipo=="09") {
//Console.WriteLine(" - Alguem mudou o chapeu");
} else if (trocaTipo=="11") {
//Console.WriteLine(" - Alguem mudou o animal");
} else if (trocaTipo=="0a") {
//Console.WriteLine(" - Alguem mudou o traje");
}
}
else if (Regex.IsMatch(data, acaoRealizada)) {
string res = Regex.Split(data, acaoRealizada)[1];
Console.WriteLine("Ação Não Mapeada: " + res);
}
}
}
public static bool didAdd = false;
public static bool getPlayerFromString(string playersStr) {
var charCount = Regex.Match(playersStr, talvezRealmenteEntrou).Groups[1].Value;
try { Convert.ToInt32("0x"+charCount, 16); } catch(Exception) { return false; }
int qntCharsName = Convert.ToInt32("0x"+charCount, 16);
var pRgxStr = entrou.Replace("charCount", $"{qntCharsName}");
Regex playerRgx = new Regex(pRgxStr, RegexOptions.Compiled);
var player = playerRgx.Match(playersStr);
if (player.Success) {
var id = player.Groups[1].Value;
var name = getNameFromData(player.Groups[3].Value, 0);
var color = player.Groups[5].Value;
var tryContinuing = player.Groups[4].Value;
bool nomeValido = Regex.IsMatch(name.Trim(), @"^[0-9 A-Za-zÀ-ÖØ-öø-ÿ]{1,10}$", RegexOptions.IgnoreCase);
bool corValida = Regex.IsMatch(color.Trim(), @"^0[0-9ab]$", RegexOptions.IgnoreCase);
if (name.Trim()!="" && nomeValido && corValida) {
if (!(orderedIds.Contains(id) && players[id]==name)) {
Console.WriteLine($" - {name} entrou ({id}) com a cor {getCorById(color)}");
orderedIds.Add(id);
players[id] = name;
}
didAdd = true;
}
bool keepTrying = false;
bool worked;
do {
worked = getPlayerFromString(tryContinuing);
keepTrying = Regex.IsMatch(tryContinuing, next0002);
if (keepTrying) tryContinuing = Regex.Split(tryContinuing, next0002)[1];
} while (!worked && keepTrying);
return true;
} else {
if (Regex.IsMatch(playersStr, next0002))
return getPlayerFromString(Regex.Split(playersStr, next0002)[1]);
}
return false;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment