/*-----------------------------------------------------------------------*/
/* R I N G 0, I S S U E # 1 */
/*-----------------------------------------------------------------------*/
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
http://www.bethoven.f2s.com
http://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:
[email protected]
[email protected]
website:
www.bethoven.f2s.com
2001 (c) Bethoven