Вычисление контрольной суммы для TCP-пакетов из байтовых массивовC#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Вычисление контрольной суммы для TCP-пакетов из байтовых массивов

Сообщение Anonymous »

Недавно я задал аналогичный вопрос, но отметил его как решенный, так как думал, что нашел ответ, хотя на самом деле мой код работал только в определенных случаях, пропуская при этом большую часть случаев. В любом случае я использую WinDivert для захвата TCP-пакетов с целью вычисления контрольных сумм и поиска некорректных пакетов. Массивы байтов имеют обратный порядок байтов, поскольку они извлекаются непосредственно из WinDivert. Я также прочитал RFC о контрольной сумме TCP и не могу понять, что я делаю неправильно. Я даже добавил проверку длины, так как заметил следующее... Если сегмент содержит нечетное количество октетов заголовка и текста для контрольной суммы, последний октет дополняется справа нулями. Но даже в этом случае мои расчеты контрольной суммы терпят неудачу, даже когда полезной нагрузки нет. Например, пакет, который содержал только 40 байтов (что означает отсутствие полезной нагрузки) и имел адрес источника 172.64.151.73 и адрес назначения 192.168.50.134, и мой код дал правильную контрольную сумму, однако, когда полезная нагрузка все еще равна 40, но с обратными адресами (это означает, что источник теперь 192.168.50.134) я получаю совершенно неправильную контрольную сумму. Кажется, мой код также выдает неправильный ответ для большинства пакетов с любой полезной нагрузкой
public override ushort ComputeChecksum(byte[] ipv4Header, byte[] transportHeader, byte[] payload)
{
int pseudoHeaderLength = 12; // Pseudo-header is 12 bytes
int tcpLength = transportHeader.Length;
int payloadLength = payload.Length;
int totalLength = pseudoHeaderLength + tcpLength + payloadLength;
bool isOddLength = (totalLength % 2 != 0);

byte[] pseudoHeaderAndTcpSegment = new byte[totalLength + (isOddLength ? 1 : 0)];
Console.WriteLine($"pseudoHeaderLength:{pseudoHeaderLength} transportHeader.Length:{tcpLength} payloadLength:{payloadLength} totalLength:{totalLength} newTotalLength:{pseudoHeaderAndTcpSegment.Length} OddLength:{isOddLength}");

// Copy Source IP address (4 bytes)
Buffer.BlockCopy(ipv4Header, 12, pseudoHeaderAndTcpSegment, 0, 4);
Console.WriteLine((BitConverter.ToString(pseudoHeaderAndTcpSegment).Replace("-", " ") + ", "));
Console.WriteLine("");

// Copy Destination IP address (4 bytes)
Buffer.BlockCopy(ipv4Header, 16, pseudoHeaderAndTcpSegment, 4, 4);
Console.WriteLine((BitConverter.ToString(pseudoHeaderAndTcpSegment).Replace("-", " ") + ", "));
Console.WriteLine("");

// Zero byte (1 byte)
pseudoHeaderAndTcpSegment[8] = 0;

// Protocol (1 byte)
pseudoHeaderAndTcpSegment[9] = ipv4Header[9];
Console.WriteLine((BitConverter.ToString(pseudoHeaderAndTcpSegment).Replace("-", " ") + ", ") + " Protocol:" + ipv4Header[9]); // ipv4Header[9] prints 6 like it should
Console.WriteLine("");

// TCP length (2 bytes)
pseudoHeaderAndTcpSegment[10] = (byte)((tcpLength + payloadLength) >> 8);
pseudoHeaderAndTcpSegment[11] = (byte)(tcpLength & 0xFF);
Console.WriteLine((BitConverter.ToString(pseudoHeaderAndTcpSegment).Replace("-", " ") + ", "));
Console.WriteLine("");

// Make a copy of the transport header to zero out the checksum
byte[] transportHeaderCopy = new byte[tcpLength];
Buffer.BlockCopy(transportHeader, 0, transportHeaderCopy, 0, tcpLength);
transportHeaderCopy[16] = 0; // Zero out the checksum field (16th byte)
transportHeaderCopy[17] = 0; // Zero out the checksum field (17th byte)
Console.WriteLine((BitConverter.ToString(transportHeaderCopy).Replace("-", " ") + ", "));
Console.WriteLine("");

// Copy the modified TCP header with zeroed checksum field
Buffer.BlockCopy(transportHeaderCopy, 0, pseudoHeaderAndTcpSegment, 12, tcpLength);
Console.WriteLine("TCPHeader:" + (BitConverter.ToString(pseudoHeaderAndTcpSegment).Replace("-", " ") + ", "));
Console.WriteLine("");

// Copy the payload
Buffer.BlockCopy(payload, 0, pseudoHeaderAndTcpSegment, 12 + tcpLength, payload.Length);
if (isOddLength)
{
Console.WriteLine("Odd Length adding a zero");
pseudoHeaderAndTcpSegment[totalLength] = 0;
}
Console.WriteLine("Payload:" + (BitConverter.ToString(pseudoHeaderAndTcpSegment).Replace("-", " ") + ", "));
Console.WriteLine("");

return ComputeChecksum(pseudoHeaderAndTcpSegment);
}

