@@ -24,7 +24,7 @@ public override bool CanInvoke(ChatCommandContext context)
2424
2525 public override void Invoke ( ChatCommandContext context )
2626 {
27- var t = Arguments . Count == 0 ? "" : Arguments [ 0 ] ; // target
27+ var t = Arguments . Count == 0 ? string . Empty : Arguments [ 0 ] ; // target
2828 string r ; // reply
2929
3030 if ( t . Length == 0 || ! Battlenet . Common . GetClientByOnlineName ( t , out var target ) || target == null )
@@ -38,15 +38,6 @@ public override void Invoke(ChatCommandContext context)
3838 Arguments . RemoveAt ( 0 ) ; // remove target
3939 // Calculates and removes (target+' ') from (raw) which prints into (newRaw):
4040 RawBuffer = RawBuffer [ ( Encoding . UTF8 . GetByteCount ( t ) + ( Arguments . Count > 0 ? 1 : 0 ) ) ..] ;
41- var type = string . Join ( ' ' , Arguments ) ;
42-
43- if ( string . IsNullOrEmpty ( type ) )
44- {
45- r = Resources . AdminBotFuckeryCommandInvalid ;
46- foreach ( var line in r . Split ( Environment . NewLine ) )
47- new ChatEvent ( ChatEvent . EventIds . EID_ERROR , context . GameState . ChannelFlags , context . GameState . Client . RemoteIPAddress , context . GameState . Ping , context . GameState . OnlineName , line ) . WriteTo ( context . GameState . Client ) ;
48- return ;
49- }
5041
5142 var realmName = Settings . GetString ( new string [ ] { "battlenet" , "realm" , "name" } , Resources . Battlenet ) ;
5243 var targetEnv = new Dictionary < string , string > ( )
@@ -65,33 +56,85 @@ public override void Invoke(ChatCommandContext context)
6556 { "username" , target . OnlineName } ,
6657 { "userName" , target . OnlineName } ,
6758 } ;
68- var env = targetEnv . Concat ( context . Environment ) ;
6959
70- SID_AUTH_CHECK . Statuses status = type . ToLowerInvariant ( ) . Replace ( " " , string . Empty ) switch
71- {
72- "bannedkey" => SID_AUTH_CHECK . Statuses . GameKeyBanned ,
73- "bannedkey2" => SID_AUTH_CHECK . Statuses . GameKeyBanned | SID_AUTH_CHECK . Statuses . GameKeyExpansion ,
74- "inusekey" => SID_AUTH_CHECK . Statuses . GameKeyInUse ,
75- "inusekey2" => SID_AUTH_CHECK . Statuses . GameKeyInUse | SID_AUTH_CHECK . Statuses . GameKeyExpansion ,
76- "invalidkey" => SID_AUTH_CHECK . Statuses . GameKeyInvalid ,
77- "invalidkey2" => SID_AUTH_CHECK . Statuses . GameKeyInvalid | SID_AUTH_CHECK . Statuses . GameKeyExpansion ,
78- "invalidversion" => SID_AUTH_CHECK . Statuses . InvalidVersion ,
79- "success" => SID_AUTH_CHECK . Statuses . Success ,
80- "toonew" => SID_AUTH_CHECK . Statuses . VersionTooNew ,
81- "tooold" => SID_AUTH_CHECK . Statuses . VersionTooOld ,
82- "wronggamekey" => SID_AUTH_CHECK . Statuses . GameKeyProductMismatch ,
83- "wronggamekey2" => SID_AUTH_CHECK . Statuses . GameKeyProductMismatch | SID_AUTH_CHECK . Statuses . GameKeyExpansion ,
84- _ => SID_AUTH_CHECK . Statuses . InvalidVersion ,
85- } ;
60+ var random = new Random ( ) ;
61+ int choice1 = ( Arguments . Count > 0 ? int . Parse ( Arguments [ 0 ] ) : random . Next ( 0 , 4 ) ) ;
8662
87- new SID_AUTH_CHECK ( ) . Invoke ( new MessageContext ( target . Client , MessageDirection . ServerToClient , new Dictionary < string , dynamic > ( ) {
88- { "status" , status } , { "info" , Array . Empty < byte > ( ) }
89- } ) ) ;
63+ switch ( choice1 )
64+ {
65+ case 0 : // What if the server sent client out-of-sequence spoofed SID_AUTH_CHECK result?
66+ {
67+ int choice2 = ( Arguments . Count > 1 ? int . Parse ( Arguments [ 1 ] ) : random . Next ( 0 , 12 ) ) ;
68+ context . Environment [ "message" ] = "SID_AUTH_CHECK" ;
69+ SID_AUTH_CHECK . Statuses status = choice2 switch
70+ {
71+ 0 => SID_AUTH_CHECK . Statuses . Success ,
72+ 1 => SID_AUTH_CHECK . Statuses . GameKeyBanned ,
73+ 2 => SID_AUTH_CHECK . Statuses . GameKeyBanned | SID_AUTH_CHECK . Statuses . GameKeyExpansion ,
74+ 3 => SID_AUTH_CHECK . Statuses . GameKeyInUse ,
75+ 4 => SID_AUTH_CHECK . Statuses . GameKeyInUse | SID_AUTH_CHECK . Statuses . GameKeyExpansion ,
76+ 5 => SID_AUTH_CHECK . Statuses . GameKeyInvalid ,
77+ 6 => SID_AUTH_CHECK . Statuses . GameKeyInvalid | SID_AUTH_CHECK . Statuses . GameKeyExpansion ,
78+ 7 => SID_AUTH_CHECK . Statuses . GameKeyProductMismatch ,
79+ 8 => SID_AUTH_CHECK . Statuses . GameKeyProductMismatch | SID_AUTH_CHECK . Statuses . GameKeyExpansion ,
80+ 9 => SID_AUTH_CHECK . Statuses . InvalidVersion ,
81+ 10 => SID_AUTH_CHECK . Statuses . VersionTooNew ,
82+ 11 => SID_AUTH_CHECK . Statuses . VersionTooOld ,
83+ _ => SID_AUTH_CHECK . Statuses . InvalidVersion ,
84+ } ;
85+ new SID_AUTH_CHECK ( ) . Invoke ( new MessageContext ( target . Client , MessageDirection . ServerToClient , new Dictionary < string , dynamic > ( ) {
86+ { "status" , status } , { "info" , Array . Empty < byte > ( ) }
87+ } ) ) ;
88+ break ;
89+ }
90+ case 1 : // What if server sent client unsolicited SID_QUERYREALMS2 with fake realm names?
91+ {
92+ context . Environment [ "message" ] = "SID_QUERYREALMS2" ;
93+ var rand20HumanBytes = new byte [ 20 ] ;
94+ for ( int i = 0 ; i < rand20HumanBytes . Length ; i ++ ) rand20HumanBytes [ i ] = ( byte ) random . Next ( ( byte ) 'A' , 1 + ( byte ) 'Z' ) ;
95+ new SID_QUERYREALMS2 ( ) . Invoke ( new MessageContext ( target . Client , MessageDirection . ServerToClient , new Dictionary < string , dynamic > ( ) {
96+ { "realms" , new Dictionary < byte [ ] , byte [ ] > ( ) { { Encoding . UTF8 . GetBytes ( "Botfuckery" ) , rand20HumanBytes } } }
97+ } ) ) ;
98+ break ;
99+ }
100+ case 2 : // What if server sent client out-of-sequence spoofed SID_LOGONRESPONSE2 result?
101+ {
102+ int choice2 = ( Arguments . Count > 1 ? int . Parse ( Arguments [ 1 ] ) : random . Next ( 0 , 4 ) ) ;
103+ context . Environment [ "message" ] = "SID_LOGONRESPONSE2" ;
104+ SID_LOGONRESPONSE2 . Statuses status = choice2 switch
105+ {
106+ 0 => SID_LOGONRESPONSE2 . Statuses . Success ,
107+ 1 => SID_LOGONRESPONSE2 . Statuses . BadPassword ,
108+ 2 => SID_LOGONRESPONSE2 . Statuses . AccountNotFound ,
109+ 3 => SID_LOGONRESPONSE2 . Statuses . AccountClosed ,
110+ _ => SID_LOGONRESPONSE2 . Statuses . AccountNotFound ,
111+ } ;
112+ var rand20HumanBytes = new byte [ 20 ] ;
113+ for ( int i = 0 ; i < rand20HumanBytes . Length ; i ++ ) rand20HumanBytes [ i ] = ( byte ) random . Next ( ( byte ) 'A' , 1 + ( byte ) 'Z' ) ;
114+ byte [ ] info = status == SID_LOGONRESPONSE2 . Statuses . AccountClosed ? rand20HumanBytes : Array . Empty < byte > ( ) ;
115+ new SID_LOGONRESPONSE2 ( ) . Invoke ( new MessageContext ( target . Client , MessageDirection . ServerToClient , new Dictionary < string , dynamic > ( ) {
116+ { "status" , status } , { "info" , info }
117+ } ) ) ;
118+ break ;
119+ }
120+ case 3 : // What if server asked for some registry info?
121+ {
122+ context . Environment [ "message" ] = "SID_REGISTRY" ;
123+ new SID_REGISTRY ( ) . Invoke ( new MessageContext ( target . Client , MessageDirection . ServerToClient , new Dictionary < string , dynamic > ( ) {
124+ { "cookie" , ( UInt32 ) random . Next ( - 0x80000000 , 0x7FFFFFFF ) } ,
125+ { "hiveKeyId" , ( UInt32 ) 0x80000001 } , // HKEY_CURRENT_USER
126+ { "keyPath" , ( string ) "Software\\ Battle.net\\ Configuration" } ,
127+ { "keyName" , ( string ) "Battle.net gateways" } ,
128+ } ) ) ;
129+ break ;
130+ }
131+ }
90132
91133 r = Resources . AdminBotFuckeryCommand ;
92- foreach ( var kv in env ) r = r . Replace ( "{" + kv . Key + "}" , kv . Value ) ;
134+ foreach ( var kv in targetEnv . Concat ( context . Environment ) ) r = r . Replace ( "{" + kv . Key + "}" , kv . Value ) ;
93135 foreach ( var line in r . Split ( Battlenet . Common . NewLine ) )
94136 new ChatEvent ( ChatEvent . EventIds . EID_INFO , context . GameState . ChannelFlags , context . GameState . Client . RemoteIPAddress , context . GameState . Ping , context . GameState . OnlineName , line ) . WriteTo ( context . GameState . Client ) ;
95137 }
96138 }
97139}
140+
0 commit comments