Статья ASM для х86. (5.3) Протокол ICMP – PING и TRACEROUTE

Продолжим круиз по стеку протоколов TCP/IP, и на этот раз остановимся на ICMP.
В реализации этого протокола нет ничего сложного – он примитивен как амёба. Однако в умелых руках ICMP превращается в грозное оружие, из-за чего Microsoft поспешила на корню отрубить к нему доступ, оставив прогерам на растерзание лишь пару функций из библиотеки iphlpapi.dll – вот их список:
  1. IcmpCreateFile() – создать ICMP сессию;
  2. IcmpSendEcho() – отправить эхо-запрос получателю;
  3. IcmpCloseHandle() – закрыть текущую сессию.
Мдаа.. не густо.. От большого куска ICMP-протокола нам остался лишь унылый PING. В никсах дела обстоят намного лучше. Обычные их сокеты-Беркли позволяют оперировать с сокетами типа IPPROTO_ICMP, хотя под виндой этот тип уже не поддерживается, и функция socket() с аргументом ICMP тут-же возвращает ошибку. Но что так напугало мелкомягких и почему они решились на такой отчаянный шаг? Давайте разбираться..


5.3.0. Назначение протокола ICMP

Под аббревиатурой ICMP кроется "Internet Control Message Protocol". Протокол был введён для обмена сообщениями об ошибках между маршрутизаторами. Например отправили мы из своей сети пакет адресату, а адресат находится в другой сети и в данный момент по каким-то причинам не доступен (узел выключен, или кабель перебит). В этом случае, можно долго томиться в ожидании ответа, и по истечении тайм-аута так и не узнать об истинной причине отказа. Здесь и приходит на помощь ICMP, который оправляет нам смс'ку с кодом ошибки.

Примечательным является тот факт, что ICMP является частью протокола IP и делит с ним ложе на сетевом уровне(2) стека TCP/IP. Такой расклад приводит к тому, что хоть маршрутизатор и отправит нам сообщение об ошибке, нет никакой гарантии что мы его получим. Из протоколов сетевого стека, гарантировать доставку может только протокол транспортного уровня TCP, а он находится по лестнице выше IP. Задачей протокола ICMP является передача информации о проблемах в коммуникационной среде, но отнюдь не повышение уровня надёжности IP.

icmp_arp.png


В глобальных сетях маршрутизатор (он-же шлюз и роутер) представляет собой специально выделенный для перенаправления трафика компьютер. Он имеет карту IP-адресов своих клиентов, в числе которых и следующие в цепочки шлюзы. Всё-что делает маршрутизатор, это сверяет поле с адресом получателя в IP-заголовке пакета со своей таблицей маршрутизации, и если такого IP-адреса не обнаруживает, то перенаправляет трафик соседнему маршрутизатору. На рисунке представлена схема подключения нескольких локальных сетей, при помощи маршрутизаторов R1-RN (route):


router.png


Здесь видно, что если узел из сети(B) захочет переслать пакет например узлу в сети(С), то пакет ждёт экстремальное путешествие – это коммутатор и сервак в своём периметре... после чего пакет выходит наружу и прямиком попадёт в лапы маршрутизатора R2. В маршрутной карте R2 прописаны IP-адреса только узлов сети(В) и оккупировавших его с двух сторон соседних маршрутизаторов R1 и R3.

Теперь R2 уменьшает в IP-заголовке пакета значение TTL на единицу, и перенаправляет пакет по цепочке дальше, в объятия маршрутизатора R3. Тот видит, что указанный IP-адрес имеется в его таблице, и пропускает пакет в свою сеть. В контексте данной темы, декремент значения TTL для нас в приоритете – именно на этот факт опирается утилита TRACERT, которая работает как-раз по протоколу ICMP.

Нужно иметь в виду, что маршрутизаторы общаются между собой по своим правилам. Если сеть небольшая, таблица маршрутизации может заполняться админом вручную. Однако в больших сетях таблицы заполняются уже динамически, самим маршрутизатором при помощи ARP-запросов. Например он может на автомате определять добавление новой сети, недоступность пункта назначения по тайм-ауту, добавление в сеть нового маршрутизатора, который может обеспечить более короткий путь к месту назначения и т.д.

Протоколом маршрутизации внутри автономных систем являлся протокол внутреннего шлюза "Interior Gateway Protocol" или IGP. Его расширением стал "Routing Information Protocol" RIP (не путать с посмертной надписью). Однако новый протокол "Open Shortest Path First" OSPF имеет более продвинутый набор возможностей, и в дословном переводе означает "Сначала открывать самый короткий путь" – в этом случае маршрутизатор отправляет ICMP сообщение типа(5) - Redirect. На радость устаревшим IGP и RIP, большинство маршрутизаторов поддерживают все перечисленные протоколы, хотя пальмовую ветвь носит OSPF.


5.3.1. Обзор протокола ICMP и типы его ошибок

Сообщения ICMP обычно содержат информацию об ошибках при обработке пакетов маршрутизаторами. Вполне возможна ситуация, когда сообщения будут передаваться в непрерывном режиме, полностью забивая пропускную способность канала. Чтобы предотвратить такой беспредел, маршрутизаторы не должны передавать сообщения ICMP, которые связаны с ошибками самих-же сообщений ICMP. При возникновении ошибок в процессе обработки нескольких кадров одного (фрагментированного) пакета, сообщения должны передаваться только для первого фрагмента. В прошлой части говорилось, что первым считается тот, у которого значение "Offset" в заголовке равно нулю.

В качестве несущего, ICMP использует ненадёжный и без установки связи протокол IP. Существуют две категории сообщений – сообщения об ошибках, и управляющие запросы. Первые сообщают о проблемах, с которыми может столкнуться маршрутизатор при обработке пакета. В свою очередь управляющие сообщения всегда ходят парами "запрос-ответ", и помогают админу выудить конкретную информацию у маршрутизатора – это касается таких инструментов как PING и TRACEROUTE.

Сообщения ICMP инкапсулируются в пакеты IP и имеют свой формат. Именно по этой причине мастдай наглухо забил гвоздями дверь на этот уровнь, т.к. при благоприятных условиях мы сами должны были формировать заголовки IP и ICMP, а значит без труда могли подменить IP-адрес отправителя. Такой/левый пакет по конвейеру поступил-бы на физический уровень стека TCP/IP, где драйвер TDI дополнил-бы пакет только MAC-адресом и выпустил-бы его в белый свет. В следующей части мы вернёмся к этому вопросу и рассмотрим его подробней.

Детали протокола ICMP описывает Если коротко, то нужно создать структуру ICMP_Header и разместив её после IP-заголовка, отправить получателю посредством WinSock функции sendto(). В таблицах ниже представлена структура ICMP-сообщения и возможные варианты поля Type:

icmpType.png


Обычно прикладные программы только получают сообщения об ошибках – отправкой занимаются системные демоны. В числе запросов которые мы могли-бы отправить можно выделить лишь сообщение с типом(8) – это знакомый большинству из нас эхо-запрос PING. Но и в этом случае, как упоминалось выше, мастдай (редиска) забрал у нас эти права, а взамен вручил уже готовую функцию IcmpSendEcho(). Так-что нам остаётся лишь фильтровать входящий трафик на сообщения с ошибками. Выход – или ставить W2K (тогда о переносимости приложения можно забыть), или менять коня на Linux (что для привыкших к Win смерти подобно).


5.3.2. Практика – пишем утилиту PING

Здесь может возникнуть логичный вопрос – зачем тратить время и силы на свой пинг, когда в системе есть уже готовая утилита? Есть-то она есть, только каждый раз звать её из своего приложения слишком накладно. Можно даже вставить в код профайлер, и засечь время выполнения внешней утилиты – результат явно не обрадует. Если мы захотим из своего кода пропинговать не один, а например сразу сотни узлов (создав для каждого свой поток), то проще добежать до них пешком, чем воспользоваться системной тулзой PING. Поэтому практичней вызывать оптом и врозницу всего одну функцию IcmpSendEcho() с таким прототипом.. В случае ошибки, в регистре EAX она возвращает (-1), иначе – кол-во ответов хоста (как правило один):

C-подобный:
IcmpSendEcho(
    IcmpHandle           ; хэндл ICMP сессии, получим от IcmpCreateFile()
    DestinationAddress   ; IP-адрес получателя
    RequestData          ; указатель на необязательные данные
    RequestSize          ;   ..размер этих данных
    RequestOptions       ; ВАЖНО!!! указатель на структуру "IP_OPTIONS_INFO"
    ReplyBuffer          ; указатель на приёмный буфер
    ReplySize            ;   ..его длинна
    Timeout              ; значение тайм-аута (ожидания ответа)
);

Данные мы можем не отправлять, зато необходимо предварительно заполнить структуру "IP_OPTIONS_INFO", внутри которой имеются два интересных поля – это TTL и флаги. Под виндой, флагов всего два и они дают постановку МАС-уровню – фрагментировать пакет, если данные в нём превышают лимит (MF = more), или-же не фрагментировать его ни при каких обстоятельствах (DF = don't fragment). Значение в поле TTL определяет макс кол-во маршрутизаторов, которые сможет преодолеть наш PING:

C-подобный:
struct IP_OPTIONS_INFO     ;// Всего 8 байт
   Ttl            db  0     ; сколько маршрутизаторов пройти
   Tos            db  0     ; тип сервиса =0 (для icmp)
   Flags          db  0     ; IP_FLAG_xx
   OptionsSize    db  0     ; размер доп.опций
   OptionsData    dd  0     ; указатель на них
ends

После того как IcmpSendEcho() отправит запрос, удалённый хост заполнит наш приёмный буфер специальным пакетом. Этот пакет описывает структура WinSock под названием ICMP_ECHO_REPLY – вот её формат:

C-подобный:
struct ICMP_ECHO_REPLY      ;// Всего 64 байт
   Address        dd  0       ; адрес отправителя (хоста или шлюза)
   Status         dd  0       ; код ошибки операции
   RoundTripTime  dd  0       ; время трафика "туда-сюда"
   DataSize       dw  0       ; размер данных
   Reserved       dw  0       ; (выравнивание..)
   DataPointer    dd  0       ; указатель на данные
   Options        dd  0,0       ; опции из "IP_OPTIONS_INFO"
   icmpData       db  36 dup(0) ; данные (если есть)
ends

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

C-подобный:
format   pe console
entry    start
include 'win32ax.inc'
;----------
.data
wsa          WSADATA
ipOpt        IP_OPTIONS_INFO

capt         db  13,10,' PING example v0.1'
             db  13,10,' ******************************'
             db  13,10,' Type host.......: ',0
ping         db  13,10
             db  13,10,'    Host.........: %s'
             db  13,10,'    Time.........: %.2ld ms'
             db  13,10,'    TTL..........: %d'
             db  13,10,'    Packet size..: %d bytes',0
succes       db  13,10
             db  13,10,' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'
             db  13,10,' PING successful..'
             db  13,10,' Press any key for exit...',0

frmt         db  '%s',0               ; спецификатор для scanf()
hndl         dd  0                    ; под дескриптор ICMP сессии
addr         dd  0                    ; под IP-адрес назначения
count        dd  2                    ; счётчик запросов PING
outPack      db  'Marylin example Ping'   ; необязательные данные,
outPackLen   dd  $ - outPack              ;  ..и их размер.
inPack       db  128 dup(0)            ; приёмный буфер
errMes       db  128 dup(0)           ; буфер для строки с ошибкой
hostName     db  64  dup(0)           ; сюда юзер введёт имя хоста для пинга

;---------
.code
start:
;//--- Выводим шапку и принимаем имя хоста у юзера -------
         invoke  WSAStartup,0x0101,wsa    ;
        cinvoke  printf,capt              ;
        cinvoke  scanf,frmt,hostName      ;

;//--- Обрабатываем введённую строку и получаем IP назначения -----------
         invoke  inet_addr,hostName       ;// это IP вида "127.0.0.1" ???
         cmp     eax,-1                   ; 0xFFFFFFFF = ошибка
         jnz     @create                  ; если нет ошибки..

         invoke  gethostbyname,hostName   ;// это имя типа "mail.ru" ???
         or      eax,eax                  ; 0 = ошибка
         jnz     @name                    ; если No_Zero..

        stdcall  GetError                 ; иначе: встречаем её!
         jmp     @exit                    ; ..и на выход.

@name:                                    ; юзер ввёл имя (не IP)
virtual  at      eax                      ; в EAX лежит адрес структуры "hostent"
host     hostent                          ; определяем её как виртуальную
end      virtual                          ;

         mov     eax,[host.h_addr_list]   ; берём из "hostent" 4-байтный IP
         mov     eax,[eax]                ;  ^^^
         mov     eax,[eax]                ;    ^^^
@create: mov     [addr],eax               ; запомнить его в переменной!

;//--- Создаём ICMP сессию и задаём опции -------
         invoke  IcmpCreateFile           ; создать сессию!
         mov     [hndl],eax               ; запомнить её дескриптор

         mov     [ipOpt.Ttl],32             ; выставляем для пинга TTL=32
         mov     [ipOpt.Flags],IP_FLAG_DF   ; флаг = не фрагментировать

;//--- Непосредственно PING в цикле -------------
@send:   mov     eax,[addr]                              ; EAX = IP назначения
         invoke  IcmpSendEcho,[hndl],eax,\               ; отправить эхо-запрос!!!
                               outPack,[outPackLen],\    ;  ^^^
                               ipOpt,inPack,128,3000     ;   ^^^ тайм-аут = 3000 ms

;//--- Парсим приёмный буфер ICMP_ECHO_REPLY ----
         xor     ebx,ebx              ; EBX, EDX = 0
         xor     edx,edx              ;
         mov     esi,inPack           ; ESI = адрес буфера с ответом
         mov     eax,[esi]            ; EAX = IP отправителя
         invoke  inet_ntoa,eax        ; перевести его в строку
         mov     bl,[ipOpt.Ttl]       ; EBX = TTL
         mov     ecx,dword[esi+8]     ; ECX = "RoundTripTime" потраченое время
         mov     dx,word[esi+12]      ; EDX = размер данных в байтах
        cinvoke  printf,ping,eax,ecx,ebx,edx     ; вывод бодяги на экран!
         dec     [count]              ; счётчик -1
         jnz     @send                ; повторить, если счётчик не нуль

;//--- Финальная стадия ------------------------
        cinvoke  printf,succes            ; мессага "Всё ОК!"
@exit:   invoke  IcmpCloseHandle,[hndl]   ; прибить ECHO-сессию
        cinvoke  scanf,frmt,frmt+5        ; ждём нажатия клавиши..
         invoke  ExitProcess,0            ; на выход!

;//---------------------------------------------
;//--- Вспомогательная функция обработки ошибок
;//--- выводит характер ошибки в текстовом виде.
;//---------------------------------------------
GetError:
        invoke  WSAGetLastError
        invoke  FormatMessage,0x1000,0,eax,0,errMes,128,0
        invoke  CharToOem,errMes,errMes
       cinvoke  printf,errMes
ret

;//--- Секция импорта  ------
section '.idata' import data readable     ;
library  kernel32,'kernel32.dll',\        ; импортируемые библиотеки
         user32,'user32.dll',\            ; ^^^
         wsock32,'wsock32.dll',\          ;   ^^^
         msvcrt,'msvcrt.dll',\            ;     ^^^
         iphlp,'iphlpapi.dll'             ;       ^^^

import   iphlp, IcmpSendEcho,'IcmpSendEcho',IcmpCreateFile,'IcmpCreateFile',\
                IcmpCloseHandle,'IcmpCloseHandle'
import   msvcrt, printf,'printf',scanf,'scanf'
include 'api\kernel32.inc'
include 'api\user32.inc'
include 'api\wsock32.inc'

pingRequest.png


Скрин снифера " Wireshark" показывает, что ICMP-пакеты не выходят из уровня IP.
Хоть я и отправлял запросы из своего пользовательского приложения, транспортные уровни TCP и UDP стека протоколов остались не при делах, и даже не подозревают об отправки мной запроса. Другими словами, в протоколе ICMP вообще отсутствует понятие порт, и весь обмен происходит исключительно на уровне маршрутизаторов IP.


5.3.3. Утилита TRACEROUTE

..это из той-же кухни, что и PING.
Основное назначение – хитростью отследить маршрут пакета от источника, к месту назначения. Мы уже знаем, что каждый маршрутизатор в сети уменьшает на единицу значение TTL в IP-заголовке пакета. Если маршрутизатор обнаруживает пакет с TTL=0, он дропает его и отправляет нам ICMP-сообщение типа(11), что означает "Лимит времени истёк" (см.таблицу с кодами ошибок выше). Так-как сообщение отправляет именно маршрутизатор, значит он-же и вставит в сообщение свой IP-адрес. Айпишник в полученной мессаге сдаёт маршрутизатор с потрахами и нам остаётся лишь вывести его на экран.

TRACEROUT – чемпион по бегу в мешках. Он прыгает от маршрутизатора к маршрутизатору собирая их айпи. Важным моментом в этой махинации является то, что установив сначала TTL=1, при каждом последующем запросе мы должны увеличивать его на единицу, чтобы очередной маршрутизатор передавал наш запрос на один шаг дальше. Когда запрос минуя все маршрутизаторы дойдёт до адресата, ошибка в поле "Status" структуры ICMP_ECHO_REPLY будет равна нулю, ..т.е. всё ок! В противном случае, там будет красоваться код 0x2B05 (11013) = IP_TTL_EXPIRED_TRANSIT. Возможные варианты этого поля перечислены ниже:

C-подобный:
; ICMP_ECHO_REPLY поле "Status"
;================================
IP_SUCCESS                 = 0        ; успешно
IP_BUF_TOO_SMALL           = 11001    ; Буфер ответов был слишком маленьким.
IP_DEST_NET_UNREACHABLE    = 11002    ; Сеть назначения недоступна.
IP_DEST_HOST_UNREACHABLE   = 11003    ; Хост назначения был недоступен.
IP_DEST_PROT_UNREACHABLE   = 11004    ; Протокол назначения был недоступен.
IP_DEST_PORT_UNREACHABLE   = 11005    ; Порт назначения был недоступен.
IP_NO_RESOURCES            = 11006    ; Недостаточно ресурсов IP.
IP_BAD_OPTION              = 11007    ; Указан неверный IP-адрес.
IP_HW_ERROR                = 11008    ; Произошла аппаратная ошибка.
IP_PACKET_TOO_BIG          = 11009    ; Пакет был слишком большим.
IP_REQ_TIMED_OUT           = 11010    ; Время запроса истекло.
IP_BAD_REQ                 = 11011    ; Плохая просьба
IP_BAD_ROUTE               = 11012    ; Плохой маршрут
IP_TTL_EXPIRED_TRANSIT     = 11013    ; Время жизни (TTL) истекло в пути
IP_TTL_EXPIRED_REASSEM     = 11014    ; TTL истекло при повторной сборки фрагмента
IP_PARAM_PROBLEM           = 11015    ; Проблема параметров.
IP_SOURCE_QUENCH           = 11016    ; Датаграммы приходят слишком быстро
IP_OPTION_TOO_BIG          = 11017    ; Вариант IP был слишком велик.
IP_BAD_DESTINATION         = 11018    ; Плохое место назначения.
IP_GENERAL_FAILURE         = 11050    ; искажённый ICMP пакет

Воспользовавшись этим нехитрым приёмом, мы можем написать свой TRACERT. Вообще, функционал любого кода зависит от конкретной задачи, поэтому я не стал тут выворачиваться наизнанку, и ограничился лишь выводом IP-адресов и времени прохождения пакета в обе стороны. Вот пример исходника, который вы можете заточить под себя..

C-подобный:
format   pe console
entry    start
include 'win32ax.inc'
;----------
.data
wsa          WSADATA
echoReply    ICMP_ECHO_REPLY
ipOpt        IP_OPTIONS_INFO

capt         db  13,10,' TRACERT example v0.1'
             db  13,10,' ******************************'
             db  13,10,' Host...: ',0
crlf         db  13,10,0
ping         db  13,10,'  TTL= %02d   %02d ms   %s',0
succes       db  13,10
             db  13,10,' ~~~~~~'
             db  13,10,' TRACE successful..'
             db  13,10,' Press any key for exit...',0

frmt         db  '%s',0           ;
hndl         dd  0                ;
addr         dd  0                ;
errMes       db  128 dup(0)       ;
hostName     db  64  dup(0)       ;
;----------
.code
start:
;//---- Шапка и запрашиваем имя хоста ------
         invoke  WSAStartup,0x0101,wsa
        cinvoke  printf,capt
        cinvoke  scanf,frmt,hostName
        cinvoke  printf,crlf

;//---- Вычисляем IP-адрес назначения ------
        stdcall  GetDestAddress           ; (см.функцию в хвосте)
         mov     [addr],eax               ; запомнить его в переменной!

;//---- Создаём сессию и задаём опции ------
         invoke  IcmpCreateFile
         mov     [hndl],eax
         mov     [ipOpt.Ttl],1              ;// выставляем стартовый TTL=1
         mov     [ipOpt.Flags],IP_FLAG_DF   ; флаг = не фрагментировать пакет

;//---- Стартуем трейс.. -------------------
@trace:  mov     eax,[addr]                        ; EAX = IP удалённого хоста
         invoke  IcmpSendEcho,[hndl],eax,0,0,\          ; данных нет(0,0)
                               ipOpt,echoReply,64,2000  ; тайм-аут =2 сек
;-- парсим приёмный буфер ------------------
         mov     eax,[echoReply.Address]         ; EAX = IP отправителя
         invoke  inet_ntoa,eax                   ; перевести его в строку
         mov     ecx,[echoReply.RoundTripTime]   ; ECX = время туда-обратно
         xor     ebx,ebx                         ;
         mov     bl,[ipOpt.Ttl]                  ; EBX = текущий TTL
        cinvoke  printf,ping,ebx,ecx,eax     ; вывод на экран!
         inc     byte[ipOpt.Ttl]             ;// Важно!!! TTL+1
         cmp     [echoReply.Status],0        ; проверить статут на SUCCESS!
         jnz     @trace                      ; повторить, если не нуль..

;//---- Закругляемся.. ---------------------
         cinvoke  printf,<'  <--- %s',0>,hostName
         cinvoke  printf,succes            ; мессага "Всё ОК!"
         invoke  IcmpCloseHandle,[hndl]    ; прибить ECHO-сессию
@exit:  cinvoke  scanf,frmt,frmt+5         ; ждём нажатия клавиши..
         invoke  ExitProcess,0             ; на выход!

;//*****************************************
;//---- Вспомогательные функции
;//*****************************************
GetError:
        invoke  WSAGetLastError
        invoke  FormatMessage,0x1000,0,eax,0,errMes,128,0
        invoke  CharToOem,errMes,errMes
       cinvoke  printf,errMes
ret

GetDestAddress:
        invoke  inet_addr,hostName       ;// это IP вида "127.0.0.1" ???
        cmp     eax,-1                     ; 0xFFFFFFFF = ошибка
        jnz     @ok                        ; если нет..
        invoke  gethostbyname,hostName   ;// это имя типа "mail.ru" ???
        or      eax,eax                    ; 0 = ошибка
        jnz     @name                      ; если No_Zero..
       stdcall  GetError                   ; иначе: встречаем её!
        pop     eax                        ;
        jmp     @exit                      ; на выход с ошибкой.
@name:                                     ; юзер ввёл имя (не IP)
virtual  at     eax                        ; в EAX лежит адрес структуры "hostent"
host     hostent                           ; определяем её как виртуальную
end      virtual                           ;
        mov     eax,[host.h_addr_list]     ; берём из неё 4-байтный IP
        mov     eax,[eax]                  ;  ^^^
        mov     eax,[eax]                  ;    ^^^
@ok:    ret

;//--- Секция импорта  ------
section '.idata' import data readable     ;
library  kernel32,'kernel32.dll',\        ; импортируемые библиотеки
         user32,'user32.dll',\
         wsock32,'wsock32.dll',\          ;  ^^^
         msvcrt,'msvcrt.dll',\            ;    ^^^
         iphlp,'iphlpapi.dll'             ;      ^^^

import   iphlp, IcmpSendEcho,'IcmpSendEcho',IcmpCreateFile,'IcmpCreateFile',\
                IcmpCloseHandle,'IcmpCloseHandle'
import   msvcrt, printf,'printf',scanf,'scanf'
include 'api\kernel32.inc'
include 'api\user32.inc'
include 'api\wsock32.inc'
trace.png


На всякий/пожарный, в скрепке цепляю обновлённый вариант инклуд, в который добавил некоторые структуры и константы ошибок.
 

Вложения

  • WSOCK32.ZIP
    7,4 КБ · Просмотры: 467
Последнее редактирование:

Salivan

Green Team
24.06.2019
44
13
BIT
0
ТС случаем на Си не пишет? Может такое же, только на Си?
 

Hardreversengineer

Green Team
20.08.2019
49
28
BIT
14
ТС случаем на Си не пишет? Может такое же, только на Си?
С позволения ТС, хочу процитировать его же (извините если исковеркано): "Есть ряд возможностей присущих только ассемблеру и отсутствующих в таких языках, как Си."
Но речь шла конкретно о внедрении в память к другому приложению. По поводу этой программы, мне кажется ничего особенного здесь нет.
Создаёте проект, выбираете консольное приложение, инклюдите библиотеки, в третьей главе о практике были примеры циклов и ветвлений.
Советую то что стоит после cinvoke/invoke гуглить (это обычно названия функций), в MSDN даётся полная информация о функциях.
 

Marylin

Mod.Assembler
Red Team
05.06.2019
326
1 451
BIT
696
Может такое же, только на Си?
так раздел вроде ассемблера..
а на сишке есть уже хоть на том-же MSDN по запросу этой функции. Чтобы сделать из него tracert, просто увеличивайте ttl на единицу, и всё.
 
  • Нравится
Реакции: Mikl___ и Salivan

Salivan

Green Team
24.06.2019
44
13
BIT
0
так раздел вроде ассемблера..
а на сишке есть уже хоть на том-же MSDN по запросу этой функции. Чтобы сделать из него tracert, просто увеличивайте ttl на единицу, и всё.
msdn это конечно святое, но подробные коменты как у тебя в стетье даже в msdn отсутсвуют)
 
  • Нравится
Реакции: Marylin
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!