Created
May 8, 2021 22:32
-
-
Save Seeker14491/f714985cb594adf99f7a99c509ad0971 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.IO; | |
using System.Security.Cryptography; | |
using System.Threading; | |
using SteamKit2; | |
namespace SteamKit2Exploration | |
{ | |
class Program | |
{ | |
static SteamClient steamClient; | |
static CallbackManager manager; | |
static SteamUser steamUser; | |
static SteamUserStats steamUserStats; | |
static bool isRunning; | |
static string user, pass; | |
static string authCode, twoFactorAuth; | |
static void Main( string[] args ) | |
{ | |
if ( args.Length < 2 ) | |
{ | |
Console.WriteLine( "No username and password specified!" ); | |
return; | |
} | |
// save our logon details | |
user = args[ 0 ]; | |
pass = args[ 1 ]; | |
// create our steamclient instance | |
steamClient = new SteamClient(); | |
// create the callback manager which will route callbacks to function calls | |
manager = new CallbackManager( steamClient ); | |
// get the steamuser handler, which is used for logging on after successfully connecting | |
steamUser = steamClient.GetHandler<SteamUser>(); | |
steamUserStats = steamClient.GetHandler<SteamUserStats>(); | |
// register a few callbacks we're interested in | |
// these are registered upon creation to a callback manager, which will then route the callbacks | |
// to the functions specified | |
manager.Subscribe<SteamClient.ConnectedCallback>( OnConnected ); | |
manager.Subscribe<SteamClient.DisconnectedCallback>( OnDisconnected ); | |
manager.Subscribe<SteamUser.LoggedOnCallback>( OnLoggedOn ); | |
manager.Subscribe<SteamUser.LoggedOffCallback>( OnLoggedOff ); | |
// this callback is triggered when the steam servers wish for the client to store the sentry file | |
manager.Subscribe<SteamUser.UpdateMachineAuthCallback>( OnMachineAuth ); | |
manager.Subscribe<SteamUserStats.FindOrCreateLeaderboardCallback>(OnFindOrCreateLeaderboard); | |
isRunning = true; | |
Console.WriteLine( "Connecting to Steam..." ); | |
// initiate the connection | |
steamClient.Connect(); | |
// create our callback handling loop | |
while ( isRunning ) | |
{ | |
// in order for the callbacks to get routed, they need to be handled by the manager | |
manager.RunWaitCallbacks( TimeSpan.FromSeconds( 1 ) ); | |
} | |
} | |
private static void OnFindOrCreateLeaderboard(SteamUserStats.FindOrCreateLeaderboardCallback callback) | |
{ | |
if (callback.Result == EResult.OK) | |
{ | |
Console.WriteLine($"Found leaderboard with {callback.EntryCount} entries."); | |
} | |
} | |
static void OnConnected( SteamClient.ConnectedCallback callback ) | |
{ | |
Console.WriteLine( "Connected to Steam! Logging in '{0}'...", user ); | |
byte[] sentryHash = null; | |
if ( File.Exists( "sentry.bin" ) ) | |
{ | |
// if we have a saved sentry file, read and sha-1 hash it | |
byte[] sentryFile = File.ReadAllBytes( "sentry.bin" ); | |
sentryHash = CryptoHelper.SHAHash( sentryFile ); | |
} | |
steamUser.LogOn( new SteamUser.LogOnDetails | |
{ | |
Username = user, | |
Password = pass, | |
// in this sample, we pass in an additional authcode | |
// this value will be null (which is the default) for our first logon attempt | |
AuthCode = authCode, | |
// if the account is using 2-factor auth, we'll provide the two factor code instead | |
// this will also be null on our first logon attempt | |
TwoFactorCode = twoFactorAuth, | |
// our subsequent logons use the hash of the sentry file as proof of ownership of the file | |
// this will also be null for our first (no authcode) and second (authcode only) logon attempts | |
SentryFileHash = sentryHash, | |
} ); | |
} | |
static void OnDisconnected( SteamClient.DisconnectedCallback callback ) | |
{ | |
// after recieving an AccountLogonDenied, we'll be disconnected from steam | |
// so after we read an authcode from the user, we need to reconnect to begin the logon flow again | |
Console.WriteLine( "Disconnected from Steam, reconnecting in 5..." ); | |
Thread.Sleep( TimeSpan.FromSeconds( 5 ) ); | |
steamClient.Connect(); | |
} | |
static void OnLoggedOn( SteamUser.LoggedOnCallback callback ) | |
{ | |
bool isSteamGuard = callback.Result == EResult.AccountLogonDenied; | |
bool is2FA = callback.Result == EResult.AccountLoginDeniedNeedTwoFactor; | |
if ( isSteamGuard || is2FA ) | |
{ | |
Console.WriteLine( "This account is SteamGuard protected!" ); | |
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; | |
} | |
if ( callback.Result != EResult.OK ) | |
{ | |
Console.WriteLine( "Unable to logon to Steam: {0} / {1}", callback.Result, callback.ExtendedResult ); | |
isRunning = false; | |
return; | |
} | |
Console.WriteLine( "Successfully logged on!" ); | |
var result = steamUserStats.FindLeaderboard(233610, "Inferno_1_Stable").GetAwaiter(); | |
} | |
static void OnLoggedOff( SteamUser.LoggedOffCallback callback ) | |
{ | |
Console.WriteLine( "Logged off of Steam: {0}", callback.Result ); | |
} | |
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 = SHA1.Create() ) | |
{ | |
sentryHash = sha.ComputeHash( fs ); | |
} | |
} | |
// inform the steam servers that we're accepting this sentry file | |
steamUser.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