|
You last visited: Today at 06:15
Advertisement
C# Simplest Proxy
Discussion on C# Simplest Proxy within the SRO Coding Corner forum part of the Silkroad Online category.
05/21/2011, 21:37
|
#1
|
elite*gold: 260
Join Date: Aug 2008
Posts: 560
Received Thanks: 3,779
|
C# Simplest Proxy
This is a bare minimal proxy that uses a lot less code than my other ones do. It should be a bit easier to understand and follow as well, as long as you understand the concept of a proxy. This code is preferred over the SimpleProxy included in my C# Silkroad Security project because it is single threaded and a lot more simple. This is a "one proxy per one connection" design.
In order to use this, you need the  files. Simply make a new project, paste in the code, and add a reference to SilkroadSecurityApi.
The final program uses a command line: <local address> <local port> <remote address> <remote port>.
An example of proper usage would be: "Proxy.exe 127.0.0.1 16000 gwgt1.joymax.com 15779". You would then start ISRO redirected to 127.0.0.1:16000 and it would connect to gwgt1.joymax.com:15779. The AgentServer port will use the local port + 1, so keep that in mind if you run multiple exes.
The application will spawn another copy of itself with the AgentServer information required for your client to connect with. The console window should be reused (at least it was for me, Win7 x64). As a result, you will see one exit message for the first process when connecting to the AgentServer. This is normal. The process exits when any error occurs or if the user presses Escape.
This is just for educational use! You can further develop it to integrate in a GUI for an analyzer/injector or do whatever else with it.
Proxy.cs
Code:
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Diagnostics;
using SilkroadSecurityApi;
using System.Threading;
class Program
{
class Context
{
public Socket Socket { get; set; }
public Security Security { get; set; }
public TransferBuffer Buffer { get; set; }
public Security RelaySecurity { get; set; }
public Context()
{
Socket = null;
Security = new Security();
RelaySecurity = null;
Buffer = new TransferBuffer(8192);
}
}
static void Main(string[] args)
{
try
{
String local_host;
Int32 local_port;
String remote_host;
Int32 remote_port;
local_host = args[0];
local_port = Int32.Parse(args[1]);
remote_host = args[2];
remote_port = Int32.Parse(args[3]);
Context local_context = new Context();
local_context.Security.GenerateSecurity(true, true, true);
Context remote_context = new Context();
remote_context.RelaySecurity = local_context.Security;
local_context.RelaySecurity = remote_context.Security;
List<Context> contexts = new List<Context>();
contexts.Add(local_context);
contexts.Add(remote_context);
using (Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
server.Bind(new IPEndPoint(IPAddress.Parse(local_host), local_port));
server.Listen(1);
local_context.Socket = server.Accept();
}
using (local_context.Socket)
{
using (remote_context.Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
remote_context.Socket.Connect(remote_host, remote_port);
while (true)
{
if (Console.KeyAvailable == true) // Application event processing
{
ConsoleKeyInfo key = Console.ReadKey(true);
if (key.Key == ConsoleKey.Escape)
{
break;
}
}
foreach (Context context in contexts) // Network input event processing
{
if (context.Socket.Poll(0, SelectMode.SelectRead))
{
int count = context.Socket.Receive(context.Buffer.Buffer);
if (count == 0)
{
throw new Exception("The remote connection has been lost.");
}
context.Security.Recv(context.Buffer.Buffer, 0, count);
}
}
foreach (Context context in contexts) // Logic event processing
{
List<Packet> packets = context.Security.TransferIncoming();
if (packets != null)
{
foreach (Packet packet in packets)
{
if (packet.Opcode == 0x5000 || packet.Opcode == 0x9000) // ignore always
{
}
else if (packet.Opcode == 0x2001)
{
if (context == remote_context) // ignore local to proxy only
{
context.RelaySecurity.Send(packet); // proxy to remote is handled by API
}
}
else if (packet.Opcode == 0xA102)
{
byte result = packet.ReadUInt8();
if (result == 1)
{
uint id = packet.ReadUInt32();
string ip = packet.ReadAscii();
ushort port = packet.ReadUInt16();
using (Process process = new Process())
{
process.StartInfo.UseShellExecute = false;
process.StartInfo.FileName = System.Reflection.Assembly.GetExecutingAssembly().Location;
process.StartInfo.Arguments = local_host + " " + (local_port + 1).ToString() + " " + ip + " " + port.ToString();
if (!process.Start())
{
throw new Exception("Could not start the AgentServer Proxy process.");
}
}
Thread.Sleep(250); // Should be enough time, if not, increase, but too long and C9 timeout results
Packet new_packet = new Packet(0xA102, true);
new_packet.WriteUInt8(result);
new_packet.WriteUInt32(id);
new_packet.WriteAscii(local_host);
new_packet.WriteUInt16(local_port + 1);
context.RelaySecurity.Send(new_packet);
}
}
else
{
context.RelaySecurity.Send(packet);
}
}
}
}
foreach (Context context in contexts) // Network output event processing
{
if (context.Socket.Poll(0, SelectMode.SelectWrite))
{
List<KeyValuePair<TransferBuffer, Packet>> buffers = context.Security.TransferOutgoing();
if (buffers != null)
{
foreach (KeyValuePair<TransferBuffer, Packet> kvp in buffers)
{
TransferBuffer buffer = kvp.Key;
Packet packet = kvp.Value;
byte[] packet_bytes = packet.GetBytes();
Console.WriteLine("[{0}][{1:X4}][{2} bytes]{3}{4}{6}{5}{6}", context == local_context ? "S->C" : "C->S", packet.Opcode, packet_bytes.Length, packet.Encrypted ? "[Encrypted]" : "", packet.Massive ? "[Massive]" : "", Utility.HexDump(packet_bytes), Environment.NewLine);
while (true)
{
int count = context.Socket.Send(buffer.Buffer, buffer.Offset, buffer.Size, SocketFlags.None);
buffer.Offset += count;
if (buffer.Offset == buffer.Size)
{
break;
}
Thread.Sleep(1);
}
}
}
}
}
Thread.Sleep(1); // Cycle complete, prevent 100% CPU usage
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
|
|
|
05/22/2011, 05:42
|
#2
|
elite*gold: 844
Join Date: Oct 2010
Posts: 839
Received Thanks: 192
|
thx alot bro
|
|
|
05/22/2011, 11:30
|
#3
|
elite*gold: 0
Join Date: Jan 2010
Posts: 1,484
Received Thanks: 809
|
Thanks the code works great.
I had only one little problem which was that the socket didn't accept any incoming connections.
So I changed the code at line 55 till 61 to the following:
Code:
IPAddress ipAddress = IPAddress.Any;
TcpListener listener = new TcpListener(ipAddress, local_port);
listener.Start();
local_context.Socket = listener.AcceptSocket();
But it's a great example good work
|
|
|
05/22/2011, 15:26
|
#4
|
elite*gold: 260
Join Date: Aug 2008
Posts: 560
Received Thanks: 3,779
|
Quote:
Originally Posted by kevin_owner
Thanks the code works great.
I had only one little problem which was that the socket didn't accept any incoming connections.
|
You don't have to change anything but the command line. When you start with "127.0.0.1", it binds to your loopback adapter. This means only your PC can access it.
If you want to bind to all interfaces, you may use "0.0.0.0" instead and it will be available. 0.0.0.0 is equivalent to  .
However: Since the code uses the same address for the AgentServer IP, you must specify your LAN address instead of 0.0.0.0 so the right IP is sent to the incoming client. There is no way around that because you can't detect which address should be sent auto-magically, even with .Net's tools. It's just a network concept issue rather than language issue. There's no real point in making a second parameter to bind to either because it starts a process on the same machine!
There's a neat little trick you can do to detect your real IP to the internet. Simply perform a HTTP get on a web page that shows your IP, parse the result, and send that as the AgentServer IP. That works for the cases when you aren't running on a VPN and don't have a web proxy active.
Likewise for specific network adapters, you can substitute in that address to have the program bind to that specific interface. For example, if you had Hamachi or Tunngle, you could bind to those addresses just to expose the program to those networks.
For allowing access outside your network, you must setup port forwarding. You will need to redirect the local port you specify as well as local port + 1. If you have a firewall, you must configure it to allow incoming connections on the specific port. If you aren't behind a router or firewall, then you shouldn't have to do these things, but then you are completely exposed to the internet!
However: You would have to bind to your IP address via command line so it is sent as the AgentServer IP. A second parameter for AgentServer would fix this, but this code is not meant for that. Exposing a proxy to the internet like this that creates a process on your PC is just asking for trouble, so it's by design that you have to change a few little things to bind to one address but send another different IP.
These changes would be:
- Adding 2 more args for agent ip/port
- Making 0xA102 packet use them
- Adding a 3rd command line flag to know which type of proxy it is (gateway/agent)
- Binding to the right set of command line args based on the flag
- Updating process arg list
Such a solution might look like this:
Code:
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Diagnostics;
using SilkroadSecurityApi;
using System.Threading;
class Program
{
class Context
{
public Socket Socket { get; set; }
public Security Security { get; set; }
public TransferBuffer Buffer { get; set; }
public Security RelaySecurity { get; set; }
public Context()
{
Socket = null;
Security = new Security();
RelaySecurity = null;
Buffer = new TransferBuffer(8192);
}
}
static void Main(string[] args)
{
try
{
String gateway_host = args[0];
Int32 gateway_port = Int32.Parse(args[1]);
String agent_host = args[2];
Int32 agent_port = Int32.Parse(args[3]);
String remote_host = args[4];
Int32 remote_port = Int32.Parse(args[5]);
String type = args[6];
Context local_context = new Context();
local_context.Security.GenerateSecurity(true, true, true);
Context remote_context = new Context();
remote_context.RelaySecurity = local_context.Security;
local_context.RelaySecurity = remote_context.Security;
List<Context> contexts = new List<Context>();
contexts.Add(local_context);
contexts.Add(remote_context);
using (Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
if (type == "gateway")
{
server.Bind(new IPEndPoint(IPAddress.Parse(gateway_host), gateway_port));
}
else if (type == "agent")
{
server.Bind(new IPEndPoint(IPAddress.Parse(agent_host), agent_port));
}
server.Listen(1);
local_context.Socket = server.Accept();
}
using (local_context.Socket)
{
using (remote_context.Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
remote_context.Socket.Connect(remote_host, remote_port);
while (true)
{
if (Console.KeyAvailable == true) // Application event processing
{
ConsoleKeyInfo key = Console.ReadKey(true);
if (key.Key == ConsoleKey.Escape)
{
break;
}
}
foreach (Context context in contexts) // Network input event processing
{
if (context.Socket.Poll(0, SelectMode.SelectRead))
{
int count = context.Socket.Receive(context.Buffer.Buffer);
if (count == 0)
{
throw new Exception("The remote connection has been lost.");
}
context.Security.Recv(context.Buffer.Buffer, 0, count);
}
}
foreach (Context context in contexts) // Logic event processing
{
List<Packet> packets = context.Security.TransferIncoming();
if (packets != null)
{
foreach (Packet packet in packets)
{
if (packet.Opcode == 0x5000 || packet.Opcode == 0x9000) // ignore always
{
}
else if (packet.Opcode == 0x2001)
{
if (context == remote_context) // ignore local to proxy only
{
context.RelaySecurity.Send(packet); // proxy to remote is handled by API
}
}
else if (packet.Opcode == 0xA102)
{
byte result = packet.ReadUInt8();
if (result == 1)
{
uint id = packet.ReadUInt32();
string ip = packet.ReadAscii();
ushort port = packet.ReadUInt16();
using (Process process = new Process())
{
process.StartInfo.UseShellExecute = false;
process.StartInfo.FileName = System.Reflection.Assembly.GetExecutingAssembly().Location;
process.StartInfo.Arguments = gateway_host + " " + gateway_port.ToString() + " " + agent_host + " " + agent_port.ToString() + " " + ip + " " + port.ToString() + " " + "agent";
if (!process.Start())
{
throw new Exception("Could not start the AgentServer Proxy process.");
}
}
Thread.Sleep(250); // Should be enough time, if not, increase, but too long and C9 timeout results
Packet new_packet = new Packet(0xA102, true);
new_packet.WriteUInt8(result);
new_packet.WriteUInt32(id);
new_packet.WriteAscii(agent_host);
new_packet.WriteUInt16(agent_port);
context.RelaySecurity.Send(new_packet);
}
}
else
{
context.RelaySecurity.Send(packet);
}
}
}
}
foreach (Context context in contexts) // Network output event processing
{
if (context.Socket.Poll(0, SelectMode.SelectWrite))
{
List<KeyValuePair<TransferBuffer, Packet>> buffers = context.Security.TransferOutgoing();
if (buffers != null)
{
foreach (KeyValuePair<TransferBuffer, Packet> kvp in buffers)
{
TransferBuffer buffer = kvp.Key;
Packet packet = kvp.Value;
byte[] packet_bytes = packet.GetBytes();
Console.WriteLine("[{0}][{1:X4}][{2} bytes]{3}{4}{6}{5}{6}", context == local_context ? "S->C" : "C->S", packet.Opcode, packet_bytes.Length, packet.Encrypted ? "[Encrypted]" : "", packet.Massive ? "[Massive]" : "", Utility.HexDump(packet_bytes), Environment.NewLine);
while (true)
{
int count = context.Socket.Send(buffer.Buffer, buffer.Offset, buffer.Size, SocketFlags.None);
buffer.Offset += count;
if (buffer.Offset == buffer.Size)
{
break;
}
Thread.Sleep(1);
}
}
}
}
}
Thread.Sleep(1); // Cycle complete, prevent 100% CPU usage
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
An example commandline would be: "192.168.1.112 16000 192.168.1.112 16001 gwgt1.joymax.com 15779 gateway". You would replace 192.168.1.112 with the address of the network card you wish to bind to. You can use 0.0.0.0 for the first one, but the second one must be translatable for the remote PC it is sent to. So if you send a 192.X.X.X address, the PC has to be on the same network. If you send your IP address, that PC has to be able to connect to it, and so on.
I hope that clears up some of the confusions.
|
|
|
07/22/2011, 23:17
|
#5
|
elite*gold: 0
Join Date: Feb 2008
Posts: 3,777
Received Thanks: 1,455
|
Thanks alot this help me alot
|
|
|
07/28/2011, 16:27
|
#6
|
elite*gold: 166
Join Date: Apr 2009
Posts: 2,339
Received Thanks: 2,661
|
PHP Code:
Imports System.Collections.Generic
Imports System.Net
Imports System.Net.Sockets
Imports System.Diagnostics
Imports SilkroadSecurityApi
Imports System.Threading
Class Program
Private Class Context
Public Property Socket() As Socket
Get
Return m_Socket
End Get
Set(ByVal value As Socket)
m_Socket = value
End Set
End Property
Private m_Socket As Socket
Public Property Security() As Security
Get
Return m_Security
End Get
Set(ByVal value As Security)
m_Security = value
End Set
End Property
Private m_Security As Security
Public Property Buffer() As TransferBuffer
Get
Return m_Buffer
End Get
Set(ByVal value As TransferBuffer)
m_Buffer = value
End Set
End Property
Private m_Buffer As TransferBuffer
Public Property RelaySecurity() As Security
Get
Return m_RelaySecurity
End Get
Set(ByVal value As Security)
m_RelaySecurity = value
End Set
End Property
Private m_RelaySecurity As Security
Public Sub New()
Socket = Nothing
Security = New Security()
RelaySecurity = Nothing
Buffer = New TransferBuffer(8192)
End Sub
End Class
Private Shared Sub ExecuteProxy(ByVal args As String())
Try
Dim local_host As [String]
Dim local_port As Int32
Dim remote_host As [String]
Dim remote_port As Int32
local_host = args(0)
local_port = Int32.Parse(args(1))
remote_host = args(2)
remote_port = Int32.Parse(args(3))
Dim local_context As New Context()
local_context.Security.GenerateSecurity(True, True, True)
Dim remote_context As New Context()
remote_context.RelaySecurity = local_context.Security
local_context.RelaySecurity = remote_context.Security
Dim contexts As New List(Of Context)()
contexts.Add(local_context)
contexts.Add(remote_context)
Using server As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
server.Bind(New IPEndPoint(IPAddress.Parse(local_host), local_port))
server.Listen(1)
local_context.Socket = server.Accept()
End Using
Using local_context.Socket
// ********* Using remote_context.Socket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
remote_context.Socket.Connect(remote_host, remote_port)
While True
If Console.KeyAvailable = True Then
' Application event processing
Dim key As ConsoleKeyInfo = Console.ReadKey(True)
If key.Key = ConsoleKey.Escape Then
Exit While
End If
End If
For Each context As Context In contexts
' Network input event processing
If context.Socket.Poll(0, SelectMode.SelectRead) Then
Dim count As Integer = context.Socket.Receive(context.Buffer.Buffer)
If count = 0 Then
Throw New Exception("The remote connection has been lost.")
End If
context.Security.Recv(context.Buffer.Buffer, 0, count)
End If
Next
For Each context As Context In contexts
' Logic event processing
Dim packets As List(Of Packet) = context.Security.TransferIncoming()
If packets IsNot Nothing Then
For Each packet As Packet In packets
If packet.Opcode = &H5000 OrElse packet.Opcode = &H9000 Then
' ignore always
ElseIf packet.Opcode = &H2001 Then
If context Is remote_context Then
' ignore local to proxy only
' proxy to remote is handled by API
context.RelaySecurity.Send(packet)
End If
ElseIf packet.Opcode = &HA102 Then
Dim result As Byte = packet.ReadUInt8()
If result = 1 Then
Dim id As UInteger = packet.ReadUInt32()
Dim ip As String = packet.ReadAscii()
Dim port As UShort = packet.ReadUInt16()
Using process As New Process()
process.StartInfo.UseShellExecute = False
process.StartInfo.FileName = System.Reflection.Assembly.GetExecutingAssembly().Location
process.StartInfo.Arguments = local_host & " " & (local_port + 1).ToString() & " " & ip & " " & port.ToString()
If Not process.Start() Then
Throw New Exception("Could not start the AgentServer Proxy process.")
End If
End Using
Thread.Sleep(250)
' Should be enough time, if not, increase, but too long and C9 timeout results
Dim new_packet As New Packet(&HA102, True)
new_packet.WriteUInt8(result)
new_packet.WriteUInt32(id)
new_packet.WriteAscii(local_host)
new_packet.WriteUInt16(local_port + 1)
context.RelaySecurity.Send(new_packet)
End If
Else
context.RelaySecurity.Send(packet)
End If
Next
End If
Next
For Each context As Context In contexts
' Network output event processing
If context.Socket.Poll(0, SelectMode.SelectWrite) Then
Dim buffers As List(Of KeyValuePair(Of TransferBuffer, Packet)) = context.Security.TransferOutgoing()
If buffers IsNot Nothing Then
For Each kvp As KeyValuePair(Of TransferBuffer, Packet) In buffers
Dim buffer As TransferBuffer = kvp.Key
Dim packet As Packet = kvp.Value
Dim packet_bytes As Byte() = packet.GetBytes()
Console.WriteLine("[{0}][{1:X4}][{2} bytes]{3}{4}{6}{5}{6}", If(context Is local_context, "S->C", "C->S"), packet.Opcode, packet_bytes.Length, If(packet.Encrypted, "[Encrypted]", ""), If(packet.Massive, "[Massive]", ""), _
Utility.HexDump(packet_bytes), Environment.NewLine)
While True
Dim count As Integer = context.Socket.Send(buffer.Buffer, buffer.Offset, buffer.Size, SocketFlags.None)
buffer.Offset += count
If buffer.Offset = buffer.Size Then
Exit While
End If
Thread.Sleep(1)
End While
Next
End If
End If
Next
' Cycle complete, prevent 100% CPU usage
Thread.Sleep(1)
End While
End Using
End Using
Catch ex As Exception
Console.WriteLine(ex)
End Try
End Sub
End Class
Here i translated it to VB.
The problem is i have error somewhere.
Error is at where commented with "//******"
It says that " operator type '=' is not defined for system.net.sockets.socket and system.net.sockets.socket.
I compiled it with c# without any errors but here i failed.
And also , if open this as an .exe (like a normal connector.) , my receive function doesn't work so i MUST implement it to my project.
Thank you
|
|
|
07/28/2011, 18:38
|
#7
|
elite*gold: 0
Join Date: Jan 2010
Posts: 1,484
Received Thanks: 809
|
You could remove the using statements cause that's probably causing your problem.
|
|
|
07/28/2011, 22:15
|
#8
|
elite*gold: 260
Join Date: Aug 2008
Posts: 560
Received Thanks: 3,779
|
Quote:
Originally Posted by kevin_owner
You could remove the using statements cause that's probably causing your problem.
|
Yea, that'll work. Or, you can create the socket first, then have a "Using remote_context.Socket" after it like your other code does. It doesn't matter too much, the using just dispoes it for you at the end of scope, you can just call Socket.close member function at the end if you want.
I took out your main class and made it module and changed the using (all the rest is your code, unmodified, but I'll just paste it all for reference):
Code:
Imports System.Collections.Generic
Imports System.Net
Imports System.Net.Sockets
Imports System.Diagnostics
Imports SilkroadSecurityApi
Imports System.Threading
Module Module1
Private Class Context
Public Property Socket() As Socket
Get
Return m_Socket
End Get
Set(ByVal value As Socket)
m_Socket = value
End Set
End Property
Private m_Socket As Socket
Public Property Security() As Security
Get
Return m_Security
End Get
Set(ByVal value As Security)
m_Security = value
End Set
End Property
Private m_Security As Security
Public Property Buffer() As TransferBuffer
Get
Return m_Buffer
End Get
Set(ByVal value As TransferBuffer)
m_Buffer = value
End Set
End Property
Private m_Buffer As TransferBuffer
Public Property RelaySecurity() As Security
Get
Return m_RelaySecurity
End Get
Set(ByVal value As Security)
m_RelaySecurity = value
End Set
End Property
Private m_RelaySecurity As Security
Public Sub New()
Socket = Nothing
Security = New Security()
RelaySecurity = Nothing
Buffer = New TransferBuffer(8192)
End Sub
End Class
Sub Main(ByVal args As String())
Try
Dim local_host As [String]
Dim local_port As Int32
Dim remote_host As [String]
Dim remote_port As Int32
local_host = args(0)
local_port = Int32.Parse(args(1))
remote_host = args(2)
remote_port = Int32.Parse(args(3))
Dim local_context As New Context()
local_context.Security.GenerateSecurity(True, True, True)
Dim remote_context As New Context()
remote_context.RelaySecurity = local_context.Security
local_context.RelaySecurity = remote_context.Security
Dim contexts As New List(Of Context)()
contexts.Add(local_context)
contexts.Add(remote_context)
Using server As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
server.Bind(New IPEndPoint(IPAddress.Parse(local_host), local_port))
server.Listen(1)
local_context.Socket = server.Accept()
End Using
Using local_context.Socket
remote_context.Socket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
Using remote_context.Socket
remote_context.Socket.Connect(remote_host, remote_port)
While True
If Console.KeyAvailable = True Then
' Application event processing
Dim key As ConsoleKeyInfo = Console.ReadKey(True)
If key.Key = ConsoleKey.Escape Then
Exit While
End If
End If
For Each context As Context In contexts
' Network input event processing
If context.Socket.Poll(0, SelectMode.SelectRead) Then
Dim count As Integer = context.Socket.Receive(context.Buffer.Buffer)
If count = 0 Then
Throw New Exception("The remote connection has been lost.")
End If
context.Security.Recv(context.Buffer.Buffer, 0, count)
End If
Next
For Each context As Context In contexts
' Logic event processing
Dim packets As List(Of Packet) = context.Security.TransferIncoming()
If packets IsNot Nothing Then
For Each packet As Packet In packets
If packet.Opcode = &H5000 OrElse packet.Opcode = &H9000 Then
' ignore always
ElseIf packet.Opcode = &H2001 Then
If context Is remote_context Then
' ignore local to proxy only
' proxy to remote is handled by API
context.RelaySecurity.Send(packet)
End If
ElseIf packet.Opcode = &HA102 Then
Dim result As Byte = packet.ReadUInt8()
If result = 1 Then
Dim id As UInteger = packet.ReadUInt32()
Dim ip As String = packet.ReadAscii()
Dim port As UShort = packet.ReadUInt16()
Using process As New Process()
process.StartInfo.UseShellExecute = False
process.StartInfo.FileName = System.Reflection.Assembly.GetExecutingAssembly().Location
process.StartInfo.Arguments = local_host & " " & (local_port + 1).ToString() & " " & ip & " " & port.ToString()
If Not process.Start() Then
Throw New Exception("Could not start the AgentServer Proxy process.")
End If
End Using
Thread.Sleep(250)
' Should be enough time, if not, increase, but too long and C9 timeout results
Dim new_packet As New Packet(&HA102, True)
new_packet.WriteUInt8(result)
new_packet.WriteUInt32(id)
new_packet.WriteAscii(local_host)
new_packet.WriteUInt16(local_port + 1)
context.RelaySecurity.Send(new_packet)
End If
Else
context.RelaySecurity.Send(packet)
End If
Next
End If
Next
For Each context As Context In contexts
' Network output event processing
If context.Socket.Poll(0, SelectMode.SelectWrite) Then
Dim buffers As List(Of KeyValuePair(Of TransferBuffer, Packet)) = context.Security.TransferOutgoing()
If buffers IsNot Nothing Then
For Each kvp As KeyValuePair(Of TransferBuffer, Packet) In buffers
Dim buffer As TransferBuffer = kvp.Key
Dim packet As Packet = kvp.Value
Dim packet_bytes As Byte() = packet.GetBytes()
Console.WriteLine("[{0}][{1:X4}][{2} bytes]{3}{4}{6}{5}{6}", If(context Is local_context, "S->C", "C->S"), packet.Opcode, packet_bytes.Length, If(packet.Encrypted, "[Encrypted]", ""), If(packet.Massive, "[Massive]", ""), _
Utility.HexDump(packet_bytes), Environment.NewLine)
While True
Dim count As Integer = context.Socket.Send(buffer.Buffer, buffer.Offset, buffer.Size, SocketFlags.None)
buffer.Offset += count
If buffer.Offset = buffer.Size Then
Exit While
End If
Thread.Sleep(1)
End While
Next
End If
End If
Next
'Cycle complete, prevent 100% CPU usage
Thread.Sleep(1)
End While
End Using
End Using
Catch ex As Exception
Console.WriteLine(ex)
End Try
End Sub
End Module
It seems to work for me. Great work on the port! You can't run it from Visual Studio because the path gets messed up (from my process creation logic), so you'd have to change that, but if you run it outside of VS, it should work normally.
|
|
|
07/29/2011, 00:54
|
#9
|
elite*gold: 166
Join Date: Apr 2009
Posts: 2,339
Received Thanks: 2,661
|
Quote:
Originally Posted by pushedx
Yea, that'll work. Or, you can create the socket first, then have a "Using remote_context.Socket" after it like your other code does. It doesn't matter too much, the using just dispoes it for you at the end of scope, you can just call Socket.close member function at the end if you want.
I took out your main class and made it module and changed the using (all the rest is your code, unmodified, but I'll just paste it all for reference):
Code:
Imports System.Collections.Generic
Imports System.Net
Imports System.Net.Sockets
Imports System.Diagnostics
Imports SilkroadSecurityApi
Imports System.Threading
Module Module1
Private Class Context
Public Property Socket() As Socket
Get
Return m_Socket
End Get
Set(ByVal value As Socket)
m_Socket = value
End Set
End Property
Private m_Socket As Socket
Public Property Security() As Security
Get
Return m_Security
End Get
Set(ByVal value As Security)
m_Security = value
End Set
End Property
Private m_Security As Security
Public Property Buffer() As TransferBuffer
Get
Return m_Buffer
End Get
Set(ByVal value As TransferBuffer)
m_Buffer = value
End Set
End Property
Private m_Buffer As TransferBuffer
Public Property RelaySecurity() As Security
Get
Return m_RelaySecurity
End Get
Set(ByVal value As Security)
m_RelaySecurity = value
End Set
End Property
Private m_RelaySecurity As Security
Public Sub New()
Socket = Nothing
Security = New Security()
RelaySecurity = Nothing
Buffer = New TransferBuffer(8192)
End Sub
End Class
Sub Main(ByVal args As String())
Try
Dim local_host As [String]
Dim local_port As Int32
Dim remote_host As [String]
Dim remote_port As Int32
local_host = args(0)
local_port = Int32.Parse(args(1))
remote_host = args(2)
remote_port = Int32.Parse(args(3))
Dim local_context As New Context()
local_context.Security.GenerateSecurity(True, True, True)
Dim remote_context As New Context()
remote_context.RelaySecurity = local_context.Security
local_context.RelaySecurity = remote_context.Security
Dim contexts As New List(Of Context)()
contexts.Add(local_context)
contexts.Add(remote_context)
Using server As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
server.Bind(New IPEndPoint(IPAddress.Parse(local_host), local_port))
server.Listen(1)
local_context.Socket = server.Accept()
End Using
Using local_context.Socket
remote_context.Socket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
Using remote_context.Socket
remote_context.Socket.Connect(remote_host, remote_port)
While True
If Console.KeyAvailable = True Then
' Application event processing
Dim key As ConsoleKeyInfo = Console.ReadKey(True)
If key.Key = ConsoleKey.Escape Then
Exit While
End If
End If
For Each context As Context In contexts
' Network input event processing
If context.Socket.Poll(0, SelectMode.SelectRead) Then
Dim count As Integer = context.Socket.Receive(context.Buffer.Buffer)
If count = 0 Then
Throw New Exception("The remote connection has been lost.")
End If
context.Security.Recv(context.Buffer.Buffer, 0, count)
End If
Next
For Each context As Context In contexts
' Logic event processing
Dim packets As List(Of Packet) = context.Security.TransferIncoming()
If packets IsNot Nothing Then
For Each packet As Packet In packets
If packet.Opcode = &H5000 OrElse packet.Opcode = &H9000 Then
' ignore always
ElseIf packet.Opcode = &H2001 Then
If context Is remote_context Then
' ignore local to proxy only
' proxy to remote is handled by API
context.RelaySecurity.Send(packet)
End If
ElseIf packet.Opcode = &HA102 Then
Dim result As Byte = packet.ReadUInt8()
If result = 1 Then
Dim id As UInteger = packet.ReadUInt32()
Dim ip As String = packet.ReadAscii()
Dim port As UShort = packet.ReadUInt16()
Using process As New Process()
process.StartInfo.UseShellExecute = False
process.StartInfo.FileName = System.Reflection.Assembly.GetExecutingAssembly().Location
process.StartInfo.Arguments = local_host & " " & (local_port + 1).ToString() & " " & ip & " " & port.ToString()
If Not process.Start() Then
Throw New Exception("Could not start the AgentServer Proxy process.")
End If
End Using
Thread.Sleep(250)
' Should be enough time, if not, increase, but too long and C9 timeout results
Dim new_packet As New Packet(&HA102, True)
new_packet.WriteUInt8(result)
new_packet.WriteUInt32(id)
new_packet.WriteAscii(local_host)
new_packet.WriteUInt16(local_port + 1)
context.RelaySecurity.Send(new_packet)
End If
Else
context.RelaySecurity.Send(packet)
End If
Next
End If
Next
For Each context As Context In contexts
' Network output event processing
If context.Socket.Poll(0, SelectMode.SelectWrite) Then
Dim buffers As List(Of KeyValuePair(Of TransferBuffer, Packet)) = context.Security.TransferOutgoing()
If buffers IsNot Nothing Then
For Each kvp As KeyValuePair(Of TransferBuffer, Packet) In buffers
Dim buffer As TransferBuffer = kvp.Key
Dim packet As Packet = kvp.Value
Dim packet_bytes As Byte() = packet.GetBytes()
Console.WriteLine("[{0}][{1:X4}][{2} bytes]{3}{4}{6}{5}{6}", If(context Is local_context, "S->C", "C->S"), packet.Opcode, packet_bytes.Length, If(packet.Encrypted, "[Encrypted]", ""), If(packet.Massive, "[Massive]", ""), _
Utility.HexDump(packet_bytes), Environment.NewLine)
While True
Dim count As Integer = context.Socket.Send(buffer.Buffer, buffer.Offset, buffer.Size, SocketFlags.None)
buffer.Offset += count
If buffer.Offset = buffer.Size Then
Exit While
End If
Thread.Sleep(1)
End While
Next
End If
End If
Next
'Cycle complete, prevent 100% CPU usage
Thread.Sleep(1)
End While
End Using
End Using
Catch ex As Exception
Console.WriteLine(ex)
End Try
End Sub
End Module
It seems to work for me. Great work on the port! You can't run it from Visual Studio because the path gets messed up (from my process creation logic), so you'd have to change that, but if you run it outside of VS, it should work normally.
|
I have changed starting process again, i made 2 different threads instead.
I wrote 2different threads for Gateway and agent server , and i passed the c9 error. I tried binding ports to IPAddress.Any or localhost , but with both i get error " The connection has forcibly closed by far main computer " ( this is not real text , i just translated it from my language. )
I get this error 2 times :
1 just after i send my login credentials
1 just after i hit "Start" at char listing ( i still get the chardata packet. )
So any idea about this ?
Thanks Drew for all of your efforts !
sarkolata
|
|
|
07/29/2011, 03:28
|
#10
|
elite*gold: 260
Join Date: Aug 2008
Posts: 560
Received Thanks: 3,779
|
The one after login credentials is normal. The client closes the GatewayServer connection and starts a new connection to the AgentServer.
The one after you select your character and hit Start is a problem. Which Silkroad are you using? On ISRO, HackShield will D/C you pretty fast most of the time if it's not loaded . The same could be true of any other Silkroad that uses protection.
For RSRO, there is no issue with your earlier code that I modified slightly and ran outside of Visual Studio. I'm logged into RSRO and it's working nice. You'd have to post your new code using different threads for me to get an idea of what is going on.
I switched from using many threads in my original proxy example with my C# code to this model just because it was a lot simpler to work with. If you are trying to add more functionality or customize it, then you can actually just create two projects, GatewayProxy and AgentProxy, and have GatewayProxy start an AgentProxy rather than itself. I tried that approach out too and it worked fine, but it was more code and a little more complication.
What all are you trying to do with the proxy?
|
|
|
07/29/2011, 03:42
|
#11
|
elite*gold: 166
Join Date: Apr 2009
Posts: 2,339
Received Thanks: 2,661
|
Quote:
Originally Posted by pushedx
The one after login credentials is normal. The client closes the GatewayServer connection and starts a new connection to the AgentServer.
The one after you select your character and hit Start is a problem. Which Silkroad are you using? On ISRO, HackShield will D/C you pretty fast most of the time if it's not loaded . The same could be true of any other Silkroad that uses protection.
For RSRO, there is no issue with your earlier code that I modified slightly and ran outside of Visual Studio. I'm logged into RSRO and it's working nice. You'd have to post your new code using different threads for me to get an idea of what is going on.
I switched from using many threads in my original proxy example with my C# code to this model just because it was a lot simpler to work with. If you are trying to add more functionality or customize it, then you can actually just create two projects, GatewayProxy and AgentProxy, and have GatewayProxy start an AgentProxy rather than itself. I tried that approach out too and it worked fine, but it was more code and a little more complication.
What all are you trying to do with the proxy?
|
Well, i was working on a tool for a long time.(Its not a bot yet) But i was working with phConnector and phConnector was crashing a lot so i tried to find a solution.
I am working on EliteSRO.
By the way , where i should bind the ip for agentthread and Gatewaythread? You used localhost, but a post which you and kevin_owner confused me. IpAddress.Any or localhost?
Here is my last code ;
Code:
Imports System.Collections.Generic
Imports System.Net
Imports System.Net.Sockets
Imports System.Diagnostics
Imports SilkroadSecurityApi
Imports System.Threading
Imports System.Windows.Forms
Imports System.Linq
Class Proxy
Public Shared local_context As New Context()
Public Shared remote_context As New Context()
Public Shared Str As Thread = New Thread(New ThreadStart(AddressOf Proxy.GatewayThread))
Public Shared Int As Thread = New Thread(New ThreadStart(AddressOf Proxy.AgentServerThread))
Public Shared ip As String
Public Shared port As UShort
Public Class Context
Public Property Socket() As Socket
Get
Return m_Socket
End Get
Set(ByVal value As Socket)
m_Socket = value
End Set
End Property
Private m_Socket As Socket
Public Property Security() As Security
Get
Return m_Security
End Get
Set(ByVal value As Security)
m_Security = value
End Set
End Property
Private m_Security As Security
Public Property Buffer() As TransferBuffer
Get
Return m_Buffer
End Get
Set(ByVal value As TransferBuffer)
m_Buffer = value
End Set
End Property
Private m_Buffer As TransferBuffer
Public Property RelaySecurity() As Security
Get
Return m_RelaySecurity
End Get
Set(ByVal value As Security)
m_RelaySecurity = value
End Set
End Property
Private m_RelaySecurity As Security
Public Sub New()
Socket = Nothing
Security = New Security()
RelaySecurity = Nothing
Buffer = New TransferBuffer(8192)
End Sub
End Class
Public Shared Sub GatewayThread()
Try
Dim local_host As String
Dim local_port As Int32
Dim remote_host As String
Dim remote_port As Int32
local_host = "127.0.0.1"
local_port = Int32.Parse("16000")
remote_host = "login4.sro.vn"
remote_port = Int32.Parse("15779")
local_context.Security.GenerateSecurity(True, True, True)
remote_context.RelaySecurity = local_context.Security
local_context.RelaySecurity = remote_context.Security
Dim contexts As New List(Of Context)()
contexts.Add(local_context)
contexts.Add(remote_context)
Using server As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
server.Bind(New IPEndPoint((IPAddress.Parse("127.0.0.1")), local_port))
server.Listen(1)
local_context.Socket = server.Accept()
End Using
Using local_context.Socket
remote_context.Socket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
Using remote_context.Socket
remote_context.Socket.Connect(remote_host, remote_port)
While True
For Each context As Context In contexts
' Network input event processing
If context.Socket.Poll(0, SelectMode.SelectRead) Then
Dim count As Integer = context.Socket.Receive(context.Buffer.Buffer)
If count = 0 Then
Throw New Exception("The remote connection has been lost.")
End If
context.Security.Recv(context.Buffer.Buffer, 0, count)
End If
Next
For Each context As Context In contexts
' Logic event processing
Dim packets As List(Of Packet) = context.Security.TransferIncoming()
If packets IsNot Nothing Then
For Each packet As Packet In packets
If packet.Opcode = &H5000 OrElse packet.Opcode = &H9000 Then
' ignore always
ElseIf packet.Opcode = &H2001 Then
If context Is remote_context Then
' ignore local to proxy only
' proxy to remote is handled by API
context.RelaySecurity.Send(packet)
End If
ElseIf packet.Opcode = &HA102 Then
Dim result As Byte = packet.ReadUInt8()
If result = 1 Then
Dim id As UInteger = packet.ReadUInt32()
ip = packet.ReadAscii()
port = packet.ReadUInt16()
Int.Start()
Thread.Sleep(250)
' Should be enough time, if not, increase, but too long and C9 timeout results
Dim new_packet As New Packet(&HA102, True)
new_packet.WriteUInt8(result)
new_packet.WriteUInt32(id)
new_packet.WriteAscii(local_host)
new_packet.WriteUInt16(local_port + 1)
context.RelaySecurity.Send(new_packet)
End If
Else
context.RelaySecurity.Send(packet)
End If
Next
End If
Next
For Each context As Context In contexts
' Network output event processing
If context.Socket.Poll(0, SelectMode.SelectWrite) Then
Dim buffers As List(Of KeyValuePair(Of TransferBuffer, Packet)) = context.Security.TransferOutgoing()
If buffers IsNot Nothing Then
For Each kvp As KeyValuePair(Of TransferBuffer, Packet) In buffers
Dim buffer As TransferBuffer = kvp.Key
Dim packet As Packet = kvp.Value
Dim packet_bytes As Byte() = packet.GetBytes()
While True
Dim count As Integer = context.Socket.Send(buffer.Buffer, buffer.Offset, buffer.Size, SocketFlags.None)
buffer.Offset += count
If buffer.Offset = buffer.Size Then
Exit While
End If
Thread.Sleep(1)
End While
Next
End If
End If
Next
' Cycle complete, prevent 100% CPU usage
Thread.Sleep(1)
End While
'End Using
End Using
End Using
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
Private Shared Sub AgentServerThread()
'(string[] args)
Try
Dim local_host As [String]
Dim local_port As Int32
Dim remote_host As [String]
Dim remote_port As Int32
local_host = "127.0.0.1"
local_port = Int32.Parse("16001")
remote_host = ip.ToString()
remote_port = Int32.Parse(port.ToString())
Dim local_context As New Context()
local_context.Security.GenerateSecurity(True, True, True)
Dim remote_context As New Context()
remote_context.RelaySecurity = local_context.Security
local_context.RelaySecurity = remote_context.Security
Dim contexts As New List(Of Context)()
contexts.Add(local_context)
contexts.Add(remote_context)
Using server As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
server.Bind(New IPEndPoint((IPAddress.Parse("127.0.0.1")), local_port))
server.Listen(1)
local_context.Socket = server.Accept()
End Using
Using local_context.Socket
remote_context.Socket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
Using remote_context.Socket
remote_context.Socket.Connect(remote_host, remote_port)
While True
For Each context As Context In contexts
' Network input event processing
If context.Socket.Poll(0, SelectMode.SelectRead) Then
Dim count As Integer = context.Socket.Receive(context.Buffer.Buffer)
If count = 0 Then
Throw New Exception("The remote connection has been lost.")
End If
context.Security.Recv(context.Buffer.Buffer, 0, count)
End If
Next
For Each context As Context In contexts
' Logic event processing
Dim packets As List(Of Packet) = context.Security.TransferIncoming()
If packets IsNot Nothing Then
For Each packet As Packet In packets
If packet.Opcode = &H5000 OrElse packet.Opcode = &H9000 Then
' ignore always
ElseIf packet.Opcode = &H2001 Then
If context Is remote_context Then
' ignore local to proxy only
' proxy to remote is handled by API
context.RelaySecurity.Send(packet)
End If
ElseIf packet.Opcode = &HA102 Then
Dim result As Byte = packet.ReadUInt8()
If result = 1 Then
Dim id As UInteger = packet.ReadUInt32()
ip = packet.ReadAscii()
port = packet.ReadUInt16()
Thread.Sleep(250)
' Should be enough time, if not, increase, but too long and C9 timeout results
Dim new_packet As New Packet(&HA102, True)
new_packet.WriteUInt8(result)
new_packet.WriteUInt32(id)
new_packet.WriteAscii(local_host)
new_packet.WriteUInt16(local_port + 1)
context.RelaySecurity.Send(new_packet)
End If
ElseIf packet.Opcode = &H3013 Then
MessageBox.Show("3013")
Else
context.RelaySecurity.Send(packet)
End If
Next
End If
Next
For Each context As Context In contexts
' Network output event processing
If context.Socket.Poll(0, SelectMode.SelectWrite) Then
Dim buffers As List(Of KeyValuePair(Of TransferBuffer, Packet)) = context.Security.TransferOutgoing()
If buffers IsNot Nothing Then
For Each kvp As KeyValuePair(Of TransferBuffer, Packet) In buffers
Dim buffer As TransferBuffer = kvp.Key
Dim packet As Packet = kvp.Value
Dim packet_bytes As Byte() = packet.GetBytes()
While True
Dim count As Integer = context.Socket.Send(buffer.Buffer, buffer.Offset, buffer.Size, SocketFlags.None)
buffer.Offset += count
If buffer.Offset = buffer.Size Then
Exit While
End If
Thread.Sleep(1)
End While
Next
End If
End If
Next
' Cycle complete, prevent 100% CPU usage
Thread.Sleep(1)
End While
End Using
End Using
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
End Class
I get the messagebox "3013" and when i hit OK , client closes.And over all , i start Gateway thread from form_Load.And btw what means "Client closed forcibly from far main computer" ?
|
|
|
07/29/2011, 10:38
|
#12
|
elite*gold: 260
Join Date: Aug 2008
Posts: 560
Received Thanks: 3,779
|
Quote:
Originally Posted by sarkoplata
By the way , where i should bind the ip for agentthread and Gatewaythread? You used localhost, but a post which you and kevin_owner confused me. IpAddress.Any or localhost?
|
You bind to Any to expose to all network interfaces or you bind to Loopback (localhost) to only allow your PC to connect. However, you cannot bind to "0.0.0.0" in my first example because the GatewayServer sends that ip address to the client. So, sending "0.0.0.0" to Silkroad to connect to is not valid.
As a result, the second example was made where you can bind to whatever address you wish, but a second parameter was added to be sent via the 0xA102 packet. So you could bind to 0.0.0.0 and choose to send 192.168.1.X so PCs on your LAN can access the server. That's all there was to that issue, it was more just a code limitation.
Quote:
ElseIf packet.Opcode = &H3013 Then
MessageBox.Show("3013")
Else
|
That causes a crash because you do not relay the packet back to the client! As a result, it is "skipped" so the client gets the next packet and it will crash. To fix, simply add: "context.RelaySecurity.Send(packet)" before or after the MessageBox. Ideally, you should write to the console rather than use a MessageBox, but for testing it is ok I guess.
Consider getting some VB.Net code to add a debug console to your GUI to make life easier! I don't have any links handy, but it should be possible to easily add a console.
If you add any more packet specific processing handlers, you have to make sure to forward them. You can also make a flag for it and just forward it at the end of the loop, but it's up to you. The power of the proxy is that you can add, drop, and edit packets, so that's why my code was setup to require manual forwarding.
Quote:
|
And btw what means "Client closed forcibly from far main computer" ?
|
The exact error is: "An existing connection was forcibly closed by the remote host". It just means the local connection was closed by the remote host. I.e., the client closed the GatewayServer's local connection at login since it no longer needs it.
It's not an error really, it's just a network event. Normally, you have to handle it differently to make sure it won't mess up your other code. The way you handle certain network events kind of varies based on what you are doing. In this case, what you could do is set a flag to ignore the error after the 0xA102 has been sent since you know the client will close the connection.
Once again, here's your code with some minor modifications (fixed 0x3013, console program, hard coded ports and addresses). You don't need to use this since you only need to fix the packet forwarding in yours, but I'll just post it for reference:
Code:
Imports System.Collections.Generic
Imports System.Net
Imports System.Net.Sockets
Imports System.Diagnostics
Imports SilkroadSecurityApi
Imports System.Threading
Imports System.Windows.Forms
Imports System.Linq
Module Module1
Sub Main(ByVal args As String())
Dim proxy As New Proxy()
proxy.Str.Start()
proxy.Int.Start()
proxy.Str.Join()
proxy.Int.Join()
End Sub
End Module
Class Proxy
Public Shared local_context As New Context()
Public Shared remote_context As New Context()
Public Shared Str As Thread = New Thread(New ThreadStart(AddressOf Proxy.GatewayThread))
Public Shared Int As Thread = New Thread(New ThreadStart(AddressOf Proxy.AgentServerThread))
Public Shared ip As String
Public Shared port As UShort
Public Class Context
Public Property Socket() As Socket
Get
Return m_Socket
End Get
Set(ByVal value As Socket)
m_Socket = value
End Set
End Property
Private m_Socket As Socket
Public Property Security() As Security
Get
Return m_Security
End Get
Set(ByVal value As Security)
m_Security = value
End Set
End Property
Private m_Security As Security
Public Property Buffer() As TransferBuffer
Get
Return m_Buffer
End Get
Set(ByVal value As TransferBuffer)
m_Buffer = value
End Set
End Property
Private m_Buffer As TransferBuffer
Public Property RelaySecurity() As Security
Get
Return m_RelaySecurity
End Get
Set(ByVal value As Security)
m_RelaySecurity = value
End Set
End Property
Private m_RelaySecurity As Security
Public Sub New()
Socket = Nothing
Security = New Security()
RelaySecurity = Nothing
Buffer = New TransferBuffer(8192)
End Sub
End Class
Public Shared Sub GatewayThread()
Try
local_context.Security.GenerateSecurity(True, True, True)
remote_context.RelaySecurity = local_context.Security
local_context.RelaySecurity = remote_context.Security
Dim contexts As New List(Of Context)()
contexts.Add(local_context)
contexts.Add(remote_context)
Using server As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
server.Bind(New IPEndPoint((IPAddress.Parse("127.0.0.1")), 16000))
server.Listen(1)
local_context.Socket = server.Accept()
End Using
Using local_context.Socket
remote_context.Socket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
Using remote_context.Socket
remote_context.Socket.Connect("gwgt1.joymax.com", 15779)
While True
For Each context As Context In contexts
' Network input event processing
If context.Socket.Poll(0, SelectMode.SelectRead) Then
Dim count As Integer = context.Socket.Receive(context.Buffer.Buffer)
If count = 0 Then
Throw New Exception("The remote connection has been lost.")
End If
context.Security.Recv(context.Buffer.Buffer, 0, count)
End If
Next
For Each context As Context In contexts
' Logic event processing
Dim packets As List(Of Packet) = context.Security.TransferIncoming()
If packets IsNot Nothing Then
For Each packet As Packet In packets
If packet.Opcode = &H5000 OrElse packet.Opcode = &H9000 Then
' ignore always
ElseIf packet.Opcode = &H2001 Then
If context Is remote_context Then
' ignore local to proxy only
' proxy to remote is handled by API
context.RelaySecurity.Send(packet)
End If
ElseIf packet.Opcode = &HA102 Then
Dim result As Byte = packet.ReadUInt8()
If result = 1 Then
Dim id As UInteger = packet.ReadUInt32()
ip = packet.ReadAscii()
port = packet.ReadUInt16()
'Int.Start()
' Thread.Sleep(250)
' Should be enough time, if not, increase, but too long and C9 timeout results
Dim new_packet As New Packet(&HA102, True)
new_packet.WriteUInt8(result)
new_packet.WriteUInt32(id)
new_packet.WriteAscii("127.0.0.1")
new_packet.WriteUInt16(16001)
context.RelaySecurity.Send(new_packet)
End If
Else
context.RelaySecurity.Send(packet)
End If
Next
End If
Next
For Each context As Context In contexts
' Network output event processing
If context.Socket.Poll(0, SelectMode.SelectWrite) Then
Dim buffers As List(Of KeyValuePair(Of TransferBuffer, Packet)) = context.Security.TransferOutgoing()
If buffers IsNot Nothing Then
For Each kvp As KeyValuePair(Of TransferBuffer, Packet) In buffers
Dim buffer As TransferBuffer = kvp.Key
Dim packet As Packet = kvp.Value
Dim packet_bytes As Byte() = packet.GetBytes()
While True
Dim count As Integer = context.Socket.Send(buffer.Buffer, buffer.Offset, buffer.Size, SocketFlags.None)
buffer.Offset += count
If buffer.Offset = buffer.Size Then
Exit While
End If
Thread.Sleep(1)
End While
Next
End If
End If
Next
' Cycle complete, prevent 100% CPU usage
Thread.Sleep(1)
End While
'End Using
End Using
End Using
Catch ex As Exception
'MessageBox.Show(ex.Message)
Console.WriteLine(ex.Message)
End Try
End Sub
Private Shared Sub AgentServerThread()
'(string[] args)
Try
Dim local_context As New Context()
local_context.Security.GenerateSecurity(True, True, True)
Dim remote_context As New Context()
remote_context.RelaySecurity = local_context.Security
local_context.RelaySecurity = remote_context.Security
Dim contexts As New List(Of Context)()
contexts.Add(local_context)
contexts.Add(remote_context)
Using server As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
server.Bind(New IPEndPoint((IPAddress.Parse("127.0.0.1")), 16001))
server.Listen(1)
local_context.Socket = server.Accept()
End Using
Using local_context.Socket
remote_context.Socket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
Using remote_context.Socket
remote_context.Socket.Connect(ip, port)
While True
For Each context As Context In contexts
' Network input event processing
If context.Socket.Poll(0, SelectMode.SelectRead) Then
Dim count As Integer = context.Socket.Receive(context.Buffer.Buffer)
If count = 0 Then
Throw New Exception("The remote connection has been lost.")
End If
context.Security.Recv(context.Buffer.Buffer, 0, count)
End If
Next
For Each context As Context In contexts
' Logic event processing
Dim packets As List(Of Packet) = context.Security.TransferIncoming()
If packets IsNot Nothing Then
For Each packet As Packet In packets
If packet.Opcode = &H5000 OrElse packet.Opcode = &H9000 Then
' ignore always
ElseIf packet.Opcode = &H2001 Then
If context Is remote_context Then
' ignore local to proxy only
' proxy to remote is handled by API
context.RelaySecurity.Send(packet)
End If
ElseIf packet.Opcode = &HA102 Then
Dim result As Byte = packet.ReadUInt8()
If result = 1 Then
Dim id As UInteger = packet.ReadUInt32()
ip = packet.ReadAscii()
port = packet.ReadUInt16()
Thread.Sleep(250)
' Should be enough time, if not, increase, but too long and C9 timeout results
Dim new_packet As New Packet(&HA102, True)
new_packet.WriteUInt8(result)
new_packet.WriteUInt32(id)
new_packet.WriteAscii("127.0.0.1")
new_packet.WriteUInt16(16001)
context.RelaySecurity.Send(new_packet)
End If
ElseIf packet.Opcode = &H3013 Then
'MessageBox.Show("3013")
Console.WriteLine("3013")
context.RelaySecurity.Send(packet)
Else
context.RelaySecurity.Send(packet)
End If
Next
End If
Next
For Each context As Context In contexts
' Network output event processing
If context.Socket.Poll(0, SelectMode.SelectWrite) Then
Dim buffers As List(Of KeyValuePair(Of TransferBuffer, Packet)) = context.Security.TransferOutgoing()
If buffers IsNot Nothing Then
For Each kvp As KeyValuePair(Of TransferBuffer, Packet) In buffers
Dim buffer As TransferBuffer = kvp.Key
Dim packet As Packet = kvp.Value
Dim packet_bytes As Byte() = packet.GetBytes()
While True
Dim count As Integer = context.Socket.Send(buffer.Buffer, buffer.Offset, buffer.Size, SocketFlags.None)
buffer.Offset += count
If buffer.Offset = buffer.Size Then
Exit While
End If
Thread.Sleep(1)
End While
Next
End If
End If
Next
' Cycle complete, prevent 100% CPU usage
Thread.Sleep(1)
End While
End Using
End Using
Catch ex As Exception
'MessageBox.Show(ex.Message)
Console.WriteLine(ex.Message)
End Try
End Sub
End Class
As long as GameGuard doesn't give you any issues on ESRO, your code should work fine.
|
|
|
07/29/2011, 16:33
|
#13
|
elite*gold: 166
Join Date: Apr 2009
Posts: 2,339
Received Thanks: 2,661
|
Quote:
Originally Posted by pushedx
You bind to Any to expose to all network interfaces or you bind to Loopback (localhost) to only allow your PC to connect. However, you cannot bind to "0.0.0.0" in my first example because the GatewayServer sends that ip address to the client. So, sending "0.0.0.0" to Silkroad to connect to is not valid.
As a result, the second example was made where you can bind to whatever address you wish, but a second parameter was added to be sent via the 0xA102 packet. So you could bind to 0.0.0.0 and choose to send 192.168.1.X so PCs on your LAN can access the server. That's all there was to that issue, it was more just a code limitation.
That causes a crash because you do not relay the packet back to the client! As a result, it is "skipped" so the client gets the next packet and it will crash. To fix, simply add: "context.RelaySecurity.Send(packet)" before or after the MessageBox. Ideally, you should write to the console rather than use a MessageBox, but for testing it is ok I guess.
Consider getting some VB.Net code to add a debug console to your GUI to make life easier! I don't have any links handy, but it should be possible to easily add a console.
If you add any more packet specific processing handlers, you have to make sure to forward them. You can also make a flag for it and just forward it at the end of the loop, but it's up to you. The power of the proxy is that you can add, drop, and edit packets, so that's why my code was setup to require manual forwarding.
The exact error is: "An existing connection was forcibly closed by the remote host". It just means the local connection was closed by the remote host. I.e., the client closed the GatewayServer's local connection at login since it no longer needs it.
It's not an error really, it's just a network event. Normally, you have to handle it differently to make sure it won't mess up your other code. The way you handle certain network events kind of varies based on what you are doing. In this case, what you could do is set a flag to ignore the error after the 0xA102 has been sent since you know the client will close the connection.
Once again, here's your code with some minor modifications (fixed 0x3013, console program, hard coded ports and addresses). You don't need to use this since you only need to fix the packet forwarding in yours, but I'll just post it for reference:
Code:
Imports System.Collections.Generic
Imports System.Net
Imports System.Net.Sockets
Imports System.Diagnostics
Imports SilkroadSecurityApi
Imports System.Threading
Imports System.Windows.Forms
Imports System.Linq
Module Module1
Sub Main(ByVal args As String())
Dim proxy As New Proxy()
proxy.Str.Start()
proxy.Int.Start()
proxy.Str.Join()
proxy.Int.Join()
End Sub
End Module
Class Proxy
Public Shared local_context As New Context()
Public Shared remote_context As New Context()
Public Shared Str As Thread = New Thread(New ThreadStart(AddressOf Proxy.GatewayThread))
Public Shared Int As Thread = New Thread(New ThreadStart(AddressOf Proxy.AgentServerThread))
Public Shared ip As String
Public Shared port As UShort
Public Class Context
Public Property Socket() As Socket
Get
Return m_Socket
End Get
Set(ByVal value As Socket)
m_Socket = value
End Set
End Property
Private m_Socket As Socket
Public Property Security() As Security
Get
Return m_Security
End Get
Set(ByVal value As Security)
m_Security = value
End Set
End Property
Private m_Security As Security
Public Property Buffer() As TransferBuffer
Get
Return m_Buffer
End Get
Set(ByVal value As TransferBuffer)
m_Buffer = value
End Set
End Property
Private m_Buffer As TransferBuffer
Public Property RelaySecurity() As Security
Get
Return m_RelaySecurity
End Get
Set(ByVal value As Security)
m_RelaySecurity = value
End Set
End Property
Private m_RelaySecurity As Security
Public Sub New()
Socket = Nothing
Security = New Security()
RelaySecurity = Nothing
Buffer = New TransferBuffer(8192)
End Sub
End Class
Public Shared Sub GatewayThread()
Try
local_context.Security.GenerateSecurity(True, True, True)
remote_context.RelaySecurity = local_context.Security
local_context.RelaySecurity = remote_context.Security
Dim contexts As New List(Of Context)()
contexts.Add(local_context)
contexts.Add(remote_context)
Using server As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
server.Bind(New IPEndPoint((IPAddress.Parse("127.0.0.1")), 16000))
server.Listen(1)
local_context.Socket = server.Accept()
End Using
Using local_context.Socket
remote_context.Socket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
Using remote_context.Socket
remote_context.Socket.Connect("gwgt1.joymax.com", 15779)
While True
For Each context As Context In contexts
' Network input event processing
If context.Socket.Poll(0, SelectMode.SelectRead) Then
Dim count As Integer = context.Socket.Receive(context.Buffer.Buffer)
If count = 0 Then
Throw New Exception("The remote connection has been lost.")
End If
context.Security.Recv(context.Buffer.Buffer, 0, count)
End If
Next
For Each context As Context In contexts
' Logic event processing
Dim packets As List(Of Packet) = context.Security.TransferIncoming()
If packets IsNot Nothing Then
For Each packet As Packet In packets
If packet.Opcode = &H5000 OrElse packet.Opcode = &H9000 Then
' ignore always
ElseIf packet.Opcode = &H2001 Then
If context Is remote_context Then
' ignore local to proxy only
' proxy to remote is handled by API
context.RelaySecurity.Send(packet)
End If
ElseIf packet.Opcode = &HA102 Then
Dim result As Byte = packet.ReadUInt8()
If result = 1 Then
Dim id As UInteger = packet.ReadUInt32()
ip = packet.ReadAscii()
port = packet.ReadUInt16()
'Int.Start()
' Thread.Sleep(250)
' Should be enough time, if not, increase, but too long and C9 timeout results
Dim new_packet As New Packet(&HA102, True)
new_packet.WriteUInt8(result)
new_packet.WriteUInt32(id)
new_packet.WriteAscii("127.0.0.1")
new_packet.WriteUInt16(16001)
context.RelaySecurity.Send(new_packet)
End If
Else
context.RelaySecurity.Send(packet)
End If
Next
End If
Next
For Each context As Context In contexts
' Network output event processing
If context.Socket.Poll(0, SelectMode.SelectWrite) Then
Dim buffers As List(Of KeyValuePair(Of TransferBuffer, Packet)) = context.Security.TransferOutgoing()
If buffers IsNot Nothing Then
For Each kvp As KeyValuePair(Of TransferBuffer, Packet) In buffers
Dim buffer As TransferBuffer = kvp.Key
Dim packet As Packet = kvp.Value
Dim packet_bytes As Byte() = packet.GetBytes()
While True
Dim count As Integer = context.Socket.Send(buffer.Buffer, buffer.Offset, buffer.Size, SocketFlags.None)
buffer.Offset += count
If buffer.Offset = buffer.Size Then
Exit While
End If
Thread.Sleep(1)
End While
Next
End If
End If
Next
' Cycle complete, prevent 100% CPU usage
Thread.Sleep(1)
End While
'End Using
End Using
End Using
Catch ex As Exception
'MessageBox.Show(ex.Message)
Console.WriteLine(ex.Message)
End Try
End Sub
Private Shared Sub AgentServerThread()
'(string[] args)
Try
Dim local_context As New Context()
local_context.Security.GenerateSecurity(True, True, True)
Dim remote_context As New Context()
remote_context.RelaySecurity = local_context.Security
local_context.RelaySecurity = remote_context.Security
Dim contexts As New List(Of Context)()
contexts.Add(local_context)
contexts.Add(remote_context)
Using server As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
server.Bind(New IPEndPoint((IPAddress.Parse("127.0.0.1")), 16001))
server.Listen(1)
local_context.Socket = server.Accept()
End Using
Using local_context.Socket
remote_context.Socket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
Using remote_context.Socket
remote_context.Socket.Connect(ip, port)
While True
For Each context As Context In contexts
' Network input event processing
If context.Socket.Poll(0, SelectMode.SelectRead) Then
Dim count As Integer = context.Socket.Receive(context.Buffer.Buffer)
If count = 0 Then
Throw New Exception("The remote connection has been lost.")
End If
context.Security.Recv(context.Buffer.Buffer, 0, count)
End If
Next
For Each context As Context In contexts
' Logic event processing
Dim packets As List(Of Packet) = context.Security.TransferIncoming()
If packets IsNot Nothing Then
For Each packet As Packet In packets
If packet.Opcode = &H5000 OrElse packet.Opcode = &H9000 Then
' ignore always
ElseIf packet.Opcode = &H2001 Then
If context Is remote_context Then
' ignore local to proxy only
' proxy to remote is handled by API
context.RelaySecurity.Send(packet)
End If
ElseIf packet.Opcode = &HA102 Then
Dim result As Byte = packet.ReadUInt8()
If result = 1 Then
Dim id As UInteger = packet.ReadUInt32()
ip = packet.ReadAscii()
port = packet.ReadUInt16()
Thread.Sleep(250)
' Should be enough time, if not, increase, but too long and C9 timeout results
Dim new_packet As New Packet(&HA102, True)
new_packet.WriteUInt8(result)
new_packet.WriteUInt32(id)
new_packet.WriteAscii("127.0.0.1")
new_packet.WriteUInt16(16001)
context.RelaySecurity.Send(new_packet)
End If
ElseIf packet.Opcode = &H3013 Then
'MessageBox.Show("3013")
Console.WriteLine("3013")
context.RelaySecurity.Send(packet)
Else
context.RelaySecurity.Send(packet)
End If
Next
End If
Next
For Each context As Context In contexts
' Network output event processing
If context.Socket.Poll(0, SelectMode.SelectWrite) Then
Dim buffers As List(Of KeyValuePair(Of TransferBuffer, Packet)) = context.Security.TransferOutgoing()
If buffers IsNot Nothing Then
For Each kvp As KeyValuePair(Of TransferBuffer, Packet) In buffers
Dim buffer As TransferBuffer = kvp.Key
Dim packet As Packet = kvp.Value
Dim packet_bytes As Byte() = packet.GetBytes()
While True
Dim count As Integer = context.Socket.Send(buffer.Buffer, buffer.Offset, buffer.Size, SocketFlags.None)
buffer.Offset += count
If buffer.Offset = buffer.Size Then
Exit While
End If
Thread.Sleep(1)
End While
Next
End If
End If
Next
' Cycle complete, prevent 100% CPU usage
Thread.Sleep(1)
End While
End Using
End Using
Catch ex As Exception
'MessageBox.Show(ex.Message)
Console.WriteLine(ex.Message)
End Try
End Sub
End Class
As long as GameGuard doesn't give you any issues on ESRO, your code should work fine.
|
Well ! I added context.relaysecurity.send(packet) for each packet-handle-sub.
Now working perfectly !
Thank you for all
Edit :
With some chars when i hit start , it doesnt do anything , some part of chardata is being parsed , and loading bar value is 0 . Why is that happens?
Edit 2 :
I dc randomly. I mean , i cant even find out why i am dcing :/ How i will know where i am doing something wrong ?
|
|
|
07/29/2011, 21:01
|
#14
|
elite*gold: 260
Join Date: Aug 2008
Posts: 560
Received Thanks: 3,779
|
Quote:
Originally Posted by sarkoplata
With some chars when i hit start , it doesnt do anything , some part of chardata is being parsed , and loading bar value is 0 . Why is that happens?
|
That sounds like you have a parsing error that is exiting out of the network loop, causing the client to hang at the loading screen. Silkroad doesn't handle any connection errors at the loading screen, so you need to make sure your code handles exceptions properly so the errors don't interfere with the network code.
If you remove all parsing code and only pass the character packet to the client, does this issue ever happen? If it doesn't, you can be sure it's related to your code. If it still happens even without parsing any packets, it's possible you have a gui bug.
I don't think it'll be a bug in the security API, but it could be related to it's usage. I didn't notice anything really with your posted code, so it should work, but you might also want to test the C# proxy to see if the same issues happen. If it only happens in once place, you know it has to be code related, so you'd have to track down the bug.
These things aren't easy, but as you spend more time with it, you get a feel of what is wrong when thing go bad. You do also have to keep track of possible mutlithread issues with deadlocks or race conditions. While the security api supports threads, you can still make code that will deadlock if you lock your own code in the wrong places. There's no easy fix for these things, it's just part of multithreaded programming.
Quote:
|
I dc randomly. I mean , i cant even find out why i am dcing :/ How i will know where i am doing something wrong ?
|
The best thing to do is to log all packets to a file. After you DC, you should be able to see the last packets sent and received. If you notice you send a certain packet each time, then you can start from there. Do keep in mind though, you may be able to send more packets at once to the server before it actually DCs you.
For example, you could send 3 packets to the server and log all 3, but maybe the first packet you sent triggered a DC. So you will need to verify all sent packets near the end of the log. You might also want to log timestamps for packets to help know when packets were sent and received to try and work those things out.
From time to time, you need to connect normally and play ESRO to make sure the DC's are not from the server itself. It could be GameGuard related or just a connection issue to the server. It's hard to tell, but these are common problems you have to work around when programming this stuff.
You also might want to try working on a Silkroad like RSRO too on the side to make sure your code does not have any logic issues. The packets might be slightly different here and there, but it's important to start out with good solid code proxy wise that you know doesn't have any issues. That way, if you keep getting DCs, you know it's either your code or network rather than maybe game security related.
|
|
|
07/29/2011, 21:16
|
#15
|
elite*gold: 166
Join Date: Apr 2009
Posts: 2,339
Received Thanks: 2,661
|
Quote:
Originally Posted by pushedx
That sounds like you have a parsing error that is exiting out of the network loop, causing the client to hang at the loading screen. Silkroad doesn't handle any connection errors at the loading screen, so you need to make sure your code handles exceptions properly so the errors don't interfere with the network code.
If you remove all parsing code and only pass the character packet to the client, does this issue ever happen? If it doesn't, you can be sure it's related to your code. If it still happens even without parsing any packets, it's possible you have a gui bug.
I don't think it'll be a bug in the security API, but it could be related to it's usage. I didn't notice anything really with your posted code, so it should work, but you might also want to test the C# proxy to see if the same issues happen. If it only happens in once place, you know it has to be code related, so you'd have to track down the bug.
These things aren't easy, but as you spend more time with it, you get a feel of what is wrong when thing go bad. You do also have to keep track of possible mutlithread issues with deadlocks or race conditions. While the security api supports threads, you can still make code that will deadlock if you lock your own code in the wrong places. There's no easy fix for these things, it's just part of multithreaded programming.
The best thing to do is to log all packets to a file. After you DC, you should be able to see the last packets sent and received. If you notice you send a certain packet each time, then you can start from there. Do keep in mind though, you may be able to send more packets at once to the server before it actually DCs you.
For example, you could send 3 packets to the server and log all 3, but maybe the first packet you sent triggered a DC. So you will need to verify all sent packets near the end of the log. You might also want to log timestamps for packets to help know when packets were sent and received to try and work those things out.
From time to time, you need to connect normally and play ESRO to make sure the DC's are not from the server itself. It could be GameGuard related or just a connection issue to the server. It's hard to tell, but these are common problems you have to work around when programming this stuff.
You also might want to try working on a Silkroad like RSRO too on the side to make sure your code does not have any logic issues. The packets might be slightly different here and there, but it's important to start out with good solid code proxy wise that you know doesn't have any issues. That way, if you keep getting DCs, you know it's either your code or network rather than maybe game security related.
|
The disconnects aren't because Game guard or any security , its for sure , because when i was using phConnector , no game errors was occuring. And also , I disable Gameguard , so i have 5minutes to spend in-game.
I will log packets to a text file , as you said, i hope it will help.
About sending packets : How i send packets with this simplest proxy example ? I mean ;
remote_context.relaysecurity.send or
remote_context.socket.send or with whatever?
Even though i tried both , packet isn't being sent to server.
And about client load problems , i wasn't ignoring errors , and they're were related to my code. Now I use Try-Catch so even there is errors , i just ignore and pass them.
I think to fix them later.
Now main thing is sending packets.
|
|
|
 |
|
Similar Threads
|
[TUT] REAL, SIMPLEST, EASIEST HP HACK
09/01/2009 - Grand Chase Hacks, Bots, Cheats & Exploits - 47 Replies
this is how to do the "REAL" HP HACKand this TUTORIAL is indeed a lot different from all previously posted HP HACK.as well as this is a lot better than SAVER HACK since with this you can be able to manipulate your HP without being noticed unlike SAVER HACK which makes you obviously a CHEATER when used in pvp...
but don't get me wrong... i NEVER state to use this in PVP... but i guess i don't have to WARN nor RESTRICT you as well... you are mere RESPONSIBLE enough for all your ACTIONS...and...
|
cracking sv in simplest way
06/23/2007 - CO2 Guides & Templates - 30 Replies
iam do this because i find alot of people saying they still dont under stand how to crack sv so iam giveing the simplest instruction i can for those who still cant crack it
TY to anantasia this is all her work iam just simplifying it this is for 1.15
very simple open cheat engine
then open script vessel
go back to cheat engine click on the little computer in the top right hand corner
select script vessel from the options
go to memory view
press ctrl + a
copy and paste all the codeing...
|
All times are GMT +1. The time now is 06:15.
|
|