Rambler's Top100

Back Orifice - своими руками

Алексей Волков, Вячеслав Семенов

Программные средства удаленного администрирования сети нашли довольно широкое применение. Администратор любой сети в той или иной мере использует их для облегчения своей работы. В сетевых операционных системах подобный сервис уже включен в состав ОС и, как правило, представляет собой набор команд, позволяющих администратору управлять ресурсами сервера и сети в целом, где бы он ни находился. Вот почему мечта любого хакера – получить права доступа администратора взламываемой сети. Но так ли важно иметь подобные привилегии, если речь идет об ОС Windows?

Back Orifice, или…

Администрировать сети, построенные с использованием операционной системы 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 уязвимой

Существует еще одно принципиальное отличие ОС Windows от ОС UNIX и ей подобных. В ОС UNIX процесс, созданный пользователем, имеет те же привилегии, что и пользователь. Конечно, при определенных условиях процесс может затребовать на время более высоких привилегий, но как за такое короткое время поднять его общие привилегии?

Это существенно усложняет создание программ типа Back Orifice для платформы UNIX. В ОС Windows все процессы равны: если пользователь зашел на сервер и решил его перезагрузить с помощью написанной им программы, то у него это получится.

Техника программ удаленного администрирования (BackOrifice не исключение) предельно проста. Программа состоит из двух частей – сервера и клиента. Сервер находится на удаленной (администрируемой) машине и оснащен всеми необходимыми для администратора функциями. Каждая функция вызывается специальной командой, поступающей по сети от клиента, находящегося на машине администратора. Получив команду, сервер запускает соответствующую ей подпрограмму и отправляет результат клиенту, который информирует администратора о состоянии удаленной машины. При этом весь межсетевой обмен может быть зашифрован, могут использоваться различные пароли и т.п.

Давайте рассмотрим на практике, каким образом можно заставить удаленную машину выполнить необходимые действия без участия пользователя. Попробуем разработать собственную программу удаленного администрирования. В качестве языка программирования выберем Delphi 5 для того, чтобы наглядно продемонстрировать, что даже прикладной язык может использоваться для создания такого рода программ.

Администратору необходимо обеспечить выполнение следующих функций:

·        Перемещение мыши в нужные координаты и нажатие на ее кнопки

·        Смену раскладки клавиатуры

·        Изменение разрешения экрана

·        Переключение световых индикаторов клавиатуры

·        Запретить или разрешить реакцию системы на комбинацию CTRL+ALT+DEL

·        Получение списка файлов и каталогов удаленней машины

·        Запуск файлов на удаленной машине

·        Получение содержимого экрана удаленной машины

·        Производить операции с CDROM (открыть, закрыть)

·        Выключать и включать монитор

·        Выключать удаленную машину

·        Скрывать и показывать сервер в окне CTRL+ALT+DEL

Команды и данные для обеспечения более высокого быстродействия удобно передавать по протоколу UDP, без использования шифрования. Программу клиент разбирать не будем, поскольку он лишь передает серверу команды в соответствии с выбранным администратором действием и получает ответ от сервера. Исходный код сервера разберем подробнее.

Удаленное управление Windows: это вы можете

Приведем выдержки из программного кода, поясняющие методы выполнения административных функций удаленного управления.

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 находится по адресу

http://www.cultdeadcow.com

Официальный сайт программы BackOrifice2000:

http://www.bo2k.com

Rambler's Top100 ???????@Mail.ru