i read the article on https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_server and found it very interesting as i have not done anything with websockets before. I have already managed that my client connects and the handshake takes place (was also the easy part).
However, I can't manage to set the mask on my client so that the message arrives correctly at the server. Somehow I don't quite understand this yet....
At the server it looks like this:
bool fin = (bytes[0] & 0b10000000) != 0,
mask = (bytes[1] & 0b10000000) != 0; // must be true, "All messages from the client to the server have this bit set"
int opcode = bytes[0] & 0b00001111, // expecting 1 - text message
offset = 2;
ulong msglen = (ulong)(bytes[1] & 0b01111111);
if (msglen == 126)
{
// bytes are reversed because websocket will print them in Big-Endian, whereas
// BitConverter will want them arranged in little-endian on windows
msglen = BitConverter.ToUInt16(new byte[] { bytes[3], bytes[2] }, 0);
offset = 4;
}
else if (msglen == 127)
{
// To test the below code, we need to manually buffer larger messages — since the NIC's autobuffering
// may be too latency-friendly for this code to run (that is, we may have only some of the bytes in this
// websocket frame available through client.Available).
msglen = BitConverter.ToUInt64(new byte[] { bytes[9], bytes[8], bytes[7], bytes[6], bytes[5], bytes[4], bytes[3], bytes[2] }, 0);
offset = 10;
}
if (msglen == 0)
{
Console.WriteLine("msglen == 0");
}
else if (mask)
{
byte[] decoded = new byte[msglen];
byte[] masks = new byte[4] { bytes[offset], bytes[offset + 1], bytes[offset + 2], bytes[offset + 3] };
offset += 4;
for (ulong i = 0; i < msglen; ++i)
decoded[i] = (byte)(bytes[offset + (int)i] ^ masks[i % 4]);
string text = Encoding.Default.GetString(decoded);
I have written the client in C# as TcpClient. But I just can't get it to encode the message so that it is decoded correctly at the server.
can someone of you help me? What is the inverse function to what is done at the server to decode this?
I only found Articles in Javascript or in C# without masks...
Thank u very much!
I am trying to communicate with a C# app through chrome native messaging. I am totally new to C#. So I'll create a sample app through following code. How do I add this DisplayMessage function to display the incoming message in the UI?. I have used forms for this UI.
nativeMessage.exe
using System;
using System.IO;
using System.Windows.Forms;
namespace NativeMsgApp
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string message = txt_inputBox.Text;
label1.Text = "Send Message "+ message;
OpenStandardStreamOut(message);
}
private static string OpenStandardStreamIn()
{
//// We need to read first 4 bytes for length information
Stream stdin = Console.OpenStandardInput();
int length = 0;
byte[] bytes = new byte[4];
stdin.Read(bytes, 0, 4);
length = System.BitConverter.ToInt32(bytes, 0);
string input = "";
for (int i = 0; i < length; i++)
{
input += (char)stdin.ReadByte();
}
return input;
}
private static void OpenStandardStreamOut(string stringData)
{
//// We need to send the 4 btyes of length information
string msgdata = "{\"text\":\"" + stringData + "\"}";
int DataLength = msgdata.Length;
Stream stdout = Console.OpenStandardOutput();
stdout.WriteByte((byte)((DataLength >> 0) & 0xFF));
stdout.WriteByte((byte)((DataLength >> 8) & 0xFF));
stdout.WriteByte((byte)((DataLength >> 16) & 0xFF));
stdout.WriteByte((byte)((DataLength >> 24) & 0xFF));
//Available total length : 4,294,967,295 ( FF FF FF FF )
Console.Write(msgdata);
}
private static void DisplayMessage()
{
while (OpenStandardStreamIn() != null || OpenStandardStreamIn() != "")
{
OpenStandardStreamOut("Received to Native App: " + OpenStandardStreamIn());
OpenStandardStreamOut("Recieved: " + OpenStandardStreamIn());
}
}
}
}
The UI of the App
I have a client written in C#, and a server written in python. The messages that I send over the socket are 8 bytes followed by the data, the 8 bytes are the data length.
In C# before sending, I convert the 8-byte data length too big endian as shown:
public void Send(SSLMsg m)
{
string json = m.Serialize();
byte[] data = Encoding.ASCII.GetBytes(json);
ulong dataLen = (ulong)data.Length;
byte[] dataLenPacked = packIt(dataLen);
Log("Sending " + dataLen + " " + json);
sslStream.Write(dataLenPacked);
sslStream.Write(data);
sslStream.Flush();
}
private byte[] packIt(ulong n)
{
byte[] bArr = BitConverter.GetBytes(n);
if (BitConverter.IsLittleEndian)
Array.Reverse(bArr, 0, 8);
return bArr;
}
The message is sent successfully and I am getting tied up in the python server code since the unpack format should be correct here shouldn't it?
(length,) = unpack('>Q', data)
# len(data) is 8 here
# length is 1658170187863248538
Isn't the big-endian character '>'? Why is my length so long?
UPDATE:
There was a bug where I was unpacking the wrong 8 bytes, that has been fixed, now that I am unpacking the correct data I still have the same question.
(length,) = unpack('>Q', data)
# len(data) is 8 here
# length is 13330654897016668160L
The correct length is given only if I unpack using little endian even though I sent the bytes to the server using big-endian... so I am expecting >Q to work, but instead
(length,) = unpack('<Q', data)
# len(data) is 8 here
# length is 185
Here is how I am receiving the bytes in python:
while (True):
r,w,e = select.select(...)
for c in r:
if (c == socket):
connection_accept(c)
else
# c is SSL wrapped at this point
read = 0
data = []
while (read != 8):
bytes = c.recv(min(8-read, 8))
read += len(bytes)
data.append(bytes)
joinedData = ''.join(data)
# the below length is 13330654897016668160L
# I am expecting it to be 185
(length,) = unpack('>Q', joinedData)
# the below length is 185, it should not be however
# since the bytes were sent in big-endian
(length,) = unpack('<Q', joinedData)
Something is wrong with your code:
length is 1658170187863248538
This is in hex 1703010020BB4E9A. This has nothing to do with a length of 8, no matter which endianess is involved. Instead it looks suspiciously like a TLS record:
17 - record type application data (decimal 23)
03 01 - protocol version TLS 1.0 (aka SSL 3.1)
00 20 - length of the following encrypted data (32 byte)
..
Since according to your code your are doing SSL there is probably something wrong in your receiver. My guess is that you read from the plain socket instead of the SSL socket and thus read the encrypted data instead of the decrypted ones.
On client side, when you write data to stream, you're doing two Write calls:
sslStream.Write(dataLenPacked);
sslStream.Write(data);
sslStream.Flush();
MSDN says about NetworkStream.Write: The Write method blocks until the requested number of bytes are sent or a SocketException is thrown. On the server side, there is no guarantee that you will receive all bytes in one receive call - it depends on OS, eth driver/config and etc. So, you have to handle this scenario. As I can see in you're handling it by reading 8 or less bytes, but socket.recv says, it's better to receive by bigger portions. Here is my implementation of the server on Python. It creates binary file in the current folder with received bytes - might be helpful to analyze what's wrong. To set listening port need to use -p/--port argument:
#!/usr/bin/env python
import sys, socket, io
import argparse
import struct
CHUNK_SIZE = 4096
def read_payload(connection, payload_len):
recv_bytes = 0
total_data = ""
while (recv_bytes < payload_len):
data = connection.recv(CHUNK_SIZE)
if not data:
break
total_data += data
recv_bytes += len(data)
if len(total_data) != payload_len:
print >> sys.stderr, "-ERROR. Expected to read {0} bytes, but have read {0} bytes\n".format(payload_len, len(total_data))
return total_data
def handle_connection(connection, addr):
total_received = 0
addrAsStr = "{0}:{1}".format(addr[0], addr[1])
# write receved bytes to file for analyzis
filename = "{0}_{1}.bin".format(addr[0], addr[1])
file = io.FileIO(filename, "w")
print "Connection from {0}".format(addrAsStr)
try:
# loop for handling data transfering for particular connection
while True:
header = connection.recv(CHUNK_SIZE)
header_len = len(header)
total_received += header_len
if header_len == 0:
break
if header_len < 8:
print >> sys.stderr, "-ERROR. Received header with len {0} less than 8 bytes!\n".format(header_len)
break
print("Header len is {0} bytes".format(len(header)))
# extract payload length - it's first 8 bytes
real_header = header[0:8]
file.write(real_header)
# more about unpack - https://docs.python.org/3/library/struct.html#module-struct
# Byte order - network (= big-endian), type - unsigned long long (8 bytes)
payload_len = struct.unpack("!Q", real_header)[0]
print("Payload len is {0} bytes".format(payload_len))
# extract payload from header
payload_in_header = header[8:] if header_len > 8 else ""
if len(payload_in_header) > 0:
print "Payload len in header is {0} bytes".format(len(payload_in_header))
file.write(payload_in_header)
# calculate remains
remains_payload_len = payload_len - len(payload_in_header)
remains_payload = read_payload(connection, remains_payload_len)
payload = payload_in_header + remains_payload
print("Payload is '{0}'".format(payload))
if remains_payload:
file.write(remains_payload)
else:
break
total_received += len(remains_payload)
finally:
file.close()
return total_received
def main():
parser = argparse.ArgumentParser()
parser.add_argument('-p', '--port', required=True)
args = parser.parse_args()
# listen tcp socket on all interfaces
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("0.0.0.0", int(args.port)))
s.listen(1)
# loop for handling incoming connection
while True:
print "Waiting for a connection..."
(connection, addr) = s.accept()
addrAsStr = "{0}:{1}".format(addr[0], addr[1])
try:
total_received = handle_connection(connection, addr)
print "Handled connection from {0}. Received: {1} bytes\n".format(addrAsStr, total_received)
finally:
# Clean up the connection
connection.close()
if __name__ == "__main__":
main()
To make this example full, here is C# client. It uses one external library - Newtonsoft.Json for serialization:
using Newtonsoft.Json;
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace SimpleTcpClient
{
class SimpleTcpClient : IDisposable
{
readonly TcpClient _client;
public SimpleTcpClient(string host, int port)
{
_client = new TcpClient(host, port);
}
public void Send(byte[] payload)
{
// Get network order of array length
ulong length = (ulong)IPAddress.HostToNetworkOrder(payload.LongLength);
var stream = _client.GetStream();
// Write length
stream.Write(BitConverter.GetBytes(length), 0, sizeof(long));
// Write payload
stream.Write(payload, 0, payload.Length);
stream.Flush();
Console.WriteLine("Have sent {0} bytes", sizeof(long) + payload.Length);
}
public void Dispose()
{
try { _client.Close(); }
catch { }
}
}
class Program
{
class DTO
{
public string Name { get; set; }
public int Age { get; set; }
public double Weight { get; set; }
public double Height { get; set; }
public string RawBase64 { get; set; }
}
static void Main(string[] args)
{
// Set server name/ip-address
string server = "192.168.1.101";
// Set server port
int port = 8080;
string[] someNames = new string[]
{
"James", "David", "Christopher", "George", "Ronald",
"John", "Richard", "Daniel", "Kennet", "Anthony",
"Robert","Charles", "Paul", "Steven", "Kevin",
"Michae", "Joseph", "Mark", "Edward", "Jason",
"Willia", "Thomas", "Donald", "Brian", "Jeff"
};
// Init random generator
Random rnd = new Random(Environment.TickCount);
int i = 1;
while (true) {
try {
using (var c = new SimpleTcpClient(server, port)) {
byte[] rawData = new byte[rnd.Next(16, 129)];
rnd.NextBytes(rawData);
// Create random data transfer object
var d = new DTO() {
Name = someNames[rnd.Next(0, someNames.Length)],
Age = rnd.Next(10, 101),
Weight = rnd.Next(70, 101),
Height = rnd.Next(165, 200),
RawBase64 = Convert.ToBase64String(rawData)
};
// UTF-8 doesn't have endianness - so we can convert it to byte array and send it
// More about it - https://stackoverflow.com/questions/3833693/isn-t-on-big-endian-machines-utf-8s-byte-order-different-than-on-little-endian
var bytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(d));
c.Send(bytes);
}
}
catch (Exception ex) {
Console.WriteLine("Get exception when send: {0}\n", ex);
}
Thread.Sleep(200);
i++;
}
}
}
}
According to https://msdn.microsoft.com/en-us/library/z78xtwts(v=vs.110).aspx you are reversing 9 bytes when you invoke:
if (BitConverter.IsLittleEndian)
Array.Reverse(bArr, 0, 8);
and according to https://www.displayfusion.com/Discussions/View/converting-c-data-types-to-c/?ID=38db6001-45e5-41a3-ab39-8004450204b3 a ulong in C# is only 8 bytes.
I don't think that this is necessarily an answer, but maybe it's a clue?
I'm trying to take a .txt file which icontains some binary. E.g.
&
ns16A086C66661C9 D% C(0 ¢À
&
ns167C0BC683548A €\D% €‹C(0 ¢À
&
ns16BC3BAF56248CÍ=D%¤pìC(0 ¢À
&
ns16A89FBA902317q%¤D%"÷C(0 ¢À
&
ns16EC1F720BB5983ó1C%×C(0ž¢À
&
ns1690E7C450794F ÀD% €ŠC(0 ¢À
&
ns16A408EAB24E2Fš©ED%…‹éC(0 ¢À
&
ns16F832E429A2C4 #{D% €ÍC(0 ¢À
&
ns160CD74622F0D3
—yD%ÍløC(0 ¢À
&
ns16485A3F0BA1D7öˆyD%…+¹C(0ž¢À
&
ns16EC35866601D4 #HD% ÀD(0 ¢À
&
ns1660F189ED2318 «D% èB(0 ¢À
&
ns16
to change it into string. However I do not know how to approach this using Google.Protobuf's library.
This is what I have now, I can't seem to figure out how to parse the data read from the .txt, put it through Google.Protobuf's decoder??? and get the string out proper.
namespace ConsoleApplicationTest
{
class Program
{
static void Main(string[] args)
{
byte[] array = File.ReadAllBytes("C:/brokerdata.txt");
Google.Protobuf.IMessage<string> a = new IMessage<string>();
Google.Protobuf.MessageParser<a> bb = new MessageParser<a>(() => "");
bb.ParseFrom(array);
string s = System.Text.Encoding.UTF8.GetString(array, 0, array.Length);
Console.Out.WriteLine(s);
Console.WriteLine("First byte: {0}", array[0]);
Console.WriteLine("Last byte: {0}", array[array.Length - 1]);
Console.WriteLine(array.Length);
//Console.Out.WriteLine(array);
Console.ReadKey();
}
}
}
Im currently writing a program that is encrypting a password (using a custom method), and then encoding the password to Base64 using the To/FromBase64Transform classes. The problem is, when i encode my encrypted password, I am unable to decode it back to its proper encrypted state. The Base64Helper class is just a wrapper for the To/FromBase64Transform classes.
My Test Code:
static void Main(string[] args)
{
bool Worked = false;
string Password = "testing";
Console.WriteLine("Password: " + Password);
// == Encode then decode 64 test. DecPass64 should equal password == //
// Encodes to Base64 using ToBase64Transform
string EncPass64 = Base64Helper.EncodeString(Password);
// Decodes a Base64 string using FromBase64Transform
string DecPass64 = Base64Helper.DecodeString(EncPass64);
// Test if base 64 ecoding / decoding works
Worked = (Password == DecPass64);
Console.WriteLine();
Console.WriteLine("Base64 Pass Encoded: " + EncPass64);
Console.WriteLine("Base64 Pass Decoded: " + DecPass64);
Console.WriteLine("Base64 Encode to Base64 Decode Worked? : " + Worked); // True
// gspassenc uses XOR to switch passwords back and forth between encrypted and decrypted
string GsEncodedPass = gspassenc(Password);
string GsDecodedPass = gspassenc(GsEncodedPass);
Worked = (Password == GsDecodedPass);
// GsDecodedPass should equal the original Password
Console.WriteLine();
Console.WriteLine("GsPass Encoded: " + GsEncodedPass);
Console.WriteLine("GsPass Decoded: " + GsDecodedPass);
Console.WriteLine("GsEncode to GsDecode Worked? : " + Worked); // True
// Bas64 encode the encrypted password. Then decode the base64. B64_GsDecodedPass should equal
// the GsEncoded Password... But it doesn't for some reason!
string B64_GsEncodedPass = Base64Helper.EncodeString(GsEncodedPass);
string B64_GsDecodedPass = Base64Helper.DecodeString(B64_GsEncodedPass);
Worked = (B64_GsDecodedPass == GsEncodedPass);
// Print results
Console.WriteLine();
Console.WriteLine("Base64 Encoded GsPass: " + B64_GsEncodedPass);
Console.WriteLine("Base64 Decoded GsPass: " + B64_GsDecodedPass);
Console.WriteLine("Decoded == GS Encoded Pass? : " + Worked); // False
// Stop console from closing till we say so
Console.Read();
}
private static int gslame(int num)
{
int c = (num >> 16) & 0xffff;
int a = num & 0xffff;
c *= 0x41a7;
a *= 0x41a7;
a += ((c & 0x7fff) << 16);
if (a < 0)
{
a &= 0x7fffffff;
a++;
}
a += (c >> 15);
if (a < 0)
{
a &= 0x7fffffff;
a++;
}
return a;
}
private static string gspassenc(string pass)
{
int a = 0;
int num = 0x79707367; // gspy
int len = pass.Length;
char[] newPass = new char[len];
for (int i = 0; i < len; ++i)
{
num = gslame(num);
a = num % 0xFF;
newPass[i] = (char)(pass[i] ^ a);
}
return new String(newPass);
}
And the result is:
Any help will be much appreciated!
UPDATE: Here is my Base64Helper Class:
class Base64Helper
{
public static string DecodeString(string encoded)
{
return Encoding.ASCII.GetString(Convert.FromBase64String(encoded));
}
public static string EncodeString(string decoded)
{
return Convert.ToBase64String(Encoding.ASCII.GetBytes(decoded));
}
}
It's because of the way you are interfering with the Unicode "Chars" of the string with the encoding algorithm and then constructing a String using those "Chars" which then might not form a valid Unicode stream.
When converting from your String to a Byte array and back again, you need to decide which encoding to use....and you can't arbitrarily change the byte stream (via your encryption routine) and expect it to produce a valid string when being converted back.
I've modified your code to show some string to byte[] conversion steps...you can adjust these depending on your need.
static void Main(string[] args)
{
bool Worked = false;
string Password = "testing";
Console.WriteLine("Password: " + Password);
// == Encode then decode 64 test. DecPass64 should equal password == //
// Encodes to Base64 using ToBase64Transform
string EncPass64 = Base64Helper.EncodeString(Password);
// Decodes a Base64 string using FromBase64Transform
string DecPass64 = Base64Helper.DecodeString(EncPass64);
// Test if base 64 ecoding / decoding works
Worked = (Password == DecPass64);
Console.WriteLine();
Console.WriteLine("Base64 Pass Encoded: " + EncPass64);
Console.WriteLine("Base64 Pass Decoded: " + DecPass64);
Console.WriteLine("Base64 Encode to Base64 Decode Worked? : " + Worked); // True
// gspassenc uses XOR to switch passwords back and forth between encrypted and decrypted
byte [] passwordbytes = Encoding.UTF8.GetBytes(Password);
byte [] bytes_GsEncodedPass = gspassenc(passwordbytes);
string GsEncodedPass = Encoding.UTF8.GetString(bytes_GsEncodedPass);
byte[] bytes_GsDecodedPass = gspassenc(bytes_GsEncodedPass);
string GsDecodedPass = Encoding.UTF8.GetString(bytes_GsDecodedPass);
Worked = (Password == GsDecodedPass);
// GsDecodedPass should equal the original Password
Console.WriteLine();
Console.WriteLine("GsPass Encoded: " + GsEncodedPass);
Console.WriteLine("GsPass Decoded: " + GsDecodedPass);
Console.WriteLine("GsEncode to GsDecode Worked? : " + Worked); // True
// Bas64 encode the encrypted password. Then decode the base64. B64_GsDecodedPass should equal
// the GsEncoded Password... But it doesn't for some reason!
string B64_GsEncodedPass = Convert.ToBase64String(bytes_GsEncodedPass);
byte []bytes_B64_GsDecodedPass = Convert.FromBase64String(B64_GsEncodedPass);
string B64_GsDecodedPass = Encoding.UTF8.GetString(bytes_B64_GsDecodedPass);
Worked = (B64_GsDecodedPass == GsEncodedPass);
// Print results
Console.WriteLine();
Console.WriteLine("Base64 Encoded GsPass: " + B64_GsEncodedPass);
Console.WriteLine("Base64 Decoded GsPass: " + B64_GsDecodedPass);
Console.WriteLine("Decoded == GS Encoded Pass? : " + Worked); // False
// Stop console from closing till we say so
Console.Read();
}
private static int gslame(int num)
{
int c = (num >> 16) & 0xffff;
int a = num & 0xffff;
c *= 0x41a7;
a *= 0x41a7;
a += ((c & 0x7fff) << 16);
if (a < 0)
{
a &= 0x7fffffff;
a++;
}
a += (c >> 15);
if (a < 0)
{
a &= 0x7fffffff;
a++;
}
return a;
}
private static byte[] gspassenc(byte [] pass)
{
int a = 0;
int num = 0x79707367; // gspy
int len = pass.Length;
byte[] newPass = new byte[len];
for (int i = 0; i < len; ++i)
{
num = gslame(num);
a = num % 0xFF;
newPass[i] = (byte)(pass[i] ^ a);
}
return newPass;
}
}