in name of zero INOZ, issue #1, 20 nov. 2001 Netbios и все все все... by Bethoven Contents: Вступление. Winapi vs своя реализация. Получение списка ресурсов (wnetenum*). Подсоединение к ресурсу. Использование ресурсов, работа с файлами и директориями. Собственная реализация, nessus нам в помощь. Получение netbios имени хоста. Заключение и ссылки. ВСТУПЛЕНИЕ: Netbios протокол очень широко используется в локальных сетях и служит не только для передачи файлов между машинами, но и для многих других вещей. В особенности это касается win сетей. И кстати можно сказать, что netbios самый быстрый из протоколов для обмена файлами. По сравнению с raw tcp (я не считаю более высокие http и ftp) или udp он дает прирост скорости до 20% уже на 100 мбит езернете.Это достигается за счет использования больших пакетов например.Но вернемся к сути, мы будем рассматривать самое распространенное использование netbios в локальных и глобальных сетях поверх tcp(сам netbios не обеспечивает роутинг). Этот протокол называется NBT (NetBIOS через TCP/IP). А точнее использование дисковых ресурсов с общим доступом(расшаренные ресурсы(диски), шары). В качестве ресурсов могут выступать и другие объекты например: принтеры или удаленное управление NT системами и многое другое. WINAPI VS СВОЯ РЕАЛИЗАЦИЯ: Системные функции windows (winapi) предоставляют весь нужный сервис, но у такого подхода есть свои плюсы и минусы. Преимущества winapi: Легкость использования и полная поддержка остальными системными фун-ями легкость написания, достаточно прочитать msdn полное описание возвращаемых ошибок. Недостатки winapi: Непереносимость на другие платформы не на всех win системах нормальная реализация (под win9x возможные зависания , и вообще по скорости работы win9x и winnt сильно различны) невозможность вмешиваться в работу протокола, например при реализации любого рода уязвимостей. невозможность определения скрытых ресурсов (с$ например) Я рассмотрю подробно только использование winapi, а в качестве примера собственной реализации приведу получение netbios имен. ПОЛУЧЕНИЕ СПИСКА РЕСУРСОВ (wnetenum*): И так у нас есть IP хоста, на котором мы предполагаем наличие расшаренных ресурсов. Вначале определим список ресурсов, для этого используются функции WnetOpenEnum, WnetEnumResource, WNetCloseEnum Nw: TnetResource; nw.dwScope:=RESOURCE_GLOBALNET; nw.dwType:=RESOURCETYPE_DISK; // нам нужны только дисковые ресурсы. nw.dwUsage:=RESOURCEUSAGE_CONTAINER; nw.lpLocalName:=nil; nw.lpRemoteName:='\\IP'; nw.lpProvider:=nil; Начинаем enumerating Type pnetar=^netar; netar=array [0..64] of tnetresource; var Dwresult:integer;//код ошибки Henum:thandle; lpnrLocal:pnetar; dwNumEntries:cardinal; s:string; begin lpnrLocal:=@netrrr;// так проще будет вынимать ресурсы. DwNumEntries:=64;//кол-во ресурсов которые мы сможем принять. dwResult:=WNetOpenEnum( RESOURCE_GLOBALNET, RESOURCETYPE_DISK, 0, @nw, henum //наш хендл ); if dwResult=no_error then begin repeat dwResult:=WNetEnumResource( hEnum, dwNumEntries, lpnrLocal,//здесь и будут наши ресурсы. dwBufferSize ); if dwResult=no_error then begin for dwIndex:=0 to dwNumEntries-1 do begin s:= (lpnrlocal^)[dwindex].lpRemoteName; //это и есть наш ресурс. end; end; //повторяем пока не исчерпаем все ресурсы. until dwResult=ERROR_NO_MORE_ITEMS; end; end; WNetCloseEnum(hEnum); //незабываем закрывать хендл. end; ПОДСОЕДИНЕНИЕ К РЕСУРСУ: Теперь следующая задача подключение к ресурсу фун-ция: WNetAddConnection2 В winapi существует несколько модификаций этой функции, например фун-ция WnetAddConnection3 позволит вам показать пользователю стандартный диалог подключения ресурса. Но в данном случае нам просто надо подключить ресурс. Аналогично заполняем структуру: nw.dwScope:=0 nw.dwType:=RESOURCETYPE_DISK; // нам нужны только дисковые ресурсы. nw.dwUsage:=0 nw.lpLocalName:=nil; // здесь можно указать имя локального диска, на который будет //примонтирован ресурс , но нам это не нужно. nw.lpRemoteName:='\\IP\resource'; //тут уже пишем удаленный ресурс, полученный например с помощью функций wnetenum* nw.lpProvider:=nil; //пробуем подключиться указав логин и пароль (username and pass) Err:=WNetAddConnection2(nw,pass,username,0); //Или можно так когда мы не знаем логина и пароля , и пытаемся законектиться с пустым паролем. Имя //будет использоваться то с которым вы залогинились в системе. Err:=WNetAddConnection2(nw,nil,nil,0); Более подробное описание по последнему параметру и использованию логинов и паролей смотрите msdn.Также на NT системах если вы имеете права администратора домена 1 способом возможно подключать любые ресурсы, но это конечно зависит от конкретных настроек системы. Также скажу , что подключаться к ресурсу не обязательно: функции копирования в winapi позволяет копировать сразу с ресурсов тоесть с \\ip\resource\file.ext Но подключаться нужно в тех случаях когда у ресурса есть пароль или другой логин для доступа. ИСПОЛЬЗОВАНИЕ РЕСУРСОВ, РАБОТА С ФАЙЛАМИ И ДИРЕКТОРИЯМИ: Ну и последнее: использование ресурса.Вот здесь действительно понимаешь глобальность и удобство winapi и сетевого стека win( хотя на *nix покруче конечно;) ).Любые функции работы с файлами (открытые, закрытие, запись, поиск итд) без проблем работают с удаленными файлами (UNC) вида \\ip\resource\file.ext. То есть чтобы например скопировать файл autoexec.bat достаточно написать Copyfile('\\ip\c\autoexec.bat','c:\1.bat',0); СОБСТВЕННО РЕАЛИЗАЦИЯ, NESSUS НАМ В ПОМОЩЬ: В качестве примера реализации собственного стека протокола отсылаю на www.nessus.org. В этом сканере есть plugins(nessus-plugins-1.0.7-1.i386.rpm), реализующие практически все нужные функции. Они поставляются в исходных кодах, на языке подобном перлу,и поэтому переделать под ваш любимый язык программирования не составит труда. smb_accessible_shares.nasl (проверка на доступ R или RW) smb_enum_shares.nasl (получения списка ресурсов) smb_login.nasl (обычный логин) smb_login_as_users.nasl netbios_name_get.nasl (получение netbios имен хоста, использование в Delphi описано ниже) smb_bruteforce_pass.nasl (это самый интересный наверно ;) подбор паролей аналогично pqwak , 5-10 минут для 8 значного пароля) ... и много других тоже интересных Итак к примеру нам нужно получить нетбиос имена по IP хоста.В поставке windows есть стандартная консольная программка для этого-nbtstat. Вот пример запроса: Адрес IP узла: [200.0.0.2] Код области: [] Таблица NetBIOS-имен удаленных компьютеров Имя Тип Состояние ---------------------------------------------------- LMTA <00> UNIQUE Зарегистрирован WORKGROUP <00> GROUP Зарегистрирован LMTA <20> UNIQUE Зарегистрирован Адрес платы (MAC) = 02-00-4C-4F-4F-50 Типов этих достаточно много, но наиболее интересным является для нас 03 который обозначает запущенный сервис shared files.(Полное описание можно посмотреть к примеру в ENT3 или Languard) Также как вы заметили мы можем узнать MAC адрес сетевого интерфейса машины и определить например dialup это или eth адаптер. ПОЛУЧЕНИЕ NETBIOS ИМЕНИ ХОСТА: Далее следует переработанный под Delphi плугин (netbios_name_get.nasl) из nessus. Отличается от оригинального возвращением только имени хоста, и возможностью указания таймаута для соединения. function getname(host:string;timeout:Integer;addstr:string):string; var err,soc,subloc,name_copy,loc,name_count,num_of_names, location,res,netbios_len,group_found:Integer; name,sendata,candidate,r,hole_data,hole_answer:string; buf:array [1..4096] of Char; hostname_found:boolean; sockset:TFDSet; timeval:ttimeval; begin Result:=''; try logsys(addstr+'Trying get name for host '+host); NETBIOS_LEN := 50; //пакет запроса вот в такой форме ;) если захочется узнать , что в полях пакета // читайте описание на протокол. sendata := raw_string([ $01, $F8, $00, $10, $00, $01, $00, $00, $00, $00, $00, $00, $20, $43, $4B, $41, $41, $41, $41, $41, $41, $41, $41, $41, $41, $41, $41, $41, $41, $41, $41, $41, $41, $41, $41, $41, $41, $41, $41, $41, $41, $41, $41, $41, $41, $00, $00, $21, $00, $01 ]); hostname_found := false; group_found := 0; candidate := ''; Result:=''; //открываем не блокирующий сокет. soc := open_sock_udp(host,137); if soc=invalid_socket then begin logsys(addstr+'Cant get host name (error alloc sock) '+host); Exit; end; zeromemory(@buf,4096); sockset.fd_count:=1; sockset.fd_array[0]:=soc; timeval.tv_sec:=0; timeval.tv_usec:=timeout*1000; //timeout задается мс поэтому умножаем err:=select(0,nil,@sockset,nil,@timeval);//ждем завершения коннекта, для Udp не критично if err<>1 then begin closesocket(soc); if err=0 then logsys(addstr+'Cant get host name (timeout conn) '+host); if err=-1 then logsys(addstr+'Cant get host name (send error) '+host); Exit; end; send(soc, sendata[1], netbios_len,0);//посылаем наш пакет. zeromemory(@buf,4096); sockset.fd_count:=1; sockset.fd_array[0]:=soc; timeval.tv_sec:=0; timeval.tv_usec:=timeout*1000; err:=select(0,@sockset,nil,nil,@timeval);//ждем пока придут какие либо данные if err<>1 then begin closesocket(soc); if err=0 then logsys(addstr+'Cant get host name (timeout) '+host); if err=-1 then logsys(addstr+'Cant get host name (socket error) '+host); Exit; end; res := recv(soc,buf,4096,0);// получаем ответ. err:=WSAGetLastError; if res<=0 then begin closesocket(soc); logsys(addstr+'Cant get host name (recv error '+IntToStr(err)+' ) '+host); Exit; end; closesocket(soc); r:=string(buf);setlength(r,res); {переводим буфер в строку, в плугинах nessus используется вместо обычных массивов.} {теперь собственно разбор, оставлю без пояснений. decodedostowin используется потому, что русские имена приходят в dos кодировке.Но учтите во все функции куда вы будете передавать это имя нужно оставлять в той-же досовской кодировке. remsp удаляет пробелы в конце строки} if r<>'' then begin hole_answer := ''; hole_data := r; location := 0; location := location + 56; num_of_names := ord(hole_data[location+1]); logsys(3,st_comp,addstr+'Found '+IntToStr(num_of_names)+' names on host '+host); location := location + 1; hostname_found:=False; for name_count:=0 to num_of_names-1 do begin name:=''; for name_copy:=0 to 14 do begin loc := location+name_copy+name_count*18; end; loc := location+16+name_count*18; if(hole_data[loc+1] = raw_string([68])) then begin subloc := location+15+name_count*18; if(ord(hole_data[subloc+1])=32) then begin if(not hostname_found) then begin result:=remsp(Name); hostname_found := true; xlogsys(3,st_comp,addstr+'Name for host '+host + ' is '+ Result+ ' (' +decodedostowin(result)+')'); Exit; end; end else begin if(ord(hole_data[subloc+1])=0) then begin candidate := name; if(not ( name <> '~')) then begin if(not hostname_found) then begin Result:=remsp(Name); hostname_found := true; logsys(addstr+'Name for host '+host+' is '+result+' ('+decodedostowin(result)+')'); Exit; end; end; end; end; end; if (hole_data[loc+1] = raw_string([4])) then begin subloc := location+15+name_count*18; if (hole_data[subloc+1] = raw_string([0])) then begin if( not hostname_found) then begin Result:=remsp(Name); hostname_found := true; logsys(addstr+'Name for host '+host+' is '+result+' ('+decodedostowin(result)+')'); Exit; end; end; end; end; end; xlogsys(3,st_comp,addstr+'Cant get host name '+host); except end; //вспомогательная функция конвертирующая массив байт в строку. function raw_string(const a:array of byte):string; var i:Integer; ret:string; begin ret:=''; for i:=0 to high(a) do begin ret:=ret+chr(a[i]); end; Result:=ret; end; ЗАКЛЮЧЕНИЕ И ССЫЛКИ: Естественно использование netbios протокола не заканчивается на использовании расшаренных дисков, то что с ним сделали ребята из MS даст вам работы на многие ночи вперед и быть может скоро найденная вами дырка появиться в новостях багтрака. В заключение приведу несколько интересных ссылок по данной теме. Документация: MSDN http://msdn.microsoft.com Здесь можно найти как описание winapi функций так и сам протокол netbios. Только они его переименовали и стали называть CIFS (common internet file system) Nessus project http://www.nessus.org Это очень хороший сканер безопасности для *nix систем, в том числе и netbios уизвимостей. Его плугины поставляются в исходном коде, что очень может помочь вам. Программы: Pandora ultimate scanner www.bethoven.f2s.com bethoven.pisem.net Это мой сайт на котором ведется разработка нетбиос сканера Pandora.Он имеет множество уникальных возможностей, перечислю только несколько: Полный автоматизм работы,укажите диапазоны IP все остальное Pandora сделает сама. Автоматическое копирование файлов с расшаренных ресурсов. Автоматический подбор пароля анлогично pqwak. Работа в скрытом режиме как backdoors. Полный remote administrative control. и многое, многое другое. LANguard Network Scanner http://www.gfi.com/nsnetscan.shtml Этот сканер хорош тем что дает возможность получать информацию обо всех ресурсах, подключаться указывая логин и пароль.А также проверять открытые порты, тип операционной системы и делать snmp walk. ENT (Essential NetTools) http://www.tamos.com Довольно шустро получает имена хостов.Лучший способ проверить правильно ли настроен у вас netbios. Также встроена поддержка NAT (network auditing tool) порт с *nix утилиты, которая может подключаться к ресурсам перебирая логины, и пароли из вордлиста. Contacts: mail: bethoven99@chat.ru bethoven99@mail.ru website: www.bethoven.f2s.com 2001 (c) Bethoven