Add PPOOE layer tp packet - convert length into byte - c#

I have application that play Pcap files and i try to add function that wrap my packet with PPPOE layer.
so almost all done except large packets that i didn't understand yet how to set the new langth after add PPPOE layer.
For example this packet:
As you can see this packet length is 972 bytes (03 cc), and all i want is to convert it to decimal, after see this packet byte[] in my code i can see that this value converted into 3 and 204 in my packet byte[], so my question is how this calculation works ?

Those two bytes represents a short (System.Int16) in bigendian notation (most significant byte first).
You can follow two approaches to get the decimal value of those two bytes. One is with the BitConverter class, the other is by doing the calculation your self.
BitConverter
// the bytes
var bytes = new byte[] {3, 204};
// are the bytes little endian?
var littleEndian = false; // no
// What architecure is the BitConverter running on?
if (BitConverter.IsLittleEndian != littleEndian)
{
// reverse the bytes if endianess mismatch
bytes = bytes.Reverse().ToArray();
}
// convert
var value = BitConverter.ToInt16( bytes , 0);
value.Dump(); // or Console.WriteLine(value); --> 972
Calculate your self
base 256 of two bytes:
// the bytes
var bytes2 = new byte[] {3, 204};
// [0] * 256 + [1]
var value2 = bytes2[0] * 256 + bytes2[1]; // 3 * 256 + 204
value2.Dump(); // 972

Related

What's wrong with this 2-bytes-to-int conversion?

I'm trying to parse a JPEG file. This page says that the format is the following :
0xFF+Marker Number(1 byte)+Data size(2 bytes)+Data(n bytes)
So, when I encounter a 0xFF, I read the data like this (s is the JPEG file stream) :
int marker, size;
byte[] data;
//marker number (1 byte)
marker = s.ReadByte();
//size (2 bytes)
byte[] b = new byte[2];
s.Read(b, 0, 2);
size = BitConverter.ToInt16(b, 0);
Problem is, size's value after that is -7937 (which causes the next lines to raise an exception because I try to allow a -7937-long byte[]). b[0] == 255 and b[1] == 224.
I suspect I don't use BitConverter.ToInt16 properly, but I can't find what I did wrong.
The BitConverter doc page says that "The order of bytes in the array must reflect the endianness of the computer system's architecture", but when I do this :
byte a = b[0]; b[0] = b[1]; b[1] = a;
size = BitConverter.ToInt16(b, 0);
...I get size == -32 which is not really better.
What's the problem ?
Integers are stored in Big Endian order in JPEG. If you are on a little endian system (e.g. Intel) you need to reverse the order of the bytes in the length field. Length fields are unsigned.
The data in question was an unsigned int. Using the uint type and BitConverter.ToUInt16 fixed it.

How to decode an utf8 encoded string split in two buffers right in between a 4 byte long char?

A character in UTF8 encoding has up to 4 bytes. Now imagine I read from a stream into one buffer and then into the another. Unfortunately it just happens to be that at the end of the first buffer 2 chars of the 4 byte UTF8 encoded char are left and at the beginning of the the second buffer the rest 2 bytes.
Is there a way to partially decode that string (while leaving the 2 rest byte) without copying those two buffers into one big
string str = "Hello\u263AWorld";
Console.WriteLine(str);
Console.WriteLine("Length of 'HelloWorld': " + Encoding.UTF8.GetBytes("HelloWorld").Length);
var bytes = Encoding.UTF8.GetBytes(str);
Console.WriteLine("Length of 'Hello\u263AWorld': " + bytes.Length);
Console.WriteLine(Encoding.UTF8.GetString(bytes, 0, 6));
Console.WriteLine(Encoding.UTF8.GetString(bytes, 7, bytes.Length - 7));
This returns:
Hello☺World
Length of 'HelloWorld': 10
Length of 'Hello☺World': 13
Hello�
�World
The smiley face is 3 bytes long.
Is there a class that deals with split decoding of strings?
I would like to get first "Hello" and then "☺World" reusing the reminder of the not encoded byte array. Without copying both arrays into one big array. I really just want to use the reminder of the first buffer and somehow make the magic happen.
You should use a Decoder, which is able to maintain state between calls to GetChars - it remembers the bytes it hasn't decoded yet.
using System;
using System.Text;
class Test
{
static void Main()
{
string str = "Hello\u263AWorld";
var bytes = Encoding.UTF8.GetBytes(str);
var decoder = Encoding.UTF8.GetDecoder();
// Long enough for the whole string
char[] buffer = new char[100];
// Convert the first "packet"
var length1 = decoder.GetChars(bytes, 0, 6, buffer, 0);
// Convert the second "packet", writing into the buffer
// from where we left off
// Note: 6 not 7, because otherwise we're skipping a byte...
var length2 = decoder.GetChars(bytes, 6, bytes.Length - 6,
buffer, length1);
var reconstituted = new string(buffer, 0, length1 + length2);
Console.WriteLine(str == reconstituted); // true
}
}

Read Specific Bytes Out of Byte Array C#

