Почитайте!

Нас читают

Статьи о программировании и не только

Mail.Ru

Rambler's Top100

Programming Blogs - BlogCatalog Blog Directory

Сделай сам: "Вскрывалка паролей"

17.12.2007 от Иван Ширко

Каждому пользователю ПК время от времени приходится вводить пароли: для установки программы, для соединения с интернетом, для получения почты и т.д. Как правило, при вводе пароля, вместо нормальных символов появляются звёздочки ('*'). Делается такая конспирация не только для сокрытия пароля от посторонних глаз, но и для того, чтобы злоумышленник, получивший доступ к компьютеру, не мог узнать пароли, сохранённые в системе. Но, как известно, нет совершенной защиты, поэтому теперь можно найти много программ для извлечения паролей  из-под "звёздочек". Некоторые программы могут показывать пароль в отдельном окошке, другие же неким чудесным образом заставляют превратиться "звёздочки" в нормальные символы. В данной статье мы рассмотрим процесс создания программы, которая умеет "выковыривать" пароли двумя вышеописанными способами.

         Вначале немного теории. Windows, судя по названию, это "сборище" окон. Каждое окно обычно содержит другие окна, т.е. является родителем для некоторых других окон (эти "другие окна" называют дочерними). Для нашей программы нам достаточно знать, что то поле, куда мы вводим пароли является хоть и маленьким, но окном. А значит, как и любое порядочное окно, оно имеет параметр "текст окна" и умеет принимать\отсылать сообщения. Именно на данных весьма полезных свойствах полей ввода основаны программы для извлечения паролей из-под "звёздочек".

         Итак, способ первый для "вскрытия" паролей: нужно просто узнать текст окна, содержащего пароль. Вот и всё, никаких сложностей. Правда, работать данный способ будет только в Win9x и, возможно, в WinMe. Осталось только написать функцию для получения текста произвольного окна:

Function GetText(WindowHandle: hwnd):string;

var

  txtLength : integer;

  buffer: string;

begin

//Узнаём длину текста

  TxtLength := SendMessage(WindowHandle, WM_GETTEXTLENGTH, 0, 0);

  if txtlength>0 then

begin

    txtlength := txtlength + 1;

    setlength (buffer, txtlength);

    //записываем текст окна в buffer

    sendmessage(WindowHandle, wm_gettext, txtlength, longint(@buffer[1]));

    result := buffer;

  end else result:='';

end;

 

Теперь, если мы вызовем эту функцию, записав в параметр идентификатор поля ввода пароля, то она возвратит нам сам пароль. Как узнать идентификатор нужного окна будет рассказано далее. А сейчас поговорим о втором способе извлечения пароля. Только в данном способе мы не запишем пароль в какую-либо переменную, а заставим поле ввода отобразить вместо звёздочек нормальные символы. Для этого нужно послать ему сообщение EM_SETPASSWORDCHAR. Вообще, это сообщение используется и для того, чтобы нормальный текст заменить каким-либо символом (обычно используются звёздочки). Далее приведена процедура, которая не просто показывает нормальный текст вместо звёздочек, но, если у выбранного поля ввода текст не зашифрован, то мы заменяем его звёздочками. Т.е., если для поля ввода пароля применить эту процедуру, то появятся нормальные символы, а если для того же поля повторить операцию, то текст опять превратится в звёздочки.

Procedure ShowPass(h:hwnd);

var

ch:integer;

  i:integer;

begin

  //узнаём, закодирован ли текст

  ch:=SendMessage(h, EM_GETPASSWORDCHAR, 0, 0);

  //если закодирован, то раскодируем текст, иначе кодируем звёздочками

  if ch>0 then

    i:=0

  else

    i:=ord('*');

  SendMessage(h, EM_SETPASSWORDCHAR, i, 0);

end;

Теперь можно приступить к созданию самой программы, но перед этим нужно оговорить принципы её функционирования:

       пользователь должен как-то указать программе, какой именно пароль он хочет "вскрыть". Наиболее удобным для юзера способом мне представляется следующий: пользователь наводит курсор мышки на поле ввода с нужным паролем, нажимает определённую комбинацию клавиш и получает взамен "звёздочек" нормальный пароль.

       сделаем функцию копирования паролей в буфер обмена (этого нет в подобных программах!). Windows не позволяет просто взять и скопировать пароль, поэтому будем делать так:

1)     Заменяем "звёздочки" на обычные символы;

2)     Выделяем весь текст в поле ввода;

3)     Копируем выделенный текст в буфер обмена;

4)     Обратно маскируем пароль "звёздочками.

Теперь запускаем Delphi и делаем формочку, взяв за образец рис.1.


В свойстве формы FormStyle установите константу fsStayOnTop, чтобы окно нашей программы находилось поверх остальных. Запишите функцию GetText и процедуру ShowPass (см. выше). В разделе Var нужно объявить несколько глобальных переменных:

p:TPoint;

h:HWND;

ch:Integer;

s:String;

Процедура обработки нажатия на кнопку "Показать\Спрятать пароль":

procedure TForm1.Button1Click(Sender: TObject);

begin

//узнаём координаты курсора мыши

  getcursorpos(p);

//получаем идентификатор окна, находящегося под курсором мыши

  h:=windowfrompoint(p);

//прячем\показываем пароль

  ShowPass(h);

//перерисовываем окно

  InvalidateRect(h, nil, true);

end;

Данная процедура позволяет маскировать\демаскировать текст почти любого поля ввода.

Процедура обработки нажатия на кнопку "Скопировать пароль":

procedure TForm1.Button2Click(Sender: TObject);

begin

//узнаём координаты курсора мыши

  getcursorpos(p);

//получаем идентификатор окна, находящегося под курсором мыши

  h:=windowfrompoint(p);

//каким символом замаскирован текст в данном окне?

  ch:=SendMessage(h, EM_GETPASSWORDCHAR, 0, 0);

//если пароль замаскирован, то показываем его в нормальном виде

  if ch>0 then

    SendMessage(h, EM_SETPASSWORDCHAR, 0, 0);

//выделяем весь текст

  SendMessage(h, EM_SETSEL, 0, -1);

//копируем выделенный текст

  SendMessage(h, WM_COPY, 0, 0);

//если мы "вскрывали" пароль, то опять маскируем его

  if ch>0 then

    SendMessage(h,EM_SETPASSWORDCHAR, ch, 0);

//перерисовываем окно

  InvalidateRect(h, nil, true);

end;

Процедура обработки нажатия на кнопку "Показать пароль в отдельном окне":

procedure TForm1.Button3Click(Sender: TObject);

begin

//узнаём координаты курсора мыши

  getcursorpos(p);

//получаем идентификатор окна, находящегося под курсором мыши

  h:=windowfrompoint(p);

//получаем текст окна

  s:=gettext(h);

//если текст не является пустой строкой, то показываем его пользователю

  if s<>'' then

  begin

    setforegroundwindow(form1.handle);

    showmessage(s);

  end;

end;

         С помощью данной процедуры (работает она только в Win9x) можно узнать не только пароль, скрытый под "звёздочками", но и текст практически любого стандартного элемента управления Windows: поля ввода, кнопки, флажка (checkbox) и др. Напомню, что текст копируется в буфер обмена, работа с которым будет рассмотрена в одной из следующих статей.

         В принципе программа уже готова к эксплуатации. Но для удобства пользователя сделаем, как и собирались, поддержку "горячих клавиш". Для этого мы воспользуемся функцией

RegisterHotKey(

    HWND hWnd, // этому окну придёт уведомление о нажатии

     комбинации клавиш

    int id,           // идентификатор "горячих клавиш"

    UINT fsModifiers,   // должны ли быть нажаты клавиши Ctrl, Shift или Alt

    UINT vk      // код клавиши, на которую мы будем реагировать

   );

         Для события OnCreate формы запишите процедуру:

procedure TForm1.FormCreate(Sender: TObject);

begin

//регистрируем сочетание Shift+Alt+F9

 If not RegisterHotkey

         (Handle, 1, MOD_ALT or MOD_SHIFT, VK_F9) Then

   ShowMessage('Нельзя использовать данное сочетание клавиш!');

//регистрируем сочетание Shift+Alt+F8

 If not RegisterHotkey

         (Handle, 2, MOD_ALT or MOD_SHIFT, VK_F8) Then

   ShowMessage('Нельзя использовать данное сочетание клавиш!');

//регистрируем сочетание Shift+Alt+F7

 If not RegisterHotkey

        (Handle, 3, MOD_ALT or MOD_SHIFT, VK_F7) Then

   ShowMessage('Нельзя использовать данное сочетание клавиш!');

end;

         Теперь в секции Private объявите процедуру, которая будет реагировать на нажатие комбинаций клавиш:

Procedure WMHotkey( Var msg: TWMHotkey ); message WM_HOTKEY;

         А вот и сама процедура:

Procedure TForm1.WMHotkey( Var msg: TWMHotkey );

begin

 case msg.hotkey of

//если нажато Shift+Alt+F9, то копируем пароль

  1:begin

     getcursorpos(p);

     h:=windowfrompoint(p);

     ch:=SendMessage(h,EM_GETPASSWORDCHAR,0,0);

     if ch>0 then

       SendMessage(h,EM_SETPASSWORDCHAR,0,0);

     SendMessage(h,EM_SETSEL,0,-1);

     SendMessage(h,WM_COPY,0,0);

     if ch>0 then

       SendMessage(h,EM_SETPASSWORDCHAR,ch,0);

     InvalidateRect(h,nil,true);

    end;

//если нажато Shift+Alt+F8, то прячем\показываем пароль пароль

   2:begin

      getcursorpos(p);

      h:=windowfrompoint(p);

      ShowPass(h);

      InvalidateRect(h,nil,true);

     end;

//если нажато Shift+Alt+F9, то показываем пароль в отдельном окне

   3:begin

      getcursorpos(p);

      h:=windowfrompoint(p);

      s:=gettext(h); 
    
if s<>'' then

      begin

        setforegroundwindow(form1.handle);

        showmessage(s);

        end;

     end;

 end;

end;

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

P. S.

         Разумеется, данную программу нельзя применять ни в каких деструктивных целях.

Иван Ширко
ishyrko@gmail.com

Рубрики: Delphi, Сделай сам | Комментарии (2) »

Комментарии (2)

  1. Сделай сам: IE и Delphi – вместе веселее! | Статьи о программировании и не только пишет:

    [...] На первый вопрос я уже дал частичный ответ в статье Сделай сам: “Вскрывалка паролей”, но нам нужно копнуть немного глубже, а второй вопрос [...]

  2. samsim пишет:

    Нуу..ссс.. Такая програма будет еффективна только в том случае когда пароль цыфровой и имеет небольшую длину.