В предыдущей части речь шла о портах..
Теперь поговорим о протоколах и начнём с самого простого WHOIS (nickName), который полностью развенчивает миф об анонимности в сети. Посредством сервисов Whois, начинающий разведчик сможет собрать информацию о любом домене, ..а если повезёт, и об его админе. Отмечу, что инфа о владельце является конфиденциальной и предоставляется регистратором только по запросу органов власти. Но есть и открытые данные, читать которые дозволено всем.
Суть в том, что если мы хотим купить домен в сети Интернет, то должны оставить свою/подноготную регистратору домена. Среди этих данных ФИО, адрес проживания, номер телефона, мэйл и т.д. По такой схеме "люди в чёрном" смогут отследить нас, если мы будем заниматься противозаконной деятельностью.
Основная проблема в том, что в глобальной сети доменов много, например: .ru, .com, .info, .net и собрать общую базу всех клиентов никак не получится. Поэтому у каждого домена свой регистратор, в геотермальный карман которого попадают только его клиенты. Значит если мы хотим собрать о ком-нибудь инфу, то должны запросить её не у кого-попало, а у конкретного регистратора, в поле зрения которого лежит этот домен. Например запрос mail.ru у регистратора .com – с треском провалится.
На серверах Whois в фоновом режиме работают "процессы-демоны", которые прослушивают сетевой порт 43 протокола TCP. Обнаружив входящий запрос на этом порту, сервер обрабатывает его, и возвращает клиенту текстовый пакет данных. Нам остаётся только вывести этот пакет на экран и всё. Протокол Whois описывает
Если мы хотим создать универсальное Whois-приложение, которое возвращало-бы инфу о доменах сразу всех регионов (а не о каком-то одном), то должны позаботится о том, чтобы по вводу юзера, на лету найти IP-адрес соответствующего регистратора, и только потом отправить ему запрос. Именно на этот программный модуль будет ложиться основная нагрузка. Значит должна быть база-адресов всех регистраторов, из которой мы вытащим один. Со-списком известных Whois-серверов для большинства региональных зон можно ознакомиться
Из огромного кол-ва вариантов решения этой проблемы, я выбрал самый простой..
Допустим юзер ввёл адрес mail.ru, а я беру только два последних символа из этой строки – в данном случае это "RU", которые определяют доменную зону адреса. У этого домена свой регистратор, имя которого заношу в свою базу. Если юзер введёт например google.com (где под домен выделяются уже три символа .com), то я всё-равно беру два последних и получаю маску "OM" для поиска имени сервера в своей базе. Базу оформляю так, что первые два символа в ней это маска, после которой идёт уже само имя Whois-сервера. Конечно-же способ "не фонтан" и вполне могут возникнуть коллизии (совпадения), но в большинстве случаях это работает.
Второе – мне нужна длинна одной записи в базе, чтобы переходить к следующей записи. Длину вычисляю по серверу, чьё имя самого длинное, а остальные имена в базе, дополняю до него нулями. Ниже представлена база, которая живёт в секции-данных программы. Здесь видно, что сервер регистратора доменов .com ожидает нас по адресу whois.verisign-grs.com, и это самое длинное имя из всех в моей базе. Если учесть 2-байтную маску и терминальный нуль в конце, то получаю длину одной записи =26 символов. Теперь, поставив указатель на начало базы сравниваю маску, и если она не совпадает, то к текущему указателю прибавляю 26 и перехожу на сл.строку и т.д. Счётчик(12) записей в базе предотвращает выход за её пределы:
И последнее что нужно сделать коду, это получить IP-адрес Whois сервера, по его имени. Для этого имеется уже знакомая нам функция WinSock gethostbyname(), которая обращается к DNS-серверу сети Интернет и получает от него IP-адрес запрошенного сервера. Единственным аргументом этой функции является указатель на имя, который мы передадим ей из нашей базы. Если функция выполняется успешно, то в регистре EAX возвращает указатель на структуру hostent, где среди прочего есть и IP. В противном случае – получим от неё нуль. Пример ниже представляет собой утилиту Whois собственного приготовления:
На скрине выше я не случайно выбрал Whois-сервер Казахстана – видимо регистратор этой зоны привык к порядку, т.к. позаботился о форматированном ответе. Большинство серверов плюют на такие мелочи, и вываливают инфу в виде зловонной кучи, что не способствует её зрительному восприятию от слова "никак". Один плюс ушёл в копилку kz..
Базы данных Whois-серверов, бывают централизованными и распределёнными. В первом случае один сервер содержит полную БД и отвечает на запросы, касающиеся всех регистраторов. По такой схеме построен Whois-сервер, например доменов
Когда утилита умеет распознавать такое перенаправление, она сама запрашивает нужный сервер (как в примере выше), в противном случае юзеру приходится делать это вручную. В протоколе "nickName" (whois, хуиз) не предусмотрено различия между централизованной и распределённой моделей – конкретная реализация хранилища зависит только от регистратора.
Внимательный читатель мог заметить, что функция WinSock gethostbyname() каким-то образом вычисляет IP-адрес узла, приняв на грудь лишь его имя. На самом деле она обращается к DNS-серверу "Domain-Name-System", у которого и запрашивает IP. DNS-серверы имеют такие-же базы данных как и Whois, только в них хранится не подноготная владельца домена, а только IP-адреса.
Так, немного изменив алгоритм данного кода, мы можем создать себе базу IP-адресов всех интересущих нас узлов. Обычно такие базы требуются локальным серверам, которые мы устанавливаем на своей машине. Например, мой "Small Http" имеет встроенный DNS-сервер, для работы которому необходима подобная база. Только натравив DNS-сервер на его базу я смогу обращаться к своим клиентам по их именам. Иначе он будет требовать исключительно IP-адрес, что не всегда удобно.
В следующий раз рассмотрим более продвинутые приёмы, где нужно будет отправлять уже не тупые запросы, а оформленные специальным образом сообщения. По такому алго работает протоколы ICMP и ARP. Здесь уже взводятся определённые биты в заголовках пакетов, по которым принимающая стороны понимает, что от неё хотят. Другими словами, это уже работа на логическом уровне.
Теперь поговорим о протоколах и начнём с самого простого WHOIS (nickName), который полностью развенчивает миф об анонимности в сети. Посредством сервисов Whois, начинающий разведчик сможет собрать информацию о любом домене, ..а если повезёт, и об его админе. Отмечу, что инфа о владельце является конфиденциальной и предоставляется регистратором только по запросу органов власти. Но есть и открытые данные, читать которые дозволено всем.
Суть в том, что если мы хотим купить домен в сети Интернет, то должны оставить свою/подноготную регистратору домена. Среди этих данных ФИО, адрес проживания, номер телефона, мэйл и т.д. По такой схеме "люди в чёрном" смогут отследить нас, если мы будем заниматься противозаконной деятельностью.
Основная проблема в том, что в глобальной сети доменов много, например: .ru, .com, .info, .net и собрать общую базу всех клиентов никак не получится. Поэтому у каждого домена свой регистратор, в геотермальный карман которого попадают только его клиенты. Значит если мы хотим собрать о ком-нибудь инфу, то должны запросить её не у кого-попало, а у конкретного регистратора, в поле зрения которого лежит этот домен. Например запрос mail.ru у регистратора .com – с треском провалится.
На серверах Whois в фоновом режиме работают "процессы-демоны", которые прослушивают сетевой порт 43 протокола TCP. Обнаружив входящий запрос на этом порту, сервер обрабатывает его, и возвращает клиенту текстовый пакет данных. Нам остаётся только вывести этот пакет на экран и всё. Протокол Whois описывает
Ссылка скрыта от гостей
где говорится, что запрос к серверу с нашей стороны должен быть оформлен как всего одна строка с именем интересующего домена, и терминальной пары ,13,10
(конец строки и возврат каретки соответственно). Например на запрос вида "mail.ru",13,10 сервер Whois вернёт нам техническую информацию об этом домене. Как видим – всё предельно просто..Если мы хотим создать универсальное Whois-приложение, которое возвращало-бы инфу о доменах сразу всех регионов (а не о каком-то одном), то должны позаботится о том, чтобы по вводу юзера, на лету найти IP-адрес соответствующего регистратора, и только потом отправить ему запрос. Именно на этот программный модуль будет ложиться основная нагрузка. Значит должна быть база-адресов всех регистраторов, из которой мы вытащим один. Со-списком известных Whois-серверов для большинства региональных зон можно ознакомиться
Ссылка скрыта от гостей
Из огромного кол-ва вариантов решения этой проблемы, я выбрал самый простой..
Допустим юзер ввёл адрес mail.ru, а я беру только два последних символа из этой строки – в данном случае это "RU", которые определяют доменную зону адреса. У этого домена свой регистратор, имя которого заношу в свою базу. Если юзер введёт например google.com (где под домен выделяются уже три символа .com), то я всё-равно беру два последних и получаю маску "OM" для поиска имени сервера в своей базе. Базу оформляю так, что первые два символа в ней это маска, после которой идёт уже само имя Whois-сервера. Конечно-же способ "не фонтан" и вполне могут возникнуть коллизии (совпадения), но в большинстве случаях это работает.
Второе – мне нужна длинна одной записи в базе, чтобы переходить к следующей записи. Длину вычисляю по серверу, чьё имя самого длинное, а остальные имена в базе, дополняю до него нулями. Ниже представлена база, которая живёт в секции-данных программы. Здесь видно, что сервер регистратора доменов .com ожидает нас по адресу whois.verisign-grs.com, и это самое длинное имя из всех в моей базе. Если учесть 2-байтную маску и терминальный нуль в конце, то получаю длину одной записи =26 символов. Теперь, поставив указатель на начало базы сравниваю маску, и если она не совпадает, то к текущему указателю прибавляю 26 и перехожу на сл.строку и т.д. Счётчик(12) записей в базе предотвращает выход за её пределы:
C-подобный:
;//-------- База Whois-серверов ------------------------------
;//----------------------------------------------------------
count dd 12 ; всего записей
servLen dd 26 ; длина одной записи
whoisBase db 'om whois.verisign-grs.com',0 ; .com
db 'ro whois.registrypro.pro' ,0,01 dup(0) ; .pro
db 'iz whois.neulevel.biz' ,0,04 dup(0) ; .biz
db 'fo whois.afilias.info' ,0,04 dup(0) ; .info
db 'in whois.registry.in' ,0,05 dup(0) ; .in
db 'ru whois.tcinet.ru' ,0,07 dup(0) ; .ru
db 'by whois.cctld.by' ,0,08 dup(0) ; .by
db 'uz whois.cctld.uz' ,0,08 dup(0) ; .uz
db 'rg whois.pir.org' ,0,09 dup(0) ; .org
db 'et whois.reg.ru' ,0,10 dup(0) ; .net
db 'kz whois.nic.kz' ,0,10 dup(0) ; .kz
db 'ua whois.ua' ,0,14 dup(0) ; .ua
;//------------------------------------------------------------
И последнее что нужно сделать коду, это получить IP-адрес Whois сервера, по его имени. Для этого имеется уже знакомая нам функция WinSock gethostbyname(), которая обращается к DNS-серверу сети Интернет и получает от него IP-адрес запрошенного сервера. Единственным аргументом этой функции является указатель на имя, который мы передадим ей из нашей базы. Если функция выполняется успешно, то в регистре EAX возвращает указатель на структуру hostent, где среди прочего есть и IP. В противном случае – получим от неё нуль. Пример ниже представляет собой утилиту Whois собственного приготовления:
C-подобный:
format pe console
entry start
include 'win32ax.inc'
;----------
.data
sAddr sockaddr_in ;
sData WSADATA ;
mes0 db 13,10,' Whois Example v0.1 /com,net,org,ru,kz,ua/'
db 13,10,' *****************************************'
db 13,10,' Domain name : ' ,0
servName db ' Whois server: %s' ,0
crlf db 13,10,' *****************************************',13,10,10,0
pKey db 13,10,' *****************************************'
db 13,10,' Press any key for exit..' ,0
error db 13,10,' ERROR! Check network cable..',0
noServ db 13,10,' ERROR! Bad domain..' ,0
count dd 12 ;// кол-во записей в базе ---------------
servLen dd 26 ;// длина одной записи
whoisBase db 'om whois.verisign-grs.com',0 ; .com
db 'ro whois.registrypro.pro' ,0,01 dup(0) ; .pro
db 'iz whois.neulevel.biz' ,0,04 dup(0) ; .biz
db 'fo whois.afilias.info' ,0,04 dup(0) ; .info
db 'in whois.registry.in' ,0,05 dup(0) ; .in
db 'ru whois.tcinet.ru' ,0,07 dup(0) ; .ru
db 'by whois.cctld.by' ,0,08 dup(0) ; .by
db 'uz whois.cctld.uz' ,0,08 dup(0) ; .uz
db 'rg whois.pir.org' ,0,09 dup(0) ; .org
db 'et whois.reg.ru' ,0,10 dup(0) ; .net
db 'kz whois.nic.kz' ,0,10 dup(0) ; .kz
db 'ua whois.ua' ,0,14 dup(0) ; .ua
;//------------------------------------------------------------
frmt db '%s',0 ; спецификатор для printf/scanf (строка)
s dd 0 ; под дескриптор сокета
server dd 0 ; под указатель на имя сервера из базы
whoisData db 2048 dup(0) ; буфер, для приёма от сервера Whois-данных
nameLen dd 0 ; длина запроса для передачи - требует recv()
name db 128 dup(0) ; сюда юзер введёт запрос типа: "mail.ru"
;//----------
.code
start: cinvoke printf,mes0 ; шапка и запрос на ввод
cinvoke scanf,frmt,name ; принимаем юзерский ввод в буфер..
;// Оформляем ввод как запрос и вычисляем его длину
mov edi,name ; указатель на имя жертвы (он-же запрос)
mov ecx,-1 ; счётчик на максимум
xor eax,eax ; очистить EAX=0
repne scasb ; ищем AL в EDI..
dec edi ; нашли! Коррекция и он указывает на хвост
mov word[edi],0x0a0d ; вставить в хвост CR/LF = 13,10 (оформить ввод как Whois-запрос)
not ecx ; инверсия битов в ECX
inc ecx ; теперь в ECX длина запроса для recv()
mov [nameLen],ecx ; запомнить её в переменной..
;// Берём последние два символа ввода, и ищем их в своей базе
mov ax,[edi-2] ; AX = маска (например "ru")
mov esi,whoisBase ; ESI = указатель на начало базы
mov ecx,[count] ; ECX = кол-во записей в ней
@find: cmp [esi],ax ; сравнить первые 2-байта с АХ
je @ok ; если соппало..
add esi,[servLen] ; иначе: указатель + длина одной записи
loop @find ; повторить ЕСХ-раз..
cinvoke printf,noServ ; Облом! Сервера нет в нашей базе!
jmp @exit ; на выход с ошибкой.
@ok: add esi,3 ; Нашли! Сместить указатель на начало имени
mov [server],esi ; запомнить его в переменнной
cinvoke printf,servName,esi ; покажем имя найденного Whois-сервера,
cinvoke printf,crlf ; ..и следом разделительную линию.
;// Полезный код!
;// Отправляем запрос конкретному Whois-серверу
invoke WSAStartup,0x0101,sData ;
invoke gethostbyname,[server] ; получить IP Whois-сервера, по его имени
cmp eax,0 ; ошибка?
jne @ipok ; если нет..
cinvoke printf,error ; иначе: ERROR - нет подключения к сети
jmp @exit ;
virtual at eax ; в EAX лежит указатель на структуру "hostent"
host hostent ; определяем вирт.структуру с именем "host"
end virtual ;
;// Здесь нужно заполнить адресный-пакет: IP, порт, протокол
;// и привязать этот пакет к сокету
@ipok: mov eax,[host.h_addr_list] ; ищем поле IP в структуре
mov eax,[eax] ; ^^^
mov eax,[eax] ; ^^^
mov [sAddr.sin_addr],eax ; отправляем его в пакет-адреса
mov [sAddr.sin_family],AF_INET ; туда-же протокол
invoke htons,43 ; Whois-порт в сетевой порядок
mov [sAddr.sin_port],ax ; записать в пакет!
invoke socket,AF_INET,SOCK_STREAM,IPPROTO_TCP ; создаём TCP-сокет
mov [s],eax ; запомнить хэндл в переменной
invoke bind,eax,sAddr,16 ; привязать адрес к сокету
invoke connect,[s],sAddr,16 ; пробуем соедениться с Whois-сервером..
cmp eax,-1 ; прокол?
jne @send ; если всё ОК!
cinvoke printf,error ; иначе: эррор и на выход..
jmp @exit ;
;// Всё готово! Отправляем запрос на выбранный сервер Whois,
;// и выводим все данные на консоль:
@send: invoke send,[s],name,[nameLen],0 ; --> отправить запрос
invoke recv,[s],whoisData,2048,0 ; <-- принять ответ в свой буфер
cinvoke printf,whoisData,frmt ; вывести всю портянку на экран!
@exit: cinvoke printf,pKey ;
cinvoke scanf,frmt,frmt+2 ; ждём клаву, чтобы осмотреться..
invoke ExitProcess,0 ;
;//--- Секция импорта ----------------------
section '.idata' import data readable
library kernel32,'kernel32.dll',\
wsock32,'wsock32.dll',\
msvcrt,'msvcrt.dll'
import msvcrt,printf,'printf',scanf,'scanf'
include 'api\kernel32.inc'
include 'api\wsock32.inc'
На скрине выше я не случайно выбрал Whois-сервер Казахстана – видимо регистратор этой зоны привык к порядку, т.к. позаботился о форматированном ответе. Большинство серверов плюют на такие мелочи, и вываливают инфу в виде зловонной кучи, что не способствует её зрительному восприятию от слова "никак". Один плюс ушёл в копилку kz..
Базы данных Whois-серверов, бывают централизованными и распределёнными. В первом случае один сервер содержит полную БД и отвечает на запросы, касающиеся всех регистраторов. По такой схеме построен Whois-сервер, например доменов
.org
и .ru
. Во втором случае – центральный сервер не содержит полной БД и рекурсивно перенаправляет юзера на сервер соответствующего регистратора. По такой схеме работает домен .com
.Когда утилита умеет распознавать такое перенаправление, она сама запрашивает нужный сервер (как в примере выше), в противном случае юзеру приходится делать это вручную. В протоколе "nickName" (whois, хуиз) не предусмотрено различия между централизованной и распределённой моделей – конкретная реализация хранилища зависит только от регистратора.
Внимательный читатель мог заметить, что функция WinSock gethostbyname() каким-то образом вычисляет IP-адрес узла, приняв на грудь лишь его имя. На самом деле она обращается к DNS-серверу "Domain-Name-System", у которого и запрашивает IP. DNS-серверы имеют такие-же базы данных как и Whois, только в них хранится не подноготная владельца домена, а только IP-адреса.
Так, немного изменив алгоритм данного кода, мы можем создать себе базу IP-адресов всех интересущих нас узлов. Обычно такие базы требуются локальным серверам, которые мы устанавливаем на своей машине. Например, мой "Small Http" имеет встроенный DNS-сервер, для работы которому необходима подобная база. Только натравив DNS-сервер на его базу я смогу обращаться к своим клиентам по их именам. Иначе он будет требовать исключительно IP-адрес, что не всегда удобно.
В следующий раз рассмотрим более продвинутые приёмы, где нужно будет отправлять уже не тупые запросы, а оформленные специальным образом сообщения. По такому алго работает протоколы ICMP и ARP. Здесь уже взводятся определённые биты в заголовках пакетов, по которым принимающая стороны понимает, что от неё хотят. Другими словами, это уже работа на логическом уровне.