- Joined
- Jan 5, 2009
- Messages
- 343
- Reaction score
- 391
To begin, create a new standard Console Application project for C# in VS2010.
File -> New -> Project -> Visual C# -> Windows -> Console Application.
Name the project 'GlobalMan Proxy'.
Now that we have our project created, let's make some classes that we will need during the usage of our project:
Right-click project in solution explorer -> Add -> Class -> name it 'Server.cs'
Right-click project in solution explorer -> Add -> Class -> name it 'Client.cs'
Now let's add the code:
Server.cs
Client.cs
Program.cs
And now, compile it:
Right-click project in solution explorer -> Build
To run this, you need to install mono on your centos machine
Than just start it before running your WorksSvr, using "mono GlobalMan\ Proxy.exe".
Have Fun
I won't be providing much support in setting this up, just wanted to release it for ppl that need it.
Credits: atom0s (original proxy:
NOTE: Since this is a single threaded application, and has no way (well not coded anyway) of telling what channel is connecting trough it, you have to compile a different one for each channel you want to have different mobs or items on
IMPORTANT: This proxy only modifies the packet that's sent from global to worldsvr that has items and mobs filename in it since ep8 doesn't read them from common.ini file it's NOT meant to be any form of PROTECTION !
Update 2:
added a check on packet size to avoid reading data from packets that are not 785 bytes long ... somehow i encountered packets with less than 10 bytes and that caused the proxy to crash
Update 1:
handled exception for "serverSocket.EndConnect", this caused proxy to crash if globalman was restarted
File -> New -> Project -> Visual C# -> Windows -> Console Application.
Name the project 'GlobalMan Proxy'.
Now that we have our project created, let's make some classes that we will need during the usage of our project:
Right-click project in solution explorer -> Add -> Class -> name it 'Server.cs'
Right-click project in solution explorer -> Add -> Class -> name it 'Client.cs'
Now let's add the code:
Server.cs
Code:
using System;
using System.Net;
using System.Net.Sockets;
namespace GlobalMan_Proxy
{
class Server
{
/// <summary>
/// Local listening server object.
/// </summary>
private TcpListener m_vServer;
/// <summary>
/// Local copy of our connected client.
/// </summary>
private Client m_vClient;
/// <summary>
/// Default Constructor
/// </summary>
public Server()
{
// Setup class defaults..
this.LocalAddress = IPAddress.Loopback.ToString();
this.LocalPort = 1;
this.RemoteAddress = IPAddress.Loopback.ToString();
this.RemotePort = 2;
}
/// <summary>
/// Starts our listen server to accept incoming connections.
/// </summary>
/// <returns></returns>
public bool Start()
{
try
{
// Cleanup any previous objects..
this.Stop();
// Create the new TcpListener..
this.m_vServer = new TcpListener(IPAddress.Parse(this.LocalAddress), this.LocalPort);
this.m_vServer.Start();
// Setup the async handler when a client connects..
this.m_vServer.BeginAcceptTcpClient(new AsyncCallback(OnAcceptTcpClient), this.m_vServer);
return true;
}
catch (Exception ex)
{
this.Stop();
Console.WriteLine("Exception caught inside of Server::Start\r\n" + ex.Message);
return false;
}
}
/// <summary>
/// Stops the local listening server if it is started.
/// </summary>
public void Stop()
{
// Cleanup the client object..
if (this.m_vClient != null)
this.m_vClient.Stop();
this.m_vClient = null;
// Cleanup the server object..
if (this.m_vServer != null)
this.m_vServer.Stop();
this.m_vServer = null;
}
/// <summary>
/// Async callback handler that accepts incoming TcpClient connections.
/// NOTE:
/// It is important that you use the results server object to
/// prevent threading issues and object disposed errors!
/// </summary>
/// <param name="result"></param>
private void OnAcceptTcpClient(IAsyncResult result)
{
// Ensure this connection is complete and valid..
if (result.IsCompleted == false || !(result.AsyncState is TcpListener))
{
this.Stop();
return;
}
// Obtain our server instance. (YOU NEED TO USE IT LIKE THIS DO NOT USE this.m_vServer here!)
TcpListener tcpServer = (result.AsyncState as TcpListener);
TcpClient tcpClient = null;
try
{
// End the async connection request..
tcpClient = tcpServer.EndAcceptTcpClient(result);
// Kill the previous client that was connected (if any)..
if (this.m_vClient != null)
this.m_vClient.Stop();
// Prepare the client and start the proxying..
this.m_vClient = new Client(tcpClient.Client);
this.m_vClient.Start(this.RemoteAddress, this.RemotePort, this.new_item, this.new_mobs);
}
catch
{
System.Diagnostics.Debug.WriteLine("Error while attempting to complete async connection.");
}
// Begin listening for the next client..
tcpServer.BeginAcceptTcpClient(new AsyncCallback(OnAcceptTcpClient), tcpServer);
}
/// <summary>
/// Gets or sets the local address of this listen server.
/// </summary>
public String LocalAddress
{
get;
set;
}
/// <summary>
/// Gets or sets the local port of this listen server.
/// </summary>
public Int32 LocalPort
{
get;
set;
}
/// <summary>
/// Gets or sets the remote address to forward the client to.
/// </summary>
public String RemoteAddress
{
get;
set;
}
/// <summary>
/// Gets or sets the remote port to foward the client to.
/// </summary>
public Int32 RemotePort
{
get;
set;
}
public String new_item
{
get;
set;
}
public String new_mobs
{
get;
set;
}
}
}
Client.cs
Code:
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using System.Net.Sockets;
namespace GlobalMan_Proxy
{
class Client
{
/// <summary>
/// The maximum amount of data to receive in a single packet.
/// </summary>
private static Int32 MAX_BUFFER_SIZE = 2048;
/// <summary>
/// Internal client state to prevent multiple stop calls.
/// (Helps reduce the number of unneeded exceptions.)
/// </summary>
private Boolean m_vIsRunning;
/// <summary>
/// Client variables.
/// </summary>
private Socket m_vClientSocket;
private Byte[] m_vClientBuffer;
private List<Byte> m_vClientBacklog;
/// <summary>
/// Server variables.
/// </summary>
private Socket m_vServerSocket;
private Byte[] m_vServerBuffer;
private List<Byte> m_vServerBacklog;
private String new_item;
private String new_mobs;
/// <summary>
/// Default Constructor
/// </summary>
/// <param name="sockClient"></param>
public Client(Socket sockClient)
{
// Setup class defaults..
this.m_vClientSocket = sockClient;
this.m_vClientBuffer = new Byte[MAX_BUFFER_SIZE];
this.m_vClientBacklog = new List<Byte>();
this.m_vServerSocket = null;
this.m_vServerBuffer = new Byte[MAX_BUFFER_SIZE];
this.m_vServerBacklog = new List<Byte>();
}
/// <summary>
/// Starts our proxy client.
/// </summary>
/// <param name="remoteTarget"></param>
/// <param name="remotePort"></param>
/// <returns></returns>
public bool Start(String remoteTarget = "127.0.0.1", Int32 remotePort = 7777, string item = "Data/Item.scp", string mobs = "Data/Mobs.scp")
{
// Stop this client if it was already started before..
if (this.m_vIsRunning == true)
this.Stop();
this.m_vIsRunning = true;
// Attempt to parse the given remote target.
// This allows an IP address or domain to be given.
// Ex:
// 127.0.0.1
// derp.no-ip.org
IPAddress ipAddress = null;
try { ipAddress = IPAddress.Parse(remoteTarget); }
catch
{
try { ipAddress = Dns.GetHostEntry(remoteTarget).AddressList[0]; }
catch { throw new SocketException((int)SocketError.HostNotFound); }
}
try
{
// Connect to the target machine on a new socket..
this.m_vServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
this.m_vServerSocket.BeginConnect(new IPEndPoint(ipAddress, remotePort),
new AsyncCallback((result) =>
{
// Ensure the connection was valid..
if (result == null || result.IsCompleted == false || !(result.AsyncState is Socket))
return;
// Obtain our server instance. (YOU NEED TO USE IT LIKE THIS DO NOT USE this.m_vServerSocket here!)
Socket serverSocket = (result.AsyncState as Socket);
// Stop processing if the server has told us to stop..
if (this.m_vIsRunning == false || serverSocket == null)
return;
// Complete the async connection request..
try
{
serverSocket.EndConnect(result);
}
catch (SocketException ex)
{
this.Stop();
return;
}
// Start monitoring for packets..
this.m_vClientSocket.ReceiveBufferSize = MAX_BUFFER_SIZE;
serverSocket.ReceiveBufferSize = MAX_BUFFER_SIZE;
this.Server_BeginReceive();
this.Client_BeginReceive();
}), this.m_vServerSocket);
this.new_item = item;
this.new_mobs = mobs;
return true;
}
catch (ObjectDisposedException ex)
{
// Process the exception as you wish here..
}
catch (SocketException ex)
{
// Process the exception as you wish here..
}
catch (Exception ex)
{
// Process the exception as you wish here..
}
return false;
}
/// <summary>
/// Stops this client object.
/// </summary>
public void Stop()
{
if (this.m_vIsRunning == false)
return;
// Cleanup the client socket..
if (this.m_vClientSocket != null)
this.m_vClientSocket.Close();
this.m_vClientSocket = null;
// Cleanup the server socket..
if (this.m_vServerSocket != null)
this.m_vServerSocket.Close();
this.m_vServerSocket = null;
this.m_vIsRunning = false;
}
/// <summary>
/// Begins an async event to receive incoming data.
/// </summary>
private void Client_BeginReceive()
{
// Prevent invalid call..
if (!this.m_vIsRunning)
return;
try
{
this.m_vClientSocket.BeginReceive(this.m_vClientBuffer, 0, MAX_BUFFER_SIZE, SocketFlags.None, new AsyncCallback(OnClientReceiveData), this.m_vClientSocket);
}
catch (SocketException ex) { this.Stop(); }
catch (Exception ex) { this.Stop(); }
}
/// <summary>
/// Begins an async event to receive incoming data.
/// </summary>
private void Server_BeginReceive()
{
// Prevent invalid call..
if (!this.m_vIsRunning)
return;
try
{
this.m_vServerSocket.BeginReceive(this.m_vServerBuffer, 0, MAX_BUFFER_SIZE, SocketFlags.None, new AsyncCallback(OnServerReceiveData), this.m_vServerSocket);
}
catch (SocketException ex) { this.Stop(); }
catch (Exception ex) { this.Stop(); }
}
/// <summary>
/// Completes an async event to receive data.
/// </summary>
/// <param name="result"></param>
private void OnClientReceiveData(IAsyncResult result)
{
// Prevent invalid calls to this function..
if (!this.m_vIsRunning || result.IsCompleted == false || !(result.AsyncState is Socket))
{
this.Stop();
return;
}
Socket client = (result.AsyncState as Socket);
// Attempt to end the async call..
Int32 nRecvCount = 0;
try
{
nRecvCount = client.EndReceive(result);
if (nRecvCount == 0)
{
this.Stop();
return;
}
}
catch { this.Stop(); return; }
// Read the current packet..
Byte[] btRecvData = new Byte[nRecvCount];
Array.Copy(this.m_vClientBuffer, 0, btRecvData, 0, nRecvCount);
//Console.WriteLine("C > S : " + BitConverter.ToString(btRecvData));
// Send the packet to the server..
this.SendToServer(btRecvData);
// Begin listening for next packet..
this.Client_BeginReceive();
}
/// <summary>
/// Completes an async event to receive data.
/// </summary>
/// <param name="result"></param>
private void OnServerReceiveData(IAsyncResult result)
{
// Prevent invalid calls to this function..
if (!this.m_vIsRunning || result.IsCompleted == false || !(result.AsyncState is Socket))
{
this.Stop();
return;
}
Socket server = (result.AsyncState as Socket);
// Attempt to end the async call..
Int32 nRecvCount = 0;
try
{
nRecvCount = server.EndReceive(result);
if (nRecvCount == 0)
{
this.Stop();
return;
}
}
catch { this.Stop(); return; }
// Read the current packet..
Byte[] btRecvData = new Byte[nRecvCount];
Array.Copy(this.m_vServerBuffer, 0, btRecvData, 0, nRecvCount);
if (btRecvData.Length == 785)
{
UInt16 opCode = BitConverter.ToUInt16(btRecvData, 4+4);
string old_item, old_mobs, item, mobs;
if (opCode == 759)
{
old_item = Encoding.UTF8.GetString(btRecvData, 15, 64);
old_mobs = Encoding.UTF8.GetString(btRecvData, 272, 64);
byte[] item_buffer = Encoding.ASCII.GetBytes(this.new_item);
byte[] mobs_buffer = Encoding.ASCII.GetBytes(this.new_mobs);
Console.WriteLine("Default Item : " + old_item);
Console.WriteLine("Default Mobs : " + old_mobs);
item_buffer.CopyTo(btRecvData, 15);
mobs_buffer.CopyTo(btRecvData, 272);
item = Encoding.UTF8.GetString(btRecvData, 15, 64);
mobs = Encoding.UTF8.GetString(btRecvData, 272, 64);
Console.WriteLine("New Item : " + item);
Console.WriteLine("New Mobs : " + mobs);
}
}
// Send the packet to the client..
this.SendToClient(btRecvData);
// Begin listening for next packet..
this.Server_BeginReceive();
}
/// <summary>
/// Sends the given packet data to the client socket.
/// </summary>
/// <param name="btPacket"></param>
public void SendToClient(byte[] btPacket)
{
if (!this.m_vIsRunning)
return;
try
{
this.m_vClientSocket.BeginSend(btPacket, 0, btPacket.Length, SocketFlags.None,
new AsyncCallback((x) =>
{
if (x.IsCompleted == false || !(x.AsyncState is Socket))
{
this.Stop();
return;
}
(x.AsyncState as Socket).EndSend(x);
}), this.m_vClientSocket);
}
catch (Exception ex) { this.Stop(); }
}
/// <summary>
/// Sends the given packet data to the server socket.
/// </summary>
/// <param name="btPacket"></param>
public void SendToServer(byte[] btPacket)
{
if (!this.m_vIsRunning)
return;
try
{
this.m_vServerSocket.BeginSend(btPacket, 0, btPacket.Length, SocketFlags.None,
new AsyncCallback((x) =>
{
if (x.IsCompleted == false || !(x.AsyncState is Socket))
{
this.Stop();
return;
}
(x.AsyncState as Socket).EndSend(x);
}), this.m_vServerSocket);
}
catch (Exception ex) { this.Stop(); }
}
/// <summary>
/// Gets the base client socket.
/// </summary>
public Socket ClientSocket
{
get
{
if (this.m_vIsRunning && this.m_vClientSocket != null)
return this.m_vClientSocket;
return null;
}
}
/// <summary>
/// Gets the base server socket.
/// </summary>
public Socket ServerSocket
{
get
{
if (this.m_vIsRunning && this.m_vServerSocket != null)
return this.m_vServerSocket;
return null;
}
}
}
}
Program.cs
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace GlobalMan_Proxy
{
class Program
{
static void Main(string[] args)
{
Server server = new Server();
server.RemoteAddress = "127.0.0.1";
server.RemotePort = 38170;
server.LocalPort = 35000; //make WorldSvr_XX_YY.ini connect to this port instead of GlobalMgr original port
server.new_item = "Data/Item_new.scp";
server.new_mobs = "Data/Mobs_new.scp";
server.Start();
while (true) { };
}
}
}
And now, compile it:
Right-click project in solution explorer -> Build
To run this, you need to install mono on your centos machine
Code:
yum install bison gettext glib2 freetype fontconfig libpng libpng-devel libX11 libX11-devel glib2-devel libgdi* libexif glibc-devel urw-fonts java unzip gcc gcc-c++ automake autoconf libtool make bzip2 wget
cd /usr/local/src
wget http://download.mono-project.com/sources/mono/mono-3.0.7.tar.bz2
tar jxf mono-3.0.7.tar.bz2
cd mono-3.0.7
./configure --prefix=/opt/mono
make && make install
Than just start it before running your WorksSvr, using "mono GlobalMan\ Proxy.exe".
Have Fun
I won't be providing much support in setting this up, just wanted to release it for ppl that need it.
Credits: atom0s (original proxy:
You must be registered to see links
)NOTE: Since this is a single threaded application, and has no way (well not coded anyway) of telling what channel is connecting trough it, you have to compile a different one for each channel you want to have different mobs or items on
IMPORTANT: This proxy only modifies the packet that's sent from global to worldsvr that has items and mobs filename in it since ep8 doesn't read them from common.ini file it's NOT meant to be any form of PROTECTION !
Update 2:
added a check on packet size to avoid reading data from packets that are not 785 bytes long ... somehow i encountered packets with less than 10 bytes and that caused the proxy to crash
Update 1:
handled exception for "serverSocket.EndConnect", this caused proxy to crash if globalman was restarted
Last edited: