Advertisement
Guest User

Untitled

a guest
May 15th, 2016
220
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.01 KB | None | 0 0
  1. using System;
  2. using System.IO;
  3. using System.Security.Cryptography;
  4. using System.Threading;
  5.  
  6. using SteamKit2;
  7.  
  8. //
  9. // Sample 5: SteamGuard
  10. //
  11. // this sample goes into detail for how to handle steamguard protected accounts and how to login to them
  12. //
  13. // SteamGuard works by enforcing a two factor authentication scheme
  14. // upon first logon to an account with SG enabled, the steam server will email an authcode to the validated address of the account
  15. // this authcode token can be used as the second factor during logon, but the token has a limited time span in which it is valid
  16. //
  17. // after a client logs on using the authcode, the steam server will generate a blob of random data that the client stores called a "sentry file"
  18. // this sentry file is then used in all subsequent logons as the second factor
  19. // ownership of this file provides proof that the machine being used to logon is owned by the client in question
  20. //
  21. // the usual login flow is thus:
  22. // 1. connect to the server
  23. // 2. logon to account with only username and password
  24. // at this point, if the account is steamguard protected, the LoggedOnCallback will have a result of AccountLogonDenied
  25. // the server will disconnect the client and email the authcode
  26. //
  27. // the login flow must then be restarted:
  28. // 1. connect to server
  29. // 2. logon to account using username, password, and authcode
  30. // at this point, login wil succeed and a UpdateMachineAuthCallback callback will be posted with the sentry file data from the steam server
  31. // the client will save the file, and reply to the server informing that it has accepted the sentry file
  32. //
  33. // all subsequent logons will use this flow:
  34. // 1. connect to server
  35. // 2. logon to account using username, password, and sha-1 hash of the sentry file
  36.  
  37.  
  38. namespace Mariobot
  39. {
  40. class Program
  41. {
  42. static SteamClient steamClient;
  43. static CallbackManager manager;
  44.  
  45. static SteamUser steamUser;
  46.  
  47. static bool isRunning;
  48.  
  49. static string user, pass;
  50. static string authCode, twoFactorAuth;
  51.  
  52.  
  53. static void Main(string[] args)
  54. {
  55. if (args.Length < 2)
  56. {
  57. Console.WriteLine("Sample5: No username and password specified!");
  58. return;
  59. }
  60.  
  61. // save our logon details
  62. user = args[0];
  63. pass = args[1];
  64.  
  65. // create our steamclient instance
  66. steamClient = new SteamClient();
  67. // create the callback manager which will route callbacks to function calls
  68. manager = new CallbackManager(steamClient);
  69.  
  70. // get the steamuser handler, which is used for logging on after successfully connecting
  71. steamUser = steamClient.GetHandler<SteamUser>();
  72.  
  73. // register a few callbacks we're interested in
  74. // these are registered upon creation to a callback manager, which will then route the callbacks
  75. // to the functions specified
  76. manager.Subscribe<SteamClient.ConnectedCallback>(OnConnected);
  77. manager.Subscribe<SteamClient.DisconnectedCallback>(OnDisconnected);
  78.  
  79. manager.Subscribe<SteamUser.LoggedOnCallback>(OnLoggedOn);
  80. manager.Subscribe<SteamUser.LoggedOffCallback>(OnLoggedOff);
  81.  
  82. // this callback is triggered when the steam servers wish for the client to store the sentry file
  83. manager.Subscribe<SteamUser.UpdateMachineAuthCallback>(OnMachineAuth);
  84.  
  85. isRunning = true;
  86.  
  87. Console.WriteLine("Connecting to Steam...");
  88.  
  89. // initiate the connection
  90. steamClient.Connect();
  91.  
  92. // create our callback handling loop
  93. while (isRunning)
  94. {
  95. // in order for the callbacks to get routed, they need to be handled by the manager
  96. manager.RunWaitCallbacks(TimeSpan.FromSeconds(1));
  97. }
  98. }
  99.  
  100. static void OnConnected(SteamClient.ConnectedCallback callback)
  101. {
  102. if (callback.Result != EResult.OK)
  103. {
  104. Console.WriteLine("Unable to connect to Steam: {0}", callback.Result);
  105.  
  106. isRunning = false;
  107. return;
  108. }
  109.  
  110. Console.WriteLine("Connected to Steam! Logging in '{0}'...", user);
  111.  
  112. byte[] sentryHash = null;
  113. if (File.Exists("sentry.bin"))
  114. {
  115. // if we have a saved sentry file, read and sha-1 hash it
  116. byte[] sentryFile = File.ReadAllBytes("sentry.bin");
  117. sentryHash = CryptoHelper.SHAHash(sentryFile);
  118. }
  119.  
  120. steamUser.LogOn(new SteamUser.LogOnDetails
  121. {
  122. Username = user,
  123. Password = pass,
  124.  
  125. // in this sample, we pass in an additional authcode
  126. // this value will be null (which is the default) for our first logon attempt
  127. AuthCode = authCode,
  128.  
  129. // if the account is using 2-factor auth, we'll provide the two factor code instead
  130. // this will also be null on our first logon attempt
  131. TwoFactorCode = twoFactorAuth,
  132.  
  133. // our subsequent logons use the hash of the sentry file as proof of ownership of the file
  134. // this will also be null for our first (no authcode) and second (authcode only) logon attempts
  135. SentryFileHash = sentryHash,
  136. });
  137. }
  138.  
  139. static void OnDisconnected(SteamClient.DisconnectedCallback callback)
  140. {
  141. // after recieving an AccountLogonDenied, we'll be disconnected from steam
  142. // so after we read an authcode from the user, we need to reconnect to begin the logon flow again
  143.  
  144. Console.WriteLine("Disconnected from Steam, reconnecting in 5...");
  145.  
  146. Thread.Sleep(TimeSpan.FromSeconds(5));
  147.  
  148. steamClient.Connect();
  149. }
  150.  
  151. static void OnLoggedOn(SteamUser.LoggedOnCallback callback)
  152. {
  153. bool isSteamGuard = callback.Result == EResult.AccountLogonDenied;
  154. bool is2FA = callback.Result == EResult.AccountLoginDeniedNeedTwoFactor;
  155.  
  156. if (isSteamGuard || is2FA)
  157. {
  158. Console.WriteLine("This account is SteamGuard protected!");
  159.  
  160. if (is2FA)
  161. {
  162. Console.Write("Please enter your 2 factor auth code from your authenticator app: ");
  163. twoFactorAuth = Console.ReadLine();
  164. }
  165. else
  166. {
  167. Console.Write("Please enter the auth code sent to the email at {0}: ", callback.EmailDomain);
  168. authCode = Console.ReadLine();
  169. }
  170.  
  171. return;
  172. }
  173.  
  174. if (callback.Result != EResult.OK)
  175. {
  176. Console.WriteLine("Unable to logon to Steam: {0} / {1}", callback.Result, callback.ExtendedResult);
  177.  
  178. isRunning = false;
  179. return;
  180. }
  181.  
  182. Console.WriteLine("Successfully logged on!");
  183.  
  184. // at this point, we'd be able to perform actions on Steam
  185. }
  186.  
  187. static void OnLoggedOff(SteamUser.LoggedOffCallback callback)
  188. {
  189. Console.WriteLine("Logged off of Steam: {0}", callback.Result);
  190. }
  191.  
  192. static void OnMachineAuth(SteamUser.UpdateMachineAuthCallback callback)
  193. {
  194. Console.WriteLine("Updating sentryfile...");
  195.  
  196. // write out our sentry file
  197. // ideally we'd want to write to the filename specified in the callback
  198. // but then this sample would require more code to find the correct sentry file to read during logon
  199. // for the sake of simplicity, we'll just use "sentry.bin"
  200.  
  201. int fileSize;
  202. byte[] sentryHash;
  203. using (var fs = File.Open("sentry.bin", FileMode.OpenOrCreate, FileAccess.ReadWrite))
  204. {
  205. fs.Seek(callback.Offset, SeekOrigin.Begin);
  206. fs.Write(callback.Data, 0, callback.BytesToWrite);
  207. fileSize = (int)fs.Length;
  208.  
  209. fs.Seek(0, SeekOrigin.Begin);
  210. using (var sha = new SHA1CryptoServiceProvider())
  211. {
  212. sentryHash = sha.ComputeHash(fs);
  213. }
  214. }
  215.  
  216. // inform the steam servers that we're accepting this sentry file
  217. steamUser.SendMachineAuthResponse(new SteamUser.MachineAuthDetails
  218. {
  219. JobID = callback.JobID,
  220.  
  221. FileName = callback.FileName,
  222.  
  223. BytesWritten = callback.BytesToWrite,
  224. FileSize = fileSize,
  225. Offset = callback.Offset,
  226.  
  227. Result = EResult.OK,
  228. LastError = 0,
  229.  
  230. OneTimePassword = callback.OneTimePassword,
  231.  
  232. SentryFileHash = sentryHash,
  233. });
  234.  
  235. Console.WriteLine("Done!");
  236. }
  237. }
  238. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement