Разводим червей Ms-Rem (Ms-Rem@yandex.ru) Хакер, номер #084, стр. 084-118-4 RR-запись выглядит так: NAME up to 255 bytes + 1 ('\0') TYPE 2 bytes (UINT) CLASS 2 bytes (UINT) TTL 4 bytes (signed 32 bits number - 'long') RDLENGTH 2 bytes (UINT) RDATA variable, depend on query Где NAME - название хоста, к которому относится запись, TYPE - тип представляемой информации (о типах см. выше), CLASS - класс сети (в нашем случае всегда 'IN' (01)), TTL - время хранения информации в секундах, RDLENGTH - длина блока информации в байтах, RDATA - блок представляемой информации. Самой главной проблемой при декодировании ответа будет разбор возвращаемых имен хостов. Имя хоста состоит из нескольких частей. Перед каждой частью ставится байт, определяющий ее длину. Например, www.microsoft.com будет выглядеть как 03 www 09 microsoft 03 com 00, имя всегда оканчивается нулевым байтом. Но самая главная фича не в этом, а в том, что имя может быть упаковано. Упаковывают имя, используя указатель, он представляет собой два байта, причем первый используется в качестве семафора, два старших бита этого семафора установлены в 1, а остальные не определены. Второй байт является смещением от начала запроса, то есть от первого байта идентификатора. Если байт длины равен $C0, то следующий за ним байт будет указателем (кошмар - прим. gorl'а). Напишем функцию, декодирующую такие имена: function GetQName(var RecvData; Offset: Integer; var Pt: Pointer): string; var ChPt : PChar; ReadBytes : Byte; begin Result := ''; ChPt := @RecvData; Inc(ChPt, Offset + 1); while ChPt^ <> '' do begin if ChPt^ = #$C0 then begin Inc(ChPt); Result :=Result + GetQName(RecvData, Ord(ChPt^) - 1, Pt); Break; end else begin ReadBytes := Ord(ChPt^); while ReadBytes > 0 do begin Inc(ChPt); Result := Result + string(ChPt^); Dec(ReadBytes); end; end; Inc(ChPt); if (ChPt^ <> '') then Result := Result + '.'; end; Pt := ChPt; end; Так как объем статьи не позволяет рассмотреть процесс MX-резолвинга целиком, то я рассмотрю здесь только еще один важный момент - получение IP DNS-сервера, через который мы будем слать запросы. В этом нам поможет функция GetNetworkParams из iphlpapi.dll. Эта функция возвращает различную информацию о сетевых адаптерах, в том числе и адреса, связанных с ними DNS. |