Алексей
Волков, Вячеслав Семенов
Программные средства
удаленного администрирования сети нашли довольно широкое применение.
Администратор любой сети в той или иной мере использует их для облегчения своей
работы. В сетевых операционных системах подобный сервис уже включен в состав ОС
и, как правило, представляет собой набор команд, позволяющих администратору
управлять ресурсами сервера и сети в целом, где бы он ни находился. Вот почему
мечта любого хакера – получить права доступа администратора взламываемой сети.
Но так ли важно иметь подобные привилегии, если речь идет об ОС Windows?
Администрировать сети, построенные с использованием операционной системы
UNIX и ее клонов – дело сложное, поскольку требует от администратора знание
сотен команд и формата конфигурационных файлов, отвечающих за настройку и
работу оборудования. В качестве компенсации администратор получает максимальную
гибкость конфигурирования сети и полный доступ ко всем ресурсам своей машины
(сервера), машин клиентов и различного дополнительного оборудования.
Что касается Windows – то здесь дело обстоит несколько иначе. Администрировать
сеть на базе NT на гораздо проще, однако за все надо платить. В данном случае
администратор платит уровнем доступа к ресурсам сети. В чем заключается
администрирование Windows? По большому счету, в настройках оборудования и
редактированию нескольких файлов и ключей реестра. Объем работ зависит лишь от
сложности построения сети.
Для того чтобы выключить или перезагрузить удаленный компьютер, в ОС
UNIX администратору (пользователю root) необходимо войти через TELNET на эту
машину и ввести команду shutdown или reboot соответственно. Администратор,
работающий с сетью на базе ОС Windows, скорей всего будет сам бегать по
кабинетам и нажимать кнопки Power или Reset.
Такое положение дел мало кого устраивало, и компания Microsoft решила
устранить эту брешь (как обычно, за большие деньги) и с выходом Windows NT
Server объявила о начале проекта Microsoft BackOffice. Пропагандируемая
Microsoft как интегрированная и управляемая система специализированных серверов
офиса, BackOrifice в действительности представляет собой совокупность отдельных
продуктов, предназначенных не столько для администрирования (хотя эти функции в
ней присутствуют), сколько для создания приложений клиент-сервер.
В состав BackOffice входят следующие продукты:
Windows NT Server, составляющий основу для построения остальных серверов:
сервер баз данных Microsoft SQL Server, почтовый сервер Microsoft Mail Server,
сервер интегрированной службы обработки сообщений Microsoft Exchange, шлюз к
SNA-сетям Microsoft SNA Server и сервер управления вычислительной системой
Microsoft System Management Server (SMS). Нас интересует лишь
последний сервер – System Management, поскольку именно в него и включены функции
для удаленного администрирования сети.
Этот сервер автоматически собирает информацию об аппаратных и программных ресурсах хостов сети, позволяет распределять и устанавливать программное обеспечение на любом хосте, анализировать и настраивать сетевые протоколы, а также удаленно управлять мышью, клавиатурой и «видеть» экран любого ПК, работающего в сети под управлением MS-DOS или Windows.
Ответным ударом хакеров на выход BackOffice
стала
программа, созданная группой The Cult of the Dead Cow и названная BackOrifice (задний проход) в честь своего
предшественника. Недоделанная, с неправильно работающим графическим
интерфейсом, она все же вполне сносно работала из командной строки и выполняла
фактически те же функции, что и SMS. Ее преимущество над
системой BackOrifice заключается в полной открытости кода и наличии массы
полезных функций. Вот лишь некоторые из них:
·
доступ к жесткому диску удаленной машины;
·
редактирование реестра;
·
полный контроль над файловой системой;
·
отчёт о введённых паролях;
·
копия экрана;
·
просмотр сетевых ресурсов удаленной машины;
·
управление списком процессов; удалённая перезагрузка;
·
удалённое выполнение программ с возможностью перенаправления консоли.
Тем не менее, эту программу можно было воспринимать двояко. С одной стороны
– это весьма полезная утилита администрирования Windows-машины, с другой – опасный
«троянец», позволяющий злоумышленнику полностью захватить контроль над
системой. Ряд пользователей начал распространять программу по Сети в виде
«ускорителей Интернета» и тому подобных вещей (размер сервера BackOrifice
всего 120 килобайт, что значительно упрощало задачу). Хакерский уклон был
«налицо», и вирусологи забили тревогу: появился новый «троянец».
Весьма любопытной была реакция MicroSoft на Back Orifice: «Мы не
придаем большого значения появлению этой программы, и не думаем, что на неё
следует обращать внимание нашим клиентам». В самом деле – ну, «через Интернет»,
ну, «полный контроль», но BackOffice-то лучше! А прогресс не стоял на месте.
Появились другие коммерческие программы удаленного администрирования (Landesk
Management Suite, Managewise и им подобные), Microsoft
выпускала новые
операционные системы, совершенствовался BackOffice,
но вместе с ним
совершенствовался и BackOrifice.
Наконец, The Cult of the Dead Cow создали BackOrifice2000. Эта программа представляет собой переработанную и значительно
улучшенную версию BackOrifice. Доведен до ума GUI, добавлено много новых
функций. Отрадно, что упор теперь сделан именно на администрирование, а не на
взлом – об этом говорит наличие дополнительных модулей шифрования,
аутентификация паролем и другие существенные доработки. Тем не менее, в основе BO2K
лежит «движок» от BackOrifice, а это значит, что
Microsoft не
извлекла для себя никаких уроков и не сделала ничего, чтобы хоть как-то
обезопасить свои операционные системы.
Существует еще одно принципиальное отличие ОС Windows от ОС UNIX и ей
подобных. В ОС UNIX процесс, созданный пользователем, имеет те же привилегии,
что и пользователь. Конечно, при определенных условиях процесс может
затребовать на время более высоких привилегий, но как за такое короткое время
поднять его общие привилегии?
Это существенно усложняет создание программ типа Back Orifice для
платформы UNIX. В ОС Windows все процессы равны: если пользователь зашел на сервер
и решил его перезагрузить с помощью написанной им программы, то у него это
получится.
Техника программ удаленного администрирования (BackOrifice не
исключение) предельно проста. Программа состоит из двух частей – сервера и
клиента. Сервер находится на удаленной (администрируемой) машине и оснащен
всеми необходимыми для администратора функциями. Каждая функция вызывается
специальной командой, поступающей по сети от клиента, находящегося на машине
администратора. Получив команду, сервер запускает соответствующую ей
подпрограмму и отправляет результат клиенту, который информирует администратора
о состоянии удаленной машины. При этом весь межсетевой обмен может быть
зашифрован, могут использоваться различные пароли и т.п.
Давайте рассмотрим на практике, каким образом можно заставить удаленную
машину выполнить необходимые действия без участия пользователя. Попробуем
разработать собственную программу удаленного администрирования. В качестве языка
программирования выберем Delphi 5 для того, чтобы наглядно продемонстрировать,
что даже прикладной язык может использоваться для создания такого рода
программ.
Администратору необходимо обеспечить выполнение следующих функций:
·
Перемещение
мыши в нужные координаты и нажатие на ее кнопки
·
Смену
раскладки клавиатуры
·
Изменение
разрешения экрана
·
Переключение
световых индикаторов клавиатуры
·
Запретить
или разрешить реакцию системы на комбинацию CTRL+ALT+DEL
·
Получение
списка файлов и каталогов удаленней машины
·
Запуск
файлов на удаленной машине
·
Получение
содержимого экрана удаленной машины
·
Производить
операции с CDROM (открыть, закрыть)
·
Выключать
и включать монитор
·
Выключать
удаленную машину
·
Скрывать
и показывать сервер в окне CTRL+ALT+DEL
Команды и данные для обеспечения более высокого быстродействия удобно
передавать по протоколу UDP, без использования шифрования. Программу клиент
разбирать не будем, поскольку он лишь передает серверу команды в соответствии с
выбранным администратором действием и получает ответ от сервера. Исходный код
сервера разберем подробнее.
Приведем выдержки из программного кода, поясняющие методы выполнения
административных функций удаленного управления.
uses
Windows, Messages,
SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
NMUDP, Psock,
ShellApi, MMSystem, NMSTRM, StdCtrls, Buttons, ExtCtrls,
FileCtrl;
function RegisterServiceProcess(dwProcessID, dwType:
Integer): Integer; stdcall;
external
'KERNEL32.DLL';
type
TFun = Function(lpBuffer:
PChar; var nSize: DWORD): BOOL; stdcall;
Tserver =
class(TForm) {}
FLB:
TFileListBox;
UDP: TNMUDP;
Powersock:
TPowersock;
Dir:
TDirectoryListBox;
Drive:
TDriveComboBox;
ListBox1:
TListBox;
procedure
Send(Ip,Mes : String);
procedure
UDPDataReceived(Sender: TComponent; NumberBytes: Integer;FromIP: String; Port:
Integer);
end;
const Result = 'Операция выполнена!';
var
Server: TServer;
MessageStream :
TStringStream;
FileNameImg :
String;
Implementation
{$R *.DFM}
// Вспомогательные
процедуры
Procedure OnKey(Key : Word); // Включить виртуальную клавишу
Var KeyState : TKeyBoardState;
begin
GetKeyboardState(
KeyState );//копирует состояние всех 256 виртуальных клавиш в буфер KeyState
KeyState[Key] :=
KeyState[Key] or $01;//установка соответствующей клавиши
SetKeyboardState(
KeyState );//установка 256 клавиш в соответствии с данными буфера
end;
Procedure OffKey(Key : Word); // Выключить виртуальную
клавишу
Var KeyState : TKeyBoardState;
begin
GetKeyboardState(
KeyState );
KeyState[Key] :=
0;
SetKeyboardState(
KeyState );
end;
procedure TServer.Send(Ip,Mes : String); // Послать
сообщение
var MessageStream : TStringStream;
begin
MessageStream := TStringStream.Create('');
MessageStream.Position:=0;
MessageStream.WriteString(Mes);
UDP.RemoteHost:= Ip;
UDP.SendStream(MessageStream);
MessageStream.Destroy;
end;
// Основная
процедура, иллюстрирующая выполняемые действия
procedure TServer.UDPDataReceived(Sender: TComponent;
NumberBytes: Integer;
FromIP: String;
Port: Integer);
var Res,ComPar,Command,Param,Par1,Par2 : String;
B : TBitmap;
ScreenDC : HDC;
DeviceMode :
TDevMode;
T : TDevMode
absolute 0;
Layout: array[0..
KL_NAMELENGTH] of char;
Pt : TPoint;
begin
MessageStream.Position
:= 0;
UDP.ReadStream(MessageStream);
ComPar :=
MessageStream.DataString;
Command :=
Copy(ComPar,1,3);
Parameter :=
Copy(ComPar,4,Length(ComPar)-3);
//--------Мышь-------------------------------------
//перемещение
Application.ProcessMessages;
Pt.x :=
StrToInt(x_pos);
Pt.y :=
StrToInt(y_pos);
{Преобразуем Pt к
координатам экрана}
Pt.x := Round(Pt.x
* (65535 / Screen.Width));
Pt.y := Round(Pt.y
* (65535 / Screen.Height));
{Переместим курсор
мыши}
Mouse_Event(MOUSEEVENTF_ABSOLUTE or
MOUSEEVENTF_MOVE,
Pt.x,Pt.y, 0, 0);
{Функция mouse_event синтезирует перемещение мыши и нажатия
на ее кнопки.
Параметры: mouse_event(
DWORD dwFlags, // флаги, указывающие на соответствующее
событие:
MOUSEEVENTF_ABSOLUTE Переменные dx и dy содержат АБСОЛЮТНЫЕ координаты.
Если флаг не установлен, эти переменные содержат смещение относительно текущего
положения.
MOUSEEVENTF_MOVE Произошло перемещение мыши.
MOUSEEVENTF_LEFTDOWN Левая кнопка мыши нажата.
MOUSEEVENTF_LEFTUP Левая кнопка мышы отжата.
MOUSEEVENTF_RIGHTDOWN Правая кнопка мыши нажата.
MOUSEEVENTF_RIGHTUP Правая кнопка мышы отжата.
MOUSEEVENTF_MIDDLEDOWN Средняя кнопка мыши нажата.
MOUSEEVENTF_MIDDLEUP Средняя кнопка мышы отжата.
DWORD dx, // горизонтальная позиция мыши или ее
изменение
DWORD dy, // вертикальная позиция мыши или ее изменение
DWORD dwData, // количество врашений колеса мыши
DWORD dwExtraInfo
// информация о связаннов 32-битном
приложении
(для ее получения
приложение вызывает функцию GetMessageExtraInfo)
);}
//левая кнопка
Application.ProcessMessages;
Pt.x :=
StrToInt(x_pos);
Pt.y :=
StrToInt(y_pos);
Mouse_Event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_LEFTDOWN,
Pt.x,Pt.y,0,0);//нажали
{Имитируем
отпускание левой кнопки мыши}
Mouse_Event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_LEFTUP,
Pt.x,Pt.y,0,0);//отпустили
//правая кнопка
Application.ProcessMessages;
Pt.x :=
StrToInt(x_pos);
Pt.y :=
StrToInt(y_pos);
Mouse_Event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_RIGHTDOWN,
Pt.x,Pt.y,0,0);//нажали
{Имитируем
отпускание левой кнопки мыши}
Mouse_Event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_RIGHTUP,
Pt.x,Pt.y,0,0);//отпустили
// -----------Индикаторы-----------------------------
//NumLock
OnKey(Vk_NumLock);
OffKey(Vk_NumLock);
//CapsLock
OnKey(VK_CAPITAL);
OffKey(VK_CAPITAL);
//ScrollLock
OnKey(Vk_Scroll);
OffKey(Vk_Scroll);
//----------Реакция на
ALT+DEL----------------------------------------------
// Включение режима
SystemParametersInfo(SPI_SCREENSAVERRUNNING, 1, 0,
0);//SPI_SCREENSAVERRUNNING используется системой и не должен изменяться
пользователем.
В действительности
- реакция на ALT+DEL (1,0 - запретить реакцию 0 - не записывать в профайл
пользователя)
// Выключение режима
SystemParametersInfo(SPI_SCREENSAVERRUNNING, 0, 0, 0);
//----------------Смена раскладки
клавиатуры---------------------------------
//Русская
LoadKeyboardLayout(
StrCopy(Layout,'00000419'),KLF_ACTIVATE);//загрузка и активизация (флаг
KLF_ACTIVATE) раскладки 00000419 (Ru)
//Латинская
LoadKeyboardLayout(StrCopy(Layout,'00000409'),KLF_ACTIVATE);//загрузка
и активизация (флаг KLF_ACTIVATE) раскладки 00000409 (En)
//-------------------Изменить разрешение экрана-------------------------------
with DeviceMode do
begin
dmSize:=SizeOf(DeviceMode);
dmBitsPerPel:=16;
dmPelsWidth:=StrToInt(h_pix_num);
//640,800,1024,1280
dmPelsHeight:=StrToInt(v_pix_num); //480,600,768,1024
dmFields:=DM_BITSPERPEL or DM_PELSWIDTH or DM_PELSHEIGHT;
ResBool := False;
if
ChangeDisplaySettings(DeviceMode,CDS_TEST or CDS_FULLSCREEN) <>
DISP_CHANGE_SUCCESSFUL
then
Exit; end;
ChangeDisplaySettings(DeviceMode,CDS_FULLSCREEN) =
DISP_CHANGE_SUCCESSFUL;
if ResBool then Res
:= 'Разрешение экрана изменено' else
Res := 'Ошибка
изменения разрешения!';
end;
{Функция ChangeDisplaySettings устанавливает соответствующий
графический режим.
Параметры: ChangeDisplaySettings(
LPDEVMODE
lpDevMode,
DWORD dwflags
);
lpDevMode - указатель структуры DEVMODE, описывающей
графический режим.
dmSize размер структуры DEVMODE.
dmBitsPerPel Глубина
цвета (бит на пиксел)
dmPelsWidth Размер
по горизонтали в пикселах
dmPelsHeight Размер
по вертикали в пикселах
dmFields Флаги режима:
DM_BITSPERPEL Используется значение dmBitsPerPel.
DM_PELSWIDTH Используется значение dmPelsWidth.
DM_PELSHEIGHT Используется значение dmPelsHeight.
dwflags - флаги, определяющие метод изменения режима:
CDS_FULLSCREEN Динамическое изменение графического режима
CDS_TEST Система тестирует устанавливаемый
графический режим.
Возвращаемые значения:
DISP_CHANGE_SUCCESSFUL Успешная
установка режима.
//-----------Работа с
файлами-------------------------------------------------
//лист каталогов
Dir.Directory :=
Parameter;
Dir.Update;
Result.Lines.Add(Dir.Items.Text);
//лист дисков
Drive.Drive :=
Parameter[1];
Drive.Update;
Result.Linse.Add(Dir.Items.Text);
//лист файлов
FLB.Items.Clear;
FLB.Directory :=
Parameter;
FLB.Update;
Result.Lines.Add(FLB.Items.Text);
//Запуск программы
ShellExecute(Handle,nil,PChar(path_and_name),nil,nil,SW_RESTORE);
{Функция ShellExecute открывает или распечатывает указанный
файл.
Файл может быть
программой или документом.
Вызов: ShellExecute(
HWND hwnd, // дескриптор родительского (вызывающего) окна
LPCTSTR
lpOperation, // указатель на строку,
описывающую операцию над файлом (nil - открыть файл)
LPCTSTR lpFile, // указатель на имя файла или имя папки
LPCTSTR
lpParameters, // указатель на строку с
параметрами запуска (nil - нет)
LPCTSTR lpDirectory, // указатель на строку с директорией по
умолчанию (нет)
INT nShowCmd //
как показывать открываемый файл
SW_RESTORE Активизировать и показать окно программы.
);}
//-----------Монитор--------------------------------------------------------
//Выключить
SendMessage(Application.Handle,//послать окну
wm_SysCommand,//сообщение с командой
SC_MonitorPower,//питание монитора
0); {Off}//выключить
//Включить
SendMessage(Application.Handle, wm_SysCommand, SC_MonitorPower, -1);
{On}
//-----------Считывание
экрана-----------------------------------------------
B:=TBitmap.Create;
with B do
begin
Width:=Screen.Width;//снимать будем изображение
Height:=Screen.Height;//со всего экрана
ScreenDC:=GetDC(0);//получаем дескриптор экрана
try
BitBlt(Canvas.Handle, 0,0,Width,Height,ScreenDC, 0, 0, SRCCOPY);
{Функция BitBlt передает графическую информацию с указанного
графического устройства на другое устройство.
Вызов: BitBlt(
HDC hdcDest, //
дескриптор принимающего устройства (канва Bitmap)
int nXDest, //
начальное положение изображения на приемнике - координата x
int nYDest, //
начальное положение изображения на приемнике - координата y
int nWidth, //
ширина области изображения на приемнике
int nHeight, //
высота области изображения на приемнике
HDC hdcSrc, //
дескриптор передающего устройства
int nXSrc, //
начальное положение изображения на источнике - координата x
int nYSrc, //
начальное положение изображения на источнике - координата y
DWORD dwRop //
код растровой операции
SRCCOPY копировать изображение
);}
finally
ReleaseDC(0,
ScreenDC);//освобождаем дескриптор
end;
end; {Whit}
Try
B.SaveToFile(FileNameImg);//сохраняем в файл
except End;
B.Destroy;//уничтожаем объект Bitmap
Send(FromIp,FileNameImg);
//---------Закрыть CD-ROM----------------------------------------------------
mciSendString('Set
cdaudio door closed wait', nil, 0, handle);
{Функция mciSendString посылает команду MCI-устройству.
Вызов: mciSendString(
LPCTSTR lpszCommand,//команда
LPTSTR lpszReturnString,//адрес буфера для
приема результатов (нет)
UINT cchReturn,//размер буфера (0)
HANDLE hwndCallback//дескриптор
вызывающего окна, если флаг нотификации в команде установлен );}
//---------Открыть
CD-ROM----------------------------------------------------
mciSendString('Set cdaudio door open wait', nil, 0, handle);
//-----------Выключить
компьютер---------------------------------------------
Application.Terminate;
ExitWindowsEx(EWX_FORCE,0);
ExitWindowsEx(EWX_ShutDown,0);
{Функция ExitWindowsEx позволяет завершить сеанс,
перезагрузить или выключить систему.
BOOL ExitWindowsEx(
UINT uFlags, // флаги операции
EWX_FORCE Аварийное
завершение процесса без сохранения всех данных.
EWX_SHUTDOWN Выключить питание компьютера. Все процессы
будут остановлены и буферы сохранены на диск.
DWORD dwReserved // зарезервировано
);
//-----------Показ сервера в окне
ALT+DEL------------------------------------
//Показать
if not (csDesigning in ComponentState) then
RegisterServiceProcess(GetCurrentProcessID, 0);
//Скрыть
if not (csDesigning in ComponentState) then
RegisterServiceProcess(GetCurrentProcessID, 1);
{Функция RegisterServiceProcess регистрирует процесс как
служебный или снимает эту регистрацию. Служебный процесс продолжает функционировать
после того, как пользователь отключится.
Вызов: RegisterServiceProcess(
DWORD dwProcessId,//идентификатор процесса
DWORD
dwType//тип процесса:
RSP_SIMPLE_SERVICE Служебный процесс (1)
RSP_UNREGISTER_SERVICE Обычный процесс(0)
);}
Дополнительную информацию о приведенных функциях несложно почерпнуть из справочной системы Delphi.
А дальше – пишете клиента и устанавливаете сервер на машинах своей сети
и можете давать рекомендации пользователям по телефону, не бегая по зданию
компании. Любопытно, что все антивирусы программы распознают только известные
программы (типа BackOrifice), поэтому ваша программа не будет пугать
пользователей, запустивших антивирусный пакет.
В заключение приведем несколько ссылок.
При написании статьи использованы фрагменты исходного кода программы Net Manager (автор – Д.Кривов). Полную версию программы Вы можете получить по
адресу
http://www.cherepovets-city.ru/insecure/utilites/dist/netman.zip
Официальный сайт группы The Cult of the Dead Cow находится по адресу
Официальный сайт программы BackOrifice2000: