Проброс трафика через NTP протокол. Часть 1

Проброс трафика через NTP протокол. Часть 1

Life-Hack [Жизнь-Взлом]/Хакинг

#Обучение 

Сегодня мы узнаем еще один способ вывести украденные данные с компьютера, и о существовании защитных мер от него на данный момент ничего не известно. Единственное решение — полностью запретить NTP в сети и выставлять часы, набирая 100 на телефоне. Также я уверен, что эта техника скоро найдет широкое применение в разного рода ботнетах, стиллерах, бэкдорах и прочих вредоносах. Встречайте — проброс трафика через NTP протокол из корпоративных сетей.

Любая возможность незаметно обращаться к внешнему миру с хоста внутри защищенной сети — драгоценная находка для пентестера. Один из последних доступных путей — это NTP, протокол синхронизации времени на часах. Его трафик разрешен почти везде, так что он будет отличным транспортом для данных. Я покажу, как реализовать базовые клиент и сервер, которые будут использовать этот феномен, а кодить мы будем на C#. 

Пару месяцев назад я гулял по загнивающей Германии, где по каждому удобному и не очень поводу строят туннель. И тут мне пришла идея: а не сделать ли свой туннель? В качестве протокола я выбрал NTP — его использование не требует специальных привилегий, системы защиты не видят в нем никаких проблем, ведь там по определению быть ничего не может, кроме текущего времени, а его формат простой как палка, что позволяет нам использовать его без необходимости закапываться в документацию. 

Этот трюк могут использовать и вирусописатели — для вывода данных из зараженных систем, причем незаметно для стандартных средств защиты. В этом нам поможет проброс трафика через NTP протокол.

Что такое NTP 

NTP (Network Time Protocol) — протокол, который работает поверх UDP и используется для синхронизации локальных часов с часами на сервере точного времени. При работе в интернете точность синхронизации составляет до 10 мс, а в локальных сетях — до 0,2 мс. При этом NTP нечувствителен к задержкам канала. 

Актуальная версия протокола (по данным Википедии) — 4, но мы будем использовать версию 3, которой для наших целей предостаточно. 

Для максимальной точности служба обновления времени постоянно должна работать в фоновом режиме, регулярно отправляя запросы на сервер точного времени, то есть генерируя довольно много трафика. Это нам на руку, так как из-за этой особенности IDS давно не обращают внимания на трафик NTP. 

За синхронизацию в Windows отвечает служба W32Time, а в Linux — демон ntpd или chronyd. Также существует более простая реализация этого протокола, известная как SNTP (Simple Network Time Protocol) — простой протокол сетевого времени. Применяют его во встраиваемых системах и устройствах, которые не требуют высокой точности, как, например, системы умного дома. 

Структура пакета NTP 

Структура пакета NTP описана в RFC 958 (v1), 1119 (v2), 1305 (v3) и 5905 (v4). Нас интересует версия 3, как довольно распространенная и простая, хотя ты свободно можешь пользоваться версией 4, она почти не отличается.

Для прожженных программистов на C есть псевдокод:

<span class="kwd">public</span> <span class="kwd">struct</span> <span class="typ">NtpPacket</span>
<span class="pun">{</span>
  <span class="kwd">public</span> <span class="kwd">byte</span> <span class="typ">First8bits</span><span class="pun">;</span> <span class="com">// 2 бита — индикатор секунды коррекции (Leap Indicator, LI)</span>
                          <span class="com">// 3 бита — версия протокола (Version Number, VN)</span>
                          <span class="com">// 3 бита — режим работы (Mode)</span>
  <span class="kwd">public</span> <span class="kwd">byte</span> <span class="typ">Stratum</span><span class="pun">;</span>    <span class="com">// Stratum — расстояние до корневого сервера по иерархии</span>
  <span class="kwd">public</span> <span class="kwd">byte</span> <span class="typ">Poll</span><span class="pun">;</span>       <span class="com">// Насколько часто можно спрашивать сервер</span>
  <span class="kwd">public</span> <span class="kwd">byte</span> <span class="typ">Precision</span><span class="pun">;</span>  <span class="com">// Точность системных часов</span>
  <span class="kwd">public</span> <span class="kwd">uint</span> <span class="typ">RootDelay</span><span class="pun">;</span>  <span class="com">// Задержка сервера относительно главного источника времени</span>
  <span class="kwd">public</span> <span class="kwd">uint</span> <span class="typ">RootDisp</span><span class="pun">;</span>   <span class="com">// Разброс показаний часов сервера</span>
  <span class="kwd">public</span> <span class="kwd">uint</span> <span class="typ">RefID</span><span class="pun">;</span>      <span class="com">// ID часов</span>
  <span class="kwd">public</span> <span class="kwd">ulong</span> <span class="typ">Reference</span><span class="pun">;</span> <span class="com">// Последние показания часов на сервере</span>
  <span class="kwd">public</span> <span class="kwd">ulong</span> <span class="typ">Originate</span><span class="pun">;</span> <span class="com">// Правильное время отправки пакета клиентом (заполняет сервер)</span>
  <span class="kwd">public</span> <span class="kwd">ulong</span> <span class="typ">Receive</span><span class="pun">;</span>   <span class="com">// Время получения пакета сервером</span>
  <span class="kwd">public</span> <span class="kwd">ulong</span> <span class="typ">Transmit</span><span class="pun">;</span>  <span class="com">// Время отправки пакета с сервера клиенту</span>
<span class="pun">}</span>

Теперь немного о назначении этих полей. 

  •  Leap indicator (LI), 2 бита — число, предупреждающее о секунде координации. Может быть от 0 до 3, где 0 — нет коррекции, 1 — последняя минута дня содержит 61 с, 2 — последняя минута дня содержит 59 с, 3 — неисправность сервера. При значении 3 полученным данным доверять не следует. Вместо этого нужно обратиться к другому серверу. Наш псевдосервер будет всегда возвращать 0.
  •  Version number (VN), 2 бита — номер версии протокола NTP (1–4). Мы поставим туда 3.
  •  Mode — режим работы отправителя пакета. Значение от 0 до 7, где 3 — клиент, а 4 — сервер.
  •  Stratum — сколько посредников между клиентом и эталонными часами (включая сам NTP-сервер). 1 — сервер берет данные непосредственно с атомных (или других точных) часов, то есть между клиентом и часами только один посредник (сам сервер); 2 — сервер берет данные с сервера со значением Stratum 1 и так далее.
  •  Poll — целое число, задающее интервал в секундах между последовательными обращениями. Клиент может указать здесь интервал, с которым он хочет отправлять запросы на сервер, а сервер — интервал, с которым он разрешает, чтобы его опрашивали.
  •  Precision (точность) — число, которое сообщает точность локальных системных часов. Значение равно двоичному логарифму секунд.
  •  Root delay (задержка сервера) — время, за которое показания эталонных часов доходят до сервера NTP. Задается как число секунд с фиксированной запятой.
  •  Root dispersion — разброс показаний сервера.
  •  RefID (идентификатор источника) — ID часов. Если поле Stratum равно единице, то RefID — имя атомных часов (четыре символа ASCII). Если текущий сервер NTP использует показания другого сервера, то в RefID записан IP-адрес этого сервера.
  •  Reference — последние показания часов сервера.
  •  Originate — время, когда пакет был отправлен, по версии сервера.
  •  Receive — время получения запроса сервером.
  •  Transmit — время отправки ответа сервера клиенту, которое заполняет клиент.

В целом процесс проброса трафика через NTP протокол крайне прост и понятен, если изучить картинку. Клиент посылает запрос на сервер, запоминая, когда этот запрос был отправлен. Сервер принимает пакет, запоминает и записывает в пакет время приема, заполняет время отправки и отвечает клиенту. Клиент запоминает, когда он получил ответ, и получает нечто вроде RTT (Round-Trip Time, в простонародье — пинг) до сервера. Дальше он определяет, сколько времени понадобилось пакету, чтобы дойти от сервера обратно ему (время между запросом и ответом клиента минус время обработки пакета на сервере, деленное на два). 

Чтобы получить текущее время, нужно прибавить полученную задержку канала к времени отправки ответа сервером. Вот только UDP на то и UDP, что задержки могут быть случайные и непредсказуемые, так что замеры повторяются по многу раз в день, вычисляется средняя ошибка, и локальные часы корректируются. 

Ограничения на трафик по порту UDP-123 

Системы обнаружения вторжений не такие глупые, какими могут показаться, так что просто пустить трафик, например, OpenVPN по 123-му порту UDP мы не сможем, по крайней мере без риска спалиться. Соответствие RFC все же проверяется. Это можно посмотреть на примере Wireshark.

Придется нам заставить наши пакеты соответствовать RFC. Проще всего это сделать, назначая некоторые поля по своему усмотрению. Мы можем внедрить свои данные в поля Transmit и Originate. Последнее не вполне соответствует RFC, но так глубоко проверки обычно не добираются. 

Концепт проброса трафика через NTP протокол 

Идея проста: мы составляем собственный «заряженный» пакет NTP и пытаемся синхронизировать время со своим сервером. Чтобы не привлекать лишнего внимания к своей передаче, на каждый запрос должен отправляться внешне валидный ответ, в котором могут быть инструкции для клиента (читай: бота). 

Чтобы всякие там системы предотвращения утечек (DLP) не мешали нам, можно, например, поксорить наши данные со статическим ключом. Естественно, в рамках PoC я не буду этого делать, но в качестве простейшего способа сокрытия данных должно сработать. 

Для передачи данных с клиента на сервер подходят поля PollOriginate и Transmit. Из них Poll пригоден ограниченно, но мы на этом останавливаться не будем. Если ты задумаешь учесть его ограничение, то имей в виду, что использовать в этом поле можно только младшие три бита (как я понял из документации). Без учета этого мы можем использовать 17 байт из 48 (35% всего объема пакета) на отправку данных, что уже неплохо. 

А что на прием? Сервер заполняет поля PrecisionRoot delayRoot dispersionReferenceRefIDReceive и, ограниченно, Poll. На ответ сервера в этом поле распространяются такие же ограничения, как на клиента. Итого имеем 29 (28 без Poll) байт из 48 (60% пакета). Полезный объем пакета — 46 из 48 байт (96%). Оставшиеся два байта — флаги и заголовки, которые мы менять не можем без вреда для скрытности. 

Проброс трафика через NTP протокол 

Писать код и дебажить наше творение мы будем в Visual Studio. Я использую версию 2019 Community, благо она бесплатная, а скачать ее можно с сайта Microsoft. 

Сервер 

Как только IDE установлена, включена темная тема и любимый плей-лист, можно приступать. Для начала создадим новый проект типа «консольное приложение» (мы ведь не прячемся от юзера) с названием NtpTun_SERVER.

Теперь нам нужна структура, описывающая пакет. Обратившись к спецификации NTP, напишем простой класс. В нем также должны быть методы упаковки пакета в массив байтов, пригодный для передачи настоящему серверу и для распаковки пришедшего ответа из массива байтов обратно в пакет. 

Весь код, используемый в статье, есть в моем репозитории на GitHub. Он намеренно подпорчен и для промышленного использования не годится, но для демонстрации работы вполне сойдет.

Объявляем структуру пакета. Не смотри на странные суффиксы в названиях функций, так задумано

Уже из этого кода видно, что мы будем притворяться сервером Stratum 3. Если бы мы были Stratum 1, то нужно было бы в поле RefID указывать ID атомных часов, которых у нас нет. А список серверов первого уровня общеизвестен, и, если IP нашего псевдосервера не окажется в таких публичных списках, обман быстро будет раскрыт. 

Stratum 2 не следует использовать, потому что тогда RefID должен был бы содержать IP сервера первого уровня, список которых опять же известен. А вот третий уровень позволяет указывать в RefID IP сервера второго уровня, полного списка которых нет. То есть мы сможем в RefID передавать еще четыре байта произвольных данных. 

Код методов упаковки и распаковки на скриншот не поместился, к тому же нам надо разобрать его отдельно. Вот он:

<span class="kwd">public</span> <span class="typ">NtpPacket</span> <span class="typ">Parse</span><span class="pun">(</span><span class="kwd">byte</span><span class="pun">[]</span><span class="pln"> data</span><span class="pun">)</span>
<span class="pun">{</span>
  <span class="kwd">var</span><span class="pln"> r </span><span class="pun">=</span> <span class="kwd">new</span> <span class="typ">NtpPacket</span><span class="pun">();</span>
  <span class="com">// NTP packet is 48 bytes long</span><span class="pln">
  r</span><span class="pun">.</span><span class="typ">First8bits</span> <span class="pun">=</span><span class="pln"> data</span><span class="pun">[</span><span class="lit">0</span><span class="pun">];</span><span class="pln">
  r</span><span class="pun">.</span><span class="typ">Poll</span> <span class="pun">=</span><span class="pln"> data</span><span class="pun">[</span><span class="lit">2</span><span class="pun">];</span><span class="pln">
  r</span><span class="pun">.</span><span class="typ">Precision</span> <span class="pun">=</span><span class="pln"> data</span><span class="pun">[</span><span class="lit">3</span><span class="pun">];</span><span class="pln">
  r</span><span class="pun">.</span><span class="typ">RootDelay</span> <span class="pun">=</span> <span class="typ">BitConverter</span><span class="pun">.</span><span class="typ">ToUInt32</span><span class="pun">(</span><span class="pln">data</span><span class="pun">,</span> <span class="lit">4</span><span class="pun">);</span><span class="pln">
  r</span><span class="pun">.</span><span class="typ">RootDisp</span> <span class="pun">=</span> <span class="typ">BitConverter</span><span class="pun">.</span><span class="typ">ToUInt32</span><span class="pun">(</span><span class="pln">data</span><span class="pun">,</span> <span class="lit">8</span><span class="pun">);</span><span class="pln">
  r</span><span class="pun">.</span><span class="typ">RefID</span> <span class="pun">=</span> <span class="typ">BitConverter</span><span class="pun">.</span><span class="typ">ToUInt32</span><span class="pun">(</span><span class="pln">data</span><span class="pun">,</span> <span class="lit">12</span><span class="pun">);</span><span class="pln">
  r</span><span class="pun">.</span><span class="typ">Reference</span> <span class="pun">=</span> <span class="typ">BitConverter</span><span class="pun">.</span><span class="typ">ToUInt64</span><span class="pun">(</span><span class="pln">data</span><span class="pun">,</span> <span class="lit">16</span><span class="pun">);</span><span class="pln">
  r</span><span class="pun">.</span><span class="typ">Originate</span> <span class="pun">=</span> <span class="typ">BitConverter</span><span class="pun">.</span><span class="typ">ToUInt64</span><span class="pun">(</span><span class="pln">data</span><span class="pun">,</span> <span class="lit">24</span><span class="pun">);</span><span class="pln">
  r</span><span class="pun">.</span><span class="typ">Receive</span> <span class="pun">=</span> <span class="typ">BitConverter</span><span class="pun">.</span><span class="typ">ToUInt64</span><span class="pun">(</span><span class="pln">data</span><span class="pun">,</span> <span class="lit">32</span><span class="pun">);</span><span class="pln">
  r</span><span class="pun">.</span><span class="typ">Transmit</span> <span class="pun">=</span> <span class="typ">BitConverter</span><span class="pun">.</span><span class="typ">ToUInt64</span><span class="pun">(</span><span class="pln">data</span><span class="pun">,</span> <span class="lit">40</span><span class="pun">);</span>
  <span class="kwd">return</span><span class="pln"> r</span><span class="pun">;</span>
<span class="pun">}</span>

Тут никаких сложностей: принимаем массив байтов и при помощи BitConverter получаем оттуда данные.

<span class="kwd">public</span> <span class="typ">InPacket</span> <span class="typ">GetBuiltInPacketC</span><span class="pun">(</span><span class="kwd">byte</span><span class="pun">[]</span><span class="pln"> packet</span><span class="pun">)</span>
<span class="pun">{</span>
  <span class="typ">InPacket</span><span class="pln"> _packet </span><span class="pun">=</span> <span class="kwd">new</span> <span class="typ">InPacket</span><span class="pun">();</span>
  <span class="typ">NtpPacket</span><span class="pln"> ntpPacket </span><span class="pun">=</span> <span class="kwd">this</span><span class="pun">.</span><span class="typ">Parse</span><span class="pun">(</span><span class="pln">packet</span><span class="pun">);</span><span class="pln">
  _packet</span><span class="pun">.</span><span class="typ">PacketID</span> <span class="pun">=</span> <span class="lit">0</span><span class="pun">;</span><span class="pln">
  _packet</span><span class="pun">.</span><span class="typ">Data</span> <span class="pun">=</span> <span class="kwd">new</span> <span class="kwd">byte</span><span class="pun">[</span><span class="lit">17</span><span class="pun">];</span><span class="pln">
  _packet</span><span class="pun">.</span><span class="typ">Data</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span> <span class="pun">=</span><span class="pln"> ntpPacket</span><span class="pun">.</span><span class="typ">Poll</span><span class="pun">;</span>
  <span class="typ">BitConverter</span><span class="pun">.</span><span class="typ">GetBytes</span><span class="pun">(</span><span class="pln">ntpPacket</span><span class="pun">.</span><span class="typ">Originate</span><span class="pun">).</span><span class="typ">CopyTo</span><span class="pun">(</span><span class="pln">_packet</span><span class="pun">.</span><span class="typ">Data</span><span class="pun">,</span> <span class="lit">1</span><span class="pun">);</span>
  <span class="typ">BitConverter</span><span class="pun">.</span><span class="typ">GetBytes</span><span class="pun">(</span><span class="pln">ntpPacket</span><span class="pun">.</span><span class="typ">Transmit</span><span class="pun">).</span><span class="typ">CopyTo</span><span class="pun">(</span><span class="pln">_packet</span><span class="pun">.</span><span class="typ">Data</span><span class="pun">,</span> <span class="lit">9</span><span class="pun">);</span>
  <span class="kwd">return</span><span class="pln"> _packet</span><span class="pun">;</span>
<span class="pun">}</span>

Структура InPacket описывает пакет, инкапсулированный в сообщение NTP. У него есть ID и полезные данные. ID нужен, чтобы сервер мог отчитаться, что получил пакет, и чтобы клиент мог его переслать в случае ошибки доставки. Кроме того, не забываем, что в качестве транспорта мы используем UDP, поэтому не исключены потери и доставка не в том порядке, в котором пакеты были отправлены.

<span class="kwd">public</span> <span class="typ">NtpPacket</span> <span class="typ">EmbedDataToPacketS</span><span class="pun">(</span><span class="kwd">byte</span><span class="pun">[]</span><span class="pln"> data</span><span class="pun">)</span>
<span class="pun">{</span>
  <span class="kwd">var</span><span class="pln"> nd </span><span class="pun">=</span> <span class="kwd">new</span> <span class="kwd">byte</span><span class="pun">[</span><span class="lit">30</span><span class="pun">];</span> <span class="com">//Max 30 bytes of data in response</span><span class="pln">
  data</span><span class="pun">.</span><span class="typ">CopyTo</span><span class="pun">(</span><span class="pln">nd</span><span class="pun">,</span> <span class="lit">0</span><span class="pun">);</span><span class="pln">
  data </span><span class="pun">=</span><span class="pln"> nd</span><span class="pun">;</span>
  <span class="typ">NtpPacket</span><span class="pln"> result </span><span class="pun">=</span> <span class="kwd">new</span> <span class="typ">NtpPacket</span><span class="pun">();</span><span class="pln">
  result</span><span class="pun">.</span><span class="typ">First8bits</span> <span class="pun">=</span> <span class="lit">0x1B</span><span class="pun">;</span><span class="pln">
  result</span><span class="pun">.</span><span class="typ">Poll</span> <span class="pun">=</span><span class="pln"> data</span><span class="pun">[</span><span class="lit">0</span><span class="pun">];</span><span class="pln">
  result</span><span class="pun">.</span><span class="typ">Precision</span> <span class="pun">=</span><span class="pln"> data</span><span class="pun">[</span><span class="lit">1</span><span class="pun">];</span><span class="pln">
  result</span><span class="pun">.</span><span class="typ">RootDelay</span> <span class="pun">=</span> <span class="typ">BitConverter</span><span class="pun">.</span><span class="typ">ToUInt32</span><span class="pun">(</span><span class="pln">data</span><span class="pun">,</span> <span class="lit">2</span><span class="pun">);</span><span class="pln">
  result</span><span class="pun">.</span><span class="typ">RootDisp</span> <span class="pun">=</span> <span class="typ">BitConverter</span><span class="pun">.</span><span class="typ">ToUInt32</span><span class="pun">(</span><span class="pln">data</span><span class="pun">,</span> <span class="lit">6</span><span class="pun">);</span><span class="pln">
  result</span><span class="pun">.</span><span class="typ">RefID</span> <span class="pun">=</span> <span class="typ">BitConverter</span><span class="pun">.</span><span class="typ">ToUInt32</span><span class="pun">(</span><span class="pln">data</span><span class="pun">,</span> <span class="lit">10</span><span class="pun">);</span><span class="pln">
  result</span><span class="pun">.</span><span class="typ">Reference</span> <span class="pun">=</span> <span class="typ">BitConverter</span><span class="pun">.</span><span class="typ">ToUInt64</span><span class="pun">(</span><span class="pln">data</span><span class="pun">,</span> <span class="lit">14</span><span class="pun">);</span><span class="pln">
  result</span><span class="pun">.</span><span class="typ">Receive</span> <span class="pun">=</span> <span class="typ">BitConverter</span><span class="pun">.</span><span class="typ">ToUInt64</span><span class="pun">(</span><span class="pln">data</span><span class="pun">,</span> <span class="lit">22</span><span class="pun">);</span>
  <span class="kwd">return</span><span class="pln"> result</span><span class="pun">;</span>
<span class="pun">}</span>

В этом коде мы видим внедрение данных в пакет. Строка data.CopyTo(nd, 0) нужна для того, чтобы функция корректно отработала, даже если передать ей не ровно 30 байт, а меньше. Дальше мы видим стандартную сборку пакета. 

Тебя, возможно, заинтересовали эти странные суффиксы в названиях функций. Я добавил их, чтобы в коде можно было визуально различить функции клиента и сервера. Суффикс C означает, что пакет был собран клиентом, а S — сервером. 

Сервер должен уметь только распаковать данные, внедренные клиентом, и собрать свой пакет с ответом. А клиент должен уметь закинуть данные в пакет в свои поля и распарсить ответ сервера. Таким образом, у сервера будет одна копия этого файла (со своими функциями), а у клиента другая.

<span class="kwd">public</span> <span class="kwd">byte</span><span class="pun">[]</span> <span class="typ">BuildPacket</span><span class="pun">()</span>
<span class="pun">{</span>
  <span class="kwd">byte</span><span class="pun">[]</span><span class="pln"> arr </span><span class="pun">=</span> <span class="kwd">new</span> <span class="kwd">byte</span><span class="pun">[</span><span class="lit">48</span><span class="pun">];</span><span class="pln">
  arr</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span> <span class="pun">=</span> <span class="typ">First8bits</span><span class="pun">;</span><span class="pln">
  arr</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]</span> <span class="pun">=</span> <span class="typ">Stratum</span><span class="pun">;</span><span class="pln">
  arr</span><span class="pun">[</span><span class="lit">2</span><span class="pun">]</span> <span class="pun">=</span> <span class="typ">Poll</span><span class="pun">;</span><span class="pln">
  arr</span><span class="pun">[</span><span class="lit">3</span><span class="pun">]</span> <span class="pun">=</span> <span class="typ">Precision</span><span class="pun">;</span>
  <span class="typ">BitConverter</span><span class="pun">.</span><span class="typ">GetBytes</span><span class="pun">(</span><span class="typ">RootDelay</span><span class="pun">).</span><span class="typ">CopyTo</span><span class="pun">(</span><span class="pln">arr</span><span class="pun">,</span> <span class="lit">4</span><span class="pun">);</span>
  <span class="typ">BitConverter</span><span class="pun">.</span><span class="typ">GetBytes</span><span class="pun">(</span><span class="typ">RefID</span><span class="pun">).</span><span class="typ">CopyTo</span><span class="pun">(</span><span class="pln">arr</span><span class="pun">,</span> <span class="lit">8</span><span class="pun">);</span>
  <span class="typ">BitConverter</span><span class="pun">.</span><span class="typ">GetBytes</span><span class="pun">(</span><span class="typ">Reference</span><span class="pun">).</span><span class="typ">CopyTo</span><span class="pun">(</span><span class="pln">arr</span><span class="pun">,</span> <span class="lit">12</span><span class="pun">);</span>
  <span class="typ">BitConverter</span><span class="pun">.</span><span class="typ">GetBytes</span><span class="pun">(</span><span class="typ">Originate</span><span class="pun">).</span><span class="typ">CopyTo</span><span class="pun">(</span><span class="pln">arr</span><span class="pun">,</span> <span class="lit">20</span><span class="pun">);</span>
  <span class="typ">BitConverter</span><span class="pun">.</span><span class="typ">GetBytes</span><span class="pun">(</span><span class="typ">Receive</span><span class="pun">).</span><span class="typ">CopyTo</span><span class="pun">(</span><span class="pln">arr</span><span class="pun">,</span> <span class="lit">28</span><span class="pun">);</span>
  <span class="typ">BitConverter</span><span class="pun">.</span><span class="typ">GetBytes</span><span class="pun">(</span><span class="typ">Transmit</span><span class="pun">).</span><span class="typ">CopyTo</span><span class="pun">(</span><span class="pln">arr</span><span class="pun">,</span> <span class="lit">36</span><span class="pun">);</span>
  <span class="kwd">return</span><span class="pln"> arr</span><span class="pun">;</span>
<span class="pun">}</span>

Продолжение следует...

Источник


Report Page