I am a newbie with a question regarding reading specific bytes out of an array in C#. I received an array response that is 128 bytes long and I am looking to read and store the first 4 bytes of the array. How do I do so?
I've read a number of posts about shifting bytes but was a bit confused and I am looking to get going in the right direction.
Use one of the Array.Copy overloads:
byte[] bytes = new byte[4];
Array.Copy(originalArray, bytes, bytes.Length);
Use Array.Copy method:
// your original array
var sourceArray = new byte[128];
// create a new one with the size you need
var firstBytes = new byte[4];
// copy the required number of bytes.
Array.Copy(sourceArray, 0, firstBytes, 0, firstBytes.Length);
If you do not need the rest of the data in the original array, you can also resize it, truncating everything after the first 4 bytes:
Array.Resize(ref sourceArray, 4);
Read the first 4 bytes in 4 different variables:
byte first = array[0],
second = array[1],
third = array[2],
forth = array[4];
Read them as one 32-bit long integer:
int result =
first << 24 ||
second << 16 ||
third << 8 ||
forth;
The x << n operator shifts the bits of number x, n times to the left. You are effectively moving the bytes of first 24 positions to the left, thus first will be stored in bits with indices 24 to 31 like that:
first 00000000 00000000 00000000
Next, move second 16 positions to the left, thus storing it in bits 16 to 23 and so on:
first second 00000000 00000000
Wikipedia provides a good summary of bitwise operations if you need more details.
Example from a network stream.
byte[] bytesRead = 0;
using (NetworkStream stream = client.GetStream())
{
byte[] length = new byte[4];
bytesRead = stream.Read(length, 0, 4);
}
bytesRead contains the first 4 bytes stored in the networkstream.
You could use the Take method. Although, this is only available if you are using .NET 3.5 or later. You will need to have using System.Linq; at the top of the .cs file.
var bytes = originalArray.Take(4).ToArray();

Byte size of Packet

I am trying to implement this protocol (http://developer.valvesoftware.com/wiki/Source_RCON_Protocol) from a C# NET application. The part applicable there to the code I am implementing is under heading "Receiving". However, I am not positive I have the byte sizes correct when constructing the packet.
Here is my function to construct a packet...
private static byte[] ConstructPacket(int request_id, int cmdtype, string cmd)
{
MemoryStream stream = new MemoryStream();
using (BinaryWriter writer = new BinaryWriter(stream))
{
byte[] cmdBytes = ConvertStringToByteArray(cmd);
int packetSize = 12 + cmdBytes.Length;
// Packet Contents
writer.Write((int)packetSize); // Byte size of Packet not including This
writer.Write((int)request_id); // 4 Bytes
writer.Write((int)cmdtype); // 4 Bytes
writer.Write(cmdBytes); // 8 Bytes ??
// NULL String 1
writer.Write((byte)0x00);
writer.Write((byte)0x00);
// NULL String 2
writer.Write((byte)0x00);
writer.Write((byte)0x00);
// Memory Stream to Byte Array
byte[] buffer = stream.ToArray();
return buffer;
}
}
According to the Protocol specifications, packetSize is the byte size of the packet not including itself.
The first 2 (int) would make it 8 bytes...
The "cmdBytes", which in this paticular instance is "testpass" would be 8 bytes I believe...
Then the final 2 null delimited strings (If I set these up right) would be 4 bytes.
So by my calculations, the packet should be 20 bytes big, but it doesn't seem to be working properly. Are the values I am thinking these should all be correct and am I setting the NULL delmited strings properly for C# .NET?
You write two zeros too many. Pretty easy to see in the examples, they all end with two zeros, not four.
You should probably call writer.Flush() after the last writer.Write(). Otherwise you run the risk of disposing the writer before it's finished writing everything to the stream.

How to produce 8 bytes from 4 bytes with a reproducible operation?

I've 4 bytes of data and need an 8 bytes array for a security operation. I should produce these 8 bytes form the 4 bytes byte array and this should be reproducible.
I was thinking of using exact byte array and adding 4 extra bytes and fill them with AND, OR, XOR... of the initial array in a known sequence. I'm not sure if it's a good idea. I just need an 8 byte array from this 4 bytes and the operation should be reproducible (same 8 bytes with same given 4 bytes). Please give an example in C#
Why not just pad the existing 4 bytes with another 4 bytes of zeroes? Or repeat the original 4 bytes. For example:
static byte[] Pad(byte[] input)
{
// Alternatively use Array.Resize
byte[] output = new byte[input.Length + 4];
Buffer.BlockCopy(input, 0, output, 0, input.Length);
return output;
}
static byte[] Repeat(byte[] input)
{
byte[] output = new byte[input.Length * 2];
Buffer.BlockCopy(input, 0, output, 0, input.Length);
Buffer.BlockCopy(input, 0, output, input.Length, input.Length);
return output;
}
Both of these fulfil your original criteria, I believe... but I suspect you're looking for something else. If that's the case, you need to be explicit about what you need.
EDIT: As I've said in the comments, you're basically not adding any real security here - padding will make that clearer, IMO. On the other hand, if you do want some security-through-obscurity, you could find a random number generator that allows seeding, and use that as a starting point. For example:
// Don't use this - see below. Just the concept...
int seed = BitConverter.ToInt32(input, 0); // TODO: Cope with endianness
Random rng = new Random(seed);
byte[] output = new byte[8];
Buffer.BlockCopy(input, 0, output, 0, 4);
for (int i = 4; i < 8; i++) {
output[i] = (byte) rng.Next(256);
}
Now, the reason I've got the comment above is that you probably need an algorithm which is guaranteed not to change between versions of .NET. Find code to something like the Mersenne Twister, for exmaple.
There are multiple methods of doing padding for block ciphers.
This Wikipedia article covers some of the more accepted solutions: http://en.wikipedia.org/wiki/Padding_(cryptography)#Padding_methods
Barring any other considerations, I would use PKCS#7 padding.
How about
bytes.Concat(bytes)
I would be very careful. If a security operation requires 64 bits worth of data it is probably because it requires that much data. If you create your 64 bits from 32 bits with a known reproducible formula you will still only have 32 bits worth of data.
If the security is not affected by the data you have you can just fill the the remaining four bytes with ones or zeros. But you should really try to get 8 bytes of "real" data.

Categories