protected static ushort ComputeChecksum(byte[] data)
{
int length = data.Length;
int i = 0;
long sum = 0;

while (length > 1)
{
sum += BinaryPrimitives.ReadUInt16BigEndian(data.AsSpan(i, 2));
i += 2;
length -= 2;

if (sum > 0xFFFF)
{
sum = (sum & 0xFFFF) + (sum >> 16);
}
}

if (length > 0)
{
sum += data > 16) != 0)
{
sum = (sum & 0xFFFF) + (sum >> 16);
}

return (ushort)(~sum);
}

В приведенном выше коде я должен обрабатывать нечетные длины, обнулять поля исходной контрольной суммы и правильно вычислять дополняющие поля. Например, когда я запускаю метод ComputeChecksum(byte[] data) для вычисления контрольной суммы IPv4, он всегда верен, поэтому я не думаю, что проблема в этом. Кто-то также упомянул, что мне следует поменять порядок 10 и 11 байт, и я также попробовал просто использовать tcpLength >> 8, но все эти попытки также не увенчались успехом. На самом деле, я понятия не имею, как это понять, поскольку не существует руководства, которое действительно делает это с кодом, по крайней мере, из того, что я могу найти. Вот как я вызываю вышеуказанные методы, но понятия не имею, в чем может быть проблема. Возможно, проблема с порядком байтов, поскольку C# использует прямой порядок байтов, а пакеты используют обратный порядок байтов, но я не понимаю, что может быть не так в моем методе ComputeChecksum(byte[] ipv4Header, byte[] TransportHeader, byte[] payload) и как я уже сказал, мой метод ComputeChecksum(byte[] data) вычисляет правильные контрольные суммы IPv4, поэтому я действительно в растерянности.
ushort computedTcpChecksum = PacketData.TCPHeader.ComputeChecksum(ipv4HeaderBytes, transportHeaderBytes, payloadBytes);
string newTcpChecksumHex = computedTcpChecksum.ToString("X4");

В любом случае, вот пример сбоя моего кода и возникающие в результате сообщения отладки.
PacketDetailsForm SrcIp:192.168.50.134 DstIp:192.168.50.1 Length:94 ClonedIpHeaderLength:24064 ThreadId:2
pseudoHeaderLength:12 transportHeader.Length:20 payloadLength:54 totalLength:86 newTotalLength:86 OddLength:False
C0 A8 32 86 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00,

C0 A8 32 86 C0 A8 32 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00,

C0 A8 32 86 C0 A8 32 01 00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00, Protocol:6

C0 A8 32 86 C0 A8 32 01 00 06 00 14 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00,

E2 B6 00 35 38 F9 6A 6F 2D F7 BC D5 50 18 04 02 00 00 00 00,

TCPHeader:C0 A8 32 86 C0 A8 32 01 00 06 00 14 E2 B6 00 35 38 F9 6A 6F 2D F7 BC D5 50 18 04 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00,

Payload:C0 A8 32 86 C0 A8 32 01 00 06 00 14 E2 B6 00 35 38 F9 6A 6F 2D F7 BC D5 50 18 04 02 00 00 00 00 76 37 01 00 00 01 00 00 00 00 00 00 0A 66 75 6E 63 74 69 6F 6E 61 6C 06 65 76 65 6E 74 73 04 64 61 74 61 09 6D 69 63 72 6F 73 6F 66 74 03 63 6F 6D 00 00 01 00 01,

TCP OriginalCheck:58920 E628, OurCheck:48147 BC13


Подробнее здесь: https://stackoverflow.com/questions/785 ... yte-arrays
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Вычисление контрольной суммы TCP из массива байтов
    Anonymous » » в форуме C#
    0 Ответы
    98 Просмотры
    Последнее сообщение Anonymous
  • Производительный способ объединения 3-байтовых массивов и их кодирования в base64.
    Anonymous » » в форуме C#
    0 Ответы
    54 Просмотры
    Последнее сообщение Anonymous
  • Обработка больших байтовых массивов в C#
    Anonymous » » в форуме C#
    0 Ответы
    14 Просмотры
    Последнее сообщение Anonymous
  • Обработка больших байтовых массивов в C#
    Anonymous » » в форуме C#
    0 Ответы
    8 Просмотры
    Последнее сообщение Anonymous
  • Сравнение двух байтовых массивов в .net
    Anonymous » » в форуме C#
    0 Ответы
    18 Просмотры
    Последнее сообщение Anonymous

Вернуться в «C#»