Created
January 16, 2019 22:42
-
-
Save nathan130200/715243c6d4eb2d4894b6675c96527a71 to your computer and use it in GitHub Desktop.
WarfaceBot in C# with UseProtect.
This file contains hidden or 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 agsXMPP; | |
using agsXMPP.protocol.tls; | |
using agsXMPP.Xml; | |
using agsXMPP.Xml.Dom; | |
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Net; | |
using System.Net.Security; | |
using System.Net.Sockets; | |
using System.Security.Cryptography.X509Certificates; | |
using System.Text; | |
using System.Threading; | |
using System.Threading.Tasks; | |
using URI = agsXMPP.Uri; | |
namespace Warface | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
var conn = new WarfaceConnection("game.warface.levelupgames.com.br"); | |
conn.Open(); | |
while (true) | |
{ | |
} | |
} | |
} | |
public class WarfaceSession | |
{ | |
public string Id { get; set; } | |
public bool IsAuthenticated { get; private set; } | |
public bool IsTlsStarted { get; private set; } | |
public bool IsBinded { get; private set; } | |
public Jid Jid { get; private set; } | |
public void Authenticate(string username, string server) | |
{ | |
this.Jid = new Jid(username, server, "GameClient"); | |
this.IsAuthenticated = true; | |
} | |
public void Bind(string resource) | |
{ | |
this.Jid.Resource = resource; | |
this.IsBinded = true; | |
} | |
public void StartTls() | |
{ | |
this.IsTlsStarted = true; | |
} | |
} | |
public class WarfaceConnection | |
{ | |
public WarfaceSession Session { get; private set; } | |
internal TcpClient _client; | |
internal string _host; | |
internal int _port; | |
internal Stream _stream; | |
internal StreamParser _parser; | |
internal string _domain = "warface"; | |
internal bool _use_protect = true; | |
internal volatile bool _are_write = false; | |
internal volatile bool _are_read = false; | |
internal volatile bool _should_read = true; | |
internal volatile bool _closed = false; | |
public WarfaceConnection(string host, int port = 5222) | |
{ | |
_host = host; | |
_port = port; | |
_client = new TcpClient(); | |
_parser = new StreamParser(); | |
_parser.OnStreamStart += OnStreamStart; | |
_parser.OnStreamElement += OnStreamElement; | |
_parser.OnStreamEnd += OnStreamEnd; | |
_parser.OnStreamError += OnError; | |
_parser.OnError += OnError; | |
this.Session = new WarfaceSession(); | |
} | |
public void Open() | |
{ | |
_client.BeginConnect(Dns.GetHostAddresses(_host), _port, OnConnect, null); | |
} | |
void OnStreamStart(object sender, Node node) | |
{ | |
Console.WriteLine("stream start."); | |
var st = ((agsXMPP.protocol.Stream)node); | |
Session.Id = st.Attribute("id"); | |
} | |
void OnStreamEnd(object sender, Node node) | |
{ | |
Console.WriteLine("stream end."); | |
Close(); | |
} | |
bool _requested_tls; | |
void OnStreamElement(object sender, Node node) | |
{ | |
Console.WriteLine("recv <<:\n{0:I}\n", node); | |
if(node is Element element) | |
{ | |
if(element.TagName == "features" && element.Prefix == "stream") | |
{ | |
var has_starttls = element.SelectSingleElement("starttls", URI.TLS) != null; | |
if (has_starttls) | |
{ | |
Send(new StartTls()); | |
_requested_tls = true; | |
} | |
} | |
if(element is Proceed _) | |
{ | |
while (_are_write) ; | |
_should_read = false; | |
this.StartTls(); | |
} | |
} | |
} | |
void OnError(object sender, Exception ex) | |
{ | |
Console.WriteLine(ex); | |
} | |
public void Send(Element element) | |
=> Send(element.ToString()); | |
public void Send(string raw) | |
=> Send(Encoding.UTF8.GetBytes(raw)); | |
public void Send(byte[] data) | |
{ | |
while (_are_write) ; | |
if (!_use_protect) | |
{ | |
_stream.BeginWrite(data, 0, data.Length, OnWrite, null); | |
} | |
else | |
{ | |
using (var ms = new MemoryStream()) | |
using (var bw = new BinaryWriter(ms)) | |
{ | |
bw.Write(MAGIC); | |
bw.Write(data.LongLength); | |
bw.Write(data, 0, data.Length); | |
_stream.BeginWrite(data, 0, data.Length, OnWrite, null); | |
} | |
} | |
} | |
public void Close() | |
{ | |
if (_closed) | |
return; | |
while (_are_write) ; | |
_are_write = false; | |
_should_read = false; | |
_closed = true; | |
_stream.Dispose(); | |
_stream = null; | |
_client.Close(); | |
_client.Dispose(); | |
_client = null; | |
} | |
public void Reset() | |
{ | |
_should_read = true; | |
_parser.Reset(); | |
Console.WriteLine("reset."); | |
this.ReadAsync(); | |
} | |
public void StartTls() | |
{ | |
_should_read = false; | |
while (_are_write && _are_read) ; | |
_stream = new SslStream(_stream, true, (sender, cert, chain, policy) => | |
{ | |
Console.WriteLine("cert <<@<< {0}, {1} ({2}).", cert.Subject, cert.GetKeyAlgorithm(), policy); | |
return true; | |
}); | |
((SslStream)_stream).AuthenticateAsClient(_host); | |
Session.StartTls(); | |
Reset(); | |
} | |
void OnConnect(IAsyncResult ar) | |
{ | |
_stream = _client.GetStream(); | |
this.SendStreamStart(); | |
this.ReadAsync(); | |
} | |
void SendStreamStart() | |
{ | |
var stbl = new StringBuilder() | |
.Append("<?xml version='1.0'?>") | |
.AppendFormat("<stream:stream to='{0}' ", _domain) | |
.Append("version='1.0' ") | |
.Append("xml:lang='en' ") | |
.AppendFormat("xmlns='{0}' ", URI.CLIENT) | |
.AppendFormat("xmlns:stream='{0}'>", URI.STREAM); | |
Console.WriteLine("send >>:\n{0:I}\n", stbl); | |
Send(stbl.ToString()); | |
} | |
void ReadAsync() | |
{ | |
while (_are_read) ; | |
if (!_use_protect) | |
{ | |
var buf = new byte[1024]; | |
_stream.BeginRead(buf, 0, buf.Length, OnRead, buf); | |
} | |
else | |
{ | |
var protect = new OnlineProtect(); | |
_stream.BeginRead(protect.Header, 0, protect.Header.Length, OnRead, protect); | |
} | |
} | |
void OnWrite(IAsyncResult ar) | |
{ | |
_stream.EndWrite(ar); | |
_are_write = false; | |
} | |
void OnRead(IAsyncResult ar) | |
{ | |
var read = _stream.EndRead(ar); | |
_are_read = false; | |
if (read > 0) | |
{ | |
if (!_use_protect) | |
{ | |
var buf = (byte[])ar.AsyncState; | |
if (read > 0) | |
{ | |
_parser.Push(buf, 0, read); | |
if (_should_read) | |
{ | |
_stream.BeginRead(buf, 0, buf.Length, OnRead, buf); | |
_are_read = true; | |
} | |
else | |
return; | |
} | |
} | |
else | |
{ | |
var protect = (OnlineProtect)ar.AsyncState; | |
if (protect.IsProtected) | |
{ | |
using (var ms = new MemoryStream(protect.Header)) | |
using (var br = new BinaryReader(ms)) | |
{ | |
var magic = br.ReadUInt32(); | |
var size = br.ReadInt64(); | |
if (magic != MAGIC) | |
throw new InvalidDataException($"Must be valid magic {MAGIC}"); | |
protect.IsProtected = false; | |
protect.Buffer = new byte[size]; | |
Console.WriteLine("header <<: {0} # {1}\n", magic, size); | |
if (_should_read) | |
{ | |
_stream.BeginRead(protect.Buffer, 0, protect.Buffer.Length, OnRead, protect); | |
_are_read = true; | |
} | |
} | |
} | |
else | |
{ | |
_parser.Push(protect.Buffer, 0, protect.Buffer.Length); | |
if (_should_read) | |
{ | |
protect = new OnlineProtect(); | |
_stream.BeginRead(protect.Header, 0, protect.Header.Length, OnRead, protect); | |
_are_read = true; | |
} | |
} | |
} | |
} | |
else | |
{ | |
Close(); | |
} | |
} | |
public const uint MAGIC = 4277001901; | |
} | |
public class OnlineProtect | |
{ | |
public bool IsProtected { get; set; } = true; | |
public byte[] Header { get; set; } = new byte[12]; | |
public byte[] Buffer { get; set; } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment