Matthias Hoste Matthias Hoste - 10 days ago 4
C# Question

Java client throws overflow exception on c# server

So I made a server c# and a client in c#, to expand usage I made a java client, but when I run the client it results in an overflow exception on the server for some reason, this is the code for the c# client(works flawlessly):

private static TcpClient T = new TcpClient();
static byte[] SendData;
static X509Certificate2 Cert;
internal static string InitIIP(string Data, string proxyHost = "127.0.0.1", int proxyPort = 9050, string destHost = "ipalbloeis2gf4vo.onion", int destPort = 666)
{
HttpProxyClient HPC = new HttpProxyClient();
return "";
}
internal static string Init(string Data, string proxyHost = "127.0.0.1", int proxyPort = 9050, string destHost = "ipalbloeis2gf4vo.onion", int destPort = 666)
{
Process[] pname = Process.GetProcessesByName("tor");
if (pname.Length == 0)
MessageBox.Show("Hmmm, we couldnt see if a tor process is running, make sure it is otherwise server connection will fail, trying to continue.....");
try
{
if (!T.Connected)
{
Socks5ProxyClient p = new Socks5ProxyClient();
p.ProxyHost = proxyHost;
p.ProxyPort = proxyPort;
p.ProxyUserName = "";
p.ProxyPassword = "";
T = p.CreateConnection(destHost, destPort);
}
while (true)
{
SendData = Encoding.ASCII.GetBytes(Data);
byte[] buffer = new byte[4];
NetworkStream serverStream = T.GetStream();
buffer = new byte[4];
buffer = BitConverter.GetBytes(SendData.Length);
serverStream.Write(buffer, 0, 4);
serverStream.Flush();
serverStream.Write(SendData, 0, SendData.Length);
serverStream.Flush();
byte[] inbuffer = new byte[4];
buffer = new byte[4];
int readBytes = serverStream.Read(buffer, 0, 4);
int MessageSize = BitConverter.ToInt32(buffer, 0);
byte[] bufferreader = new byte[MessageSize];
readBytes = serverStream.Read(bufferreader, 0, MessageSize);
return Encoding.ASCII.GetString(bufferreader);
}
}
catch (Exception ex)
{
return null;
}
}


}

and this is the same code but for my java client:

static Proxy tor = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress("127.0.0.1", 9050));
private static Socket s = new Socket(tor);
static InetSocketAddress SERVERADDR = InetSocketAddress.createUnresolved("ipalbloeis2gf4vo.onion", 666);
static byte[] SendData;
public static String Do(String Data)
{
try
{
if(!s.isConnected())
s.connect(SERVERADDR);
while(true)
{
SendData = Data.getBytes();
byte[] buffer = new byte[4];
DataOutputStream serverStream = new DataOutputStream(s.getOutputStream());
DataInputStream serverInStream = new DataInputStream(s.getInputStream());
buffer = new byte[4];
buffer = BitConverter.GetBytes(SendData.length);
serverStream.write(buffer, 0, 4);
serverStream.flush();
serverStream.write(SendData, 0, SendData.length);
serverStream.flush();
buffer = new byte[4];
int readBytes = serverInStream.read(buffer, 0, 4);
int MessageSize = BitConverter.ToInt32(buffer, 0);
byte[] bufferreader = new byte[MessageSize];
readBytes = serverInStream.read(bufferreader, 0, MessageSize);
return new String(bufferreader);
}
}
catch(Exception e)
{
JOptionPane.showMessageDialog(null, "Connection Failed" + e.getMessage(), "Status", JOptionPane.INFORMATION_MESSAGE);
return "ERR";
}
}


And this is the function on the server that handles the client connections:

private void Do()
{
int requestCount = 0;
string serverResponse = null;
string rCount = null;
string dataFromClient = null;
Byte[] sendBytes = null;
requestCount = 0;
Responder.Responder R = new Responder.Responder();
while ((true))
{
try
{
byte[] buffer = new byte[4];
requestCount = requestCount + 1;
NetworkStream networkStream = clientSocket.GetStream();
//networkStream.AuthenticateAsServer(ServerCertificate.Servercertificate(), false, SslProtocols.Tls12, true);
buffer = new byte[4];
int readBytes = networkStream.Read(buffer, 0, 4);
if (readBytes == 0)
break;
int MessageSize = BitConverter.ToInt32(buffer, 0); //this throws the exception
byte[] bufferreader = new byte[MessageSize];
clientSocket.ReceiveBufferSize = MessageSize;
readBytes = networkStream.Read(bufferreader, 0, MessageSize);
Console.WriteLine(Convert.ToString(MessageSize));
rCount = Convert.ToString(requestCount);
dataFromClient = Encoding.ASCII.GetString(bufferreader);
byte[] outbuffer = new byte[4];
serverResponse = R.Respond(dataFromClient, K, clientSocket);
sendBytes = Encoding.ASCII.GetBytes(serverResponse);
outbuffer = new byte[4];
outbuffer = BitConverter.GetBytes(sendBytes.Length);
networkStream.Write(outbuffer, 0, 4);
networkStream.Flush();
clientSocket.SendBufferSize = sendBytes.Length;
MessageBox.Show(serverResponse);
networkStream.Write(sendBytes, 0, sendBytes.Length);
networkStream.Flush();
}
catch (Exception ex)
{
EndPointHandler.RemoveEndPoint(clientSocket);
clientSocket.Close();
Console.WriteLine("User Server >> " + ex.ToString());
Thread.CurrentThread.Abort();
}
}
EndPointHandler.RemoveEndPoint(clientSocket);
Console.WriteLine("User Server >> " + "Client No:" + Convert.ToString(clNo) + " Stopped!");
}


Exact Exception message: System.OverflowException: Arithmetic operation resulted in an overflow.

I looked on google but was unable to find a fix for this

Answer

Possibly Endianness Problems

There's two mainstream ways of organising bytes; Little endian and big endian:

enter image description here

In short, you appear to be mixing the two. Java is big endian, .NET is usually little endian (as far as I'm aware, it doesn't strictly specify which it should be). When C# attempts to read the big endian number sent from Java, you'll end up with seemingly random numeric problems.

To Fix it

Make sure you use the same endianness at both ends. A common technique to avoid it all together is send strings rather than raw integer bytes.

A rough example (C#):

// Little endian int -> bytes
public static void GetBytes(int value,byte[] result,int offset){
    result[offset]=(byte)value;
    result[offset+1]=(byte) (value>>8);
    result[offset+2]=(byte) (value>>16);
    result[offset+3]=(byte) (value>>24);
}

// Little endian bytes -> int
public static int ToInt32(byte[] data,int offset){
    return    ( (int) data[offset] ) | 
            ( ( (int) data[offset+1] ) << 8 ) | 
            ( ( (int) data[offset+2] ) << 16 ) | 
            ( ( (int) data[offset+3] ) << 24 );
}

As an extra side note, your protocol is vulnerable - I could crash your server by making it run out of memory pretty easily. Watch out for things like that if you're designing a custom protocol.

Comments