Skip to content

Instantly share code, notes, and snippets.

@DoctorGester
Created April 22, 2016 13:15
Show Gist options
  • Save DoctorGester/a242b85e3b53b37f1ea13595438656da to your computer and use it in GitHub Desktop.
Save DoctorGester/a242b85e3b53b37f1ea13595438656da to your computer and use it in GitHub Desktop.
using System;
using System.IO;
using System.Net;
using System.Security.Cryptography;
using System.Threading;
using SteamKit2;
using SteamKit2.GC;
using SteamKit2.GC.Dota.Internal;
using SteamKit2.Internal;
namespace playerchecker
{
class Program
{
private static string login, pass;
private static ulong modId = 0;
private static SteamClient client;
private static SteamUser user;
private static string authCode, twoFactorAuth;
private static SteamGameCoordinator gc;
private static readonly IPEndPoint server = new IPEndPoint(IPAddress.Parse("208.78.164.10"), 27017);
private static void Main(string[] args)
{
Console.WriteLine("Login");
login = Console.ReadLine();
Console.WriteLine("Password");
pass = Console.ReadLine();
Console.WriteLine("Desired mod id");
ulong.TryParse(Console.ReadLine(), out modId);
client = new SteamClient();
var manager = new CallbackManager(client);
user = client.GetHandler<SteamUser>();
gc = client.GetHandler<SteamGameCoordinator>();
manager.Subscribe<SteamClient.ConnectedCallback>(OnConnected);
manager.Subscribe<SteamClient.DisconnectedCallback>(OnDisconnected);
manager.Subscribe<SteamUser.LoggedOnCallback>(OnLoggedOn);
manager.Subscribe<SteamUser.UpdateMachineAuthCallback>(OnMachineAuth);
manager.Subscribe<SteamGameCoordinator.MessageCallback>(OnGCMessage);
Console.WriteLine("Connecting to Steam...");
client.Connect(server);
while (true)
{
manager.RunWaitCallbacks(TimeSpan.FromSeconds(1));
}
}
private static void OnGCMessage(SteamGameCoordinator.MessageCallback callback)
{
if (callback.EMsg == (uint) EGCBaseClientMsg.k_EMsgGCClientWelcome)
{
RequestPlayerNumbers(1);
}
if (callback.EMsg == (uint) EDOTAGCMsg.k_EMsgGCToClientCustomGamePlayerCountResponse)
{
var response =
Activator.CreateInstance(typeof(ClientGCMsgProtobuf<CMsgGCToClientCustomGamePlayerCountResponse>),
callback.Message) as ClientGCMsgProtobuf<CMsgGCToClientCustomGamePlayerCountResponse>;
var players = response.Body.player_count;
var spectators = response.Body.spectator_count;
Console.WriteLine("Players: {0}, Spectators: {1}", players, spectators);
RequestPlayerNumbers(60);
}
else
{
Console.WriteLine("Got {0} GC message {1}", callback.AppID, GetEMsgName(callback.EMsg));
}
}
private static void RequestPlayerNumbers(int wait)
{
new Thread((() =>
{
Thread.Sleep(TimeSpan.FromSeconds(wait));
var request = new ClientGCMsgProtobuf<CMsgClientToGCCustomGamePlayerCountRequest>(
(uint) EDOTAGCMsg.k_EMsgClientToGCCustomGamePlayerCountRequest
);
request.Body.custom_game_id = modId;
request.SourceJobID = client.GetNextJobID();
gc.Send(request, 570);
})).Start();
}
private static string GetEMsgName(uint eMsg)
{
// first lets try the enum'd emsgs
Type[] eMsgEnums =
{
typeof(SteamKit2.GC.Dota.Internal.EGCBaseMsg),
typeof(SteamKit2.GC.Dota.Internal.EGCBaseClientMsg),
typeof(SteamKit2.GC.Dota.Internal.ESOMsg),
typeof(SteamKit2.GC.Dota.Internal.EGCSystemMsg),
typeof(SteamKit2.GC.Dota.Internal.EGCItemMsg),
typeof(SteamKit2.GC.Dota.Internal.EGCToGCMsg),
typeof(SteamKit2.GC.Dota.Internal.EDOTAGCMsg),
typeof(SteamKit2.GC.TF2.Internal.EGCBaseMsg),
typeof(SteamKit2.GC.TF2.Internal.ETFGCMsg),
};
foreach (var enumType in eMsgEnums)
{
if (Enum.IsDefined(enumType, (int) eMsg))
return Enum.GetName(enumType, (int) eMsg);
}
// no dice, we can only use the uint
return eMsg.ToString();
}
private static void OnDisconnected(SteamClient.DisconnectedCallback obj)
{
Console.WriteLine("Disconnected from Steam, reconnecting in 5...");
Thread.Sleep(TimeSpan.FromSeconds(5));
client.Connect(server);
}
private static void OnLoggedOn(SteamUser.LoggedOnCallback callback)
{
Console.WriteLine("Login callback: " + callback.Result.ToString());
var isSteamGuard = callback.Result == EResult.AccountLogonDenied;
var is2FA = callback.Result == EResult.AccountLoginDeniedNeedTwoFactor;
if (isSteamGuard || is2FA)
{
if (is2FA)
{
Console.Write("Please enter your 2 factor auth code from your authenticator app: ");
twoFactorAuth = Console.ReadLine();
}
else
{
Console.Write("Please enter the auth code sent to the email at {0}: ", callback.EmailDomain);
authCode = Console.ReadLine();
}
return;
}
Console.WriteLine("Logged in");
RequestGameData();
}
private static void RequestGameData()
{
var playGame = new ClientMsgProtobuf<CMsgClientGamesPlayed>(EMsg.ClientGamesPlayed);
playGame.Body.games_played.Add(new CMsgClientGamesPlayed.GamePlayed
{
game_id = new GameID(570),
});
Thread.Sleep(TimeSpan.FromSeconds(3));
client.Send(playGame);
var hello = new ClientGCMsgProtobuf<CMsgClientHello>((uint) EGCBaseClientMsg.k_EMsgGCClientHello);
hello.Body.engine = ESourceEngine.k_ESE_Source2;
gc.Send(hello, 570);
}
private static void OnConnected(SteamClient.ConnectedCallback obj)
{
Console.WriteLine("Connected to Steam! Logging in");
byte[] sentryHash = null;
if (File.Exists("sentry.bin"))
{
Console.WriteLine("Found a sentry file");
// if we have a saved sentry file, read and sha-1 hash it
var sentryFile = File.ReadAllBytes("sentry.bin");
sentryHash = CryptoHelper.SHAHash(sentryFile);
}
user.LogOn(new SteamUser.LogOnDetails
{
Username = login,
Password = pass,
AuthCode = authCode,
SentryFileHash = sentryHash,
TwoFactorCode = twoFactorAuth
});
}
static void OnMachineAuth(SteamUser.UpdateMachineAuthCallback callback)
{
Console.WriteLine("Updating sentryfile...");
// write out our sentry file
// ideally we'd want to write to the filename specified in the callback
// but then this sample would require more code to find the correct sentry file to read during logon
// for the sake of simplicity, we'll just use "sentry.bin"
int fileSize;
byte[] sentryHash;
using (var fs = File.Open("sentry.bin", FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
fs.Seek(callback.Offset, SeekOrigin.Begin);
fs.Write(callback.Data, 0, callback.BytesToWrite);
fileSize = (int) fs.Length;
fs.Seek(0, SeekOrigin.Begin);
using (var sha = new SHA1CryptoServiceProvider())
{
sentryHash = sha.ComputeHash(fs);
}
}
// inform the steam servers that we're accepting this sentry file
user.SendMachineAuthResponse(new SteamUser.MachineAuthDetails
{
JobID = callback.JobID,
FileName = callback.FileName,
BytesWritten = callback.BytesToWrite,
FileSize = fileSize,
Offset = callback.Offset,
Result = EResult.OK,
LastError = 0,
OneTimePassword = callback.OneTimePassword,
SentryFileHash = sentryHash,
});
Console.WriteLine("Done!");
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment