keer-necrolog

некрологна Web-Money Keeper Classic

крис касперски ака мыщъ, no-email

какую информацию собирает о нас система WebMoney и можно ли ей доверять? мыщъх, просидевший за дизассемблером всю ночь напролет, пришел к весьма неутешительным выводам, которых придерживаются и другие пользователи. как обезопасить себя и обеспечить максимальную анонимность?

Популярная платежная система Web-Money реализована в виде двух независимых программ — KeeperClassic и KeeperLight, каждая из которых имеет свои достоинства и недостатки.

KeeperClassic представляет обычное Windows-приложение, требующее инсталляции на компьютер и непонятно что на нем делающее. По словам некоторых пользователей «это —поделка от Web-Money, в которую неизвестно что зашито, может, и троян. И даже если его там нет, сие творение небезупречно – пару раз ставил на несколько компов, так они стали хромать на обе ноги, вплоть до BSOD. На других же компах работа была нормальной. Следовательно, эта программа недоработана и ведет себя непредсказуемо в зависимости от неизвестно чего».

Рисунок 1 установка KeeperClassic на компьютер

Но прикладное приложение (которым пытается казаться KeeperClassic) не может вызывать BSOD, поскольку это прерогатива драйверов, работающих на уровне ядра. Значит, Keeper каким-то образом проникает в ядро, причем не совсем легальным путем (отсюда конфликты и BSOD). Во всяком случае, я не видел никакого запроса на установку драйверов при инсталляции и никаких драйверов не появилось в каталоге WINNT\System32\Drivers, где им и положено быть, но… запуск утилиты R-Studio, восстанавливающей удаленные файлы, показал наличие созданного и тут же удаленного файла winio.sys, ссылка на который обнаружилась в компоненте Keeper'a: WMClient.dll и, судя по названию, этот драйвер открывает доступ к портам ввода/вывода с прикладного уровня, что создает нехилую дыру в системе безопасности, не говоря уже о том, что некорректное обращение с портами чревато не только голубыми экранами смерти, зависанием компьютера, но и потерей данных вместе с порчей оборудования.

Рисунок 2 утилита R-Studio удаляет драйвер установленный, загруженный и удаленный Keeper'ом

Тут же, по соседству с «winio.sys» приютились текстовые строки — «\\.\PhysicalDrive%d», «\\.\Scsi%d:» и «SCSIDISK», недвусмысленно свидетельствующие в пользу того, что Keeper работает с жесткими дисками на низком уровне!

Рисунок 3 интересные текстовые строки, обнаруженные дизассемблером IDA Pro в файле WMClient.DLL

А дальше… дальше идет нечто совершенно невероятное:

.text:100B7A31push557; nOutBufferSize

.text:100B7A36leaeax, [ebp+OutBuffer]

.text:100B7A3Cpusheax; lpOutBuffer

.text:100B7A3Dpush3Ch; nInBufferSize

.text:100B7A3Fleaecx, [ebp+OutBuffer]

.text:100B7A45pushecx; lpInBuffer

.text:100B7A46push4D008h; IoControlCode(IOCTL_SCSI_PASS_THROUGH)

.text:100B7A4Bmovedx, [ebp+hObject]

.text:100B7A4Epushedx; hDevice

.text:100B7A4Fcallds:DeviceIoControl

Листинг 1 фрагмент WMClient.DLL, передающий жесткому диску ATA-команды

Диску посылается IOCTL-код IOCTL_SCSI_PASS_THROUGH, позволяющий передавать любую ATA-команду в обход операционный системы! ATA-команды — это наиболее низкоуровневые команды, на которых «разговаривает» диск и с их помощью можно сделать все, что угодно. Малейшая неосторожность (или несовместимость) способна разрушить содержимое диска или уничтожить его «прошивку», что еще хуже. Девять из десяти, что эта процедура используется для чтения показаний SMART (которые уникальны для каждого жесткого диска, что позволяет отличить его от толпы других), однако, не исключено, что Keeper пишет на диск какую-то гадость. Мыщъх'у было лень досконально изучать этот вопрос, поскольку в любом случае Keeper мутит.

Но это только цветочки. Если поставить Keeper на VMWare, система Web-Money автоматически заблокирует электронный кошелек при первой же попытке оплаты, даже не уведомив тебя об этом! Если бы Keeper просто не работал под VM Ware, то и черт с ним. Может они просто не совместимыми… или VM Ware чего-то дурит (с ней это часто случается). Но… он ведь работает только до первой транзакции, а это значит, что вместе с данными о самой транзакции Keeper скрытно передает некоторую персональную информацию: как минимум конфигурацию оборудования, и, возможно, что-то еще.

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

Система KeeperLight работает только из-под браузера и построена на механизме сертификатов. Никакой дополнительной информации о пользователя она не собирает и единственной ниточкой, за которую могут зацепиться сыщики, оказывается IP-адрес. Не слишком серьезная улика, к тому же всегда существует возможность спрятаться за анонимным Proxy или атаковать один из компьютеров и осуществлять все транзакции его «руками. К сожалению, по своим функциональным возможностям KeeperLight значительно отстает от Classic'а и к тому же пожирает намного больше трафика (что для медленных соединений весьма актуально). Однако, ставить Classic'а на свою основную машину я так и не рискнул. Почему — читайте ниже.

Рисунок 4 вся работа через KeeperLight осуществляется через браузер

Итак, KeeperClassic лежит у нас в руках, а точнее жужжит жестким диском, устанавливая какие-то компоненты, но какие именно не говорит. Вот сука! А еще кто-то вирусов нехорошими словами называет! По одному из определений компьютерный вирус это такая штука, которая скрыто делает на вашем компьютере действия, о которых мы не знаем, а если бы знали — навряд ли бы дали свое согласие.

Чтение технической документации и заумных лицензионных соглашений не дает никакой полезной информации и трепанацией Keeper'а приходится заниматься самостоятельно. Как это можно осуществить? Самое простое – перехватить обмен Keeper'а с «базой», снифая трафик любым подходящим sniffer'ом, например, тем, что встроен в персональный брандмауэр SyGate Firewall, однако, если трафик зашифрован, его будет не так-то легко расшифровать!

Рисунок 5 перехват трафика при помощи пакетного фильтра, встроенного в персональный брандмауэр SyGatePersonalFirewall

Гораздо проще воспользоваться файловым монитором и монитором реестра Марка Руссиновича (оба можно найти на www.sysinternals.com), а так же монитором шины Bus Hound от компании Perisoft (www.perisoft.net). Полезно так же снять дамп с работающей программы любой утилитой по вкусу (например, PE-TOOLS), и поковыряться в нем на предмет интересных текстовых строк, MAC-адресов и прочих приватных данных. Самые опытные исследователи могут прибегнуть к тяжелой артиллерии — дизассемблеру IDA Pro, который покажет чем на самом деле занимается Keeper при запуске и в процессе перевода денег. Естественно, полное дизассемблирование занимает слишком много времени, поэтому мы будем обращать внимание лишь на самые заметные, наименее замаскированные места, сразу же бросающиеся при анализе в глаза.

Рисунок 6 превосходный монитор шины от компании Perisoft

Последняя (на момент написания этих строк) версия Keeper'а проходила под номером 3.0.0.2 и занимала порядка ~1.9 Мбайт. После установки, на диске в папке WebMoney образовалось множество файлов среди которых: WebMoney.exe (пусковой файл, размером 183.024 Байт, упакованный по сообщению PEiD протектором ASProtect 1.2x - 1.3x) и WWClient.dll (динамическая библиотека, реализующая основной функционал, размер — 3.331.824, не упакована).

Рисунок 7 скачиваем Keeper Classic

Собственно говоря, WebMoney.exe можно сразу отбросить в сторону, не тратя силы на распаковку — все равно, ничего интересного там нет. Но прежде представляет интерес запустить монитор реестра и посмотреть в какие ветви реестра лезет Keeper и не пытается ли он получить доступ к той информации, разглашать которую мы не хотим?

Рисунок 8 наблюдение за деятельностью Keeper'а с помощью монитора реестра (листинг приводится с сокращениями)

Даже «невооруженным» глазом видно, что сразу же после запуска Keeper ринулся определять имя чипа сетевой карты («AMD PCNET Family PCI Ethernet» в данном случае), имя машины («W2K»), и, если покопаться в дампе памяти, там можно обнаружить и MAC адрес моей сетевой карты — 00-0C-29-F6-6C-3C (виртуальный, естественно). Кстати, чтобы узнать свой MAC-адрес достаточно запустить штатную утилиту ipconfigc ключом /all:

Рисунок 9 определение собственного MAC-адреса при помощи штатной утилиты ipconfig

«Честные» программы не нуждаются в MAC-адресах и работают с Сетью через TCP/IP протоколы. Зачем же тогда Keeper'у потребовался наш MAC? А вот зачем! MAC-адрес уникален для каждой карты и, хотя его теоретически возможно сменить на другой даже _без_ использования программатора — это считается веской уликой при расследовании преступления.

Значит, все-таки Keeper палит наш компьютер! И насколько глубоко? Берем в руки IDA Pro, загружаем WWClient.dll внутрь и пока оно там дизассемблируется (а дизассемблироваться оно будет долго), достаем из заначки непочатую бутылку пива, затягиваемся сигаретой и думаем, думаем, думаем…

Лучше всего начинать анализ с поиска текстовых строк. Их легко найти в оке «NameWindows», вызываемом комбинацией клавиш <Shift-F4>. Тестовые ASCIIZ-строки начинаются с префикса «a». И, действительно, здесь притаилось немало непуганой дичи:

.rdata:1021ECB0 aPci_wmtid db 'pci_wmtid=',0 ; DATA XREF: sub_100901C0+C45o

.rdata:1021ECBC aPci_pursedest db '&pci_pursedest=',0 ; DATA XREF: sub_100901C0+CCCo

.rdata:1021ECCC aPci_pursesrc db '&pci_pursesrc=',0 ; DATA XREF: sub_100901C0+D53o

.rdata:1021ECDC aPci_amount db '&pci_amount=',0 ; DATA XREF: sub_100901C0+DDAo

.rdata:1021ECEC aPci_marker db '&pci_marker=',0 ; DATA XREF: sub_100901C0+E61o

.rdata:1021ECFC aPci_desc db '&pci_desc=',0 ; DATA XREF: sub_100901C0+EE8o

.rdata:1021ED08 aPci_datecrt db '&pci_datecrt=',0 ; DATA XREF: sub_100901C0+F6Fo

.rdata:1021ED18 aPci_modeTest db '&pci_mode=test',0 ; DATA XREF: sub_100901C0+FFFo

Листинг 2 текстовые строки «pic_xxx», обнаруженные в Keeper'е

Семейство сток, гнездящихся вокруг слова «pci», наводит на мысль, что Keeper, возможно, опрашивает PCI-шину для получения списка подключенных устройств и сканер шины это действительно подтверждает, а в дампе памяти обнаруживаются идентификационные строки всех периферийных устройств.

Поскольку, виртуальные машины и, в частности, VM Ware несут на своем борту довольно специфический набор оборудования и выделяют MAC-адреса из фиксированного пула адресов, становится ясно как система распознает факт наличия виртуальной машины. Она просто сравнивает конфигурацию пользовательского оборудования с конфигурацией виртуальной машины и, если они совпадают, электронный кошелек закрывается без предупреждений. Причем сравнение происходит не на клиентской, а на серверной стороне! То есть, Keeper не просто опрашивает PCI-шину, но еще и передает эти данные в сеть, где они, по всей видимости, заносятся в банк данных, представляющий огромный интерес для спецслужб различных стран.

Штатные средства VM Ware не позволяют менять ни MAC-адреса, ни конфигурацию оборудования (в новых версиях вроде бы сделаны некоторые шаги в этом направлении, но не слишком радикальные). К счастью, есть неофициальная заплатка, позволяющая менять все, что угодно: http://honeynet.rstack.org/tools/vmpatch.c. Эксперименты подтверждают — после изменении конфигурации, Keeper перестает распознавать VM Ware и электронный кошелек больше не «палится».

В текстовых строках можно ковыряться до бесконечности. Это настоящий Клондайк, раскрывающий зловредные намерения Keeper'а хуже любого предателя. На месте разработчиков, мыщъх их бы обязательно зашифровал, а то как-то несерьезно получается.

Как вам нравится следующее? Keeper динамически создает драйвер citio.sys (на NT/W2K/XP)/citio.vxd (на 9x), тут же его загружает в память, а после удаляет:

.rdata:10222D5C aSystem32Driverdb 'system32\drivers\citio.sys',0

.rdata:10222D78 aFileNamedb '\\.\citio',0

.rdata:10222D8C aSystemCitio_vxdb 'system\citio.vxd',0

.rdata:10222DA0 a_Citio_vxddb '\\.\CITIO.VXD',0

Листинг 3 ссылки на неопознанный драйвер, обнаруженные в Keeper'e

С самим драйвером я не разбирался. Выяснил только, что имеет размер 4048 байт и по сообщениям на форумах часто является источником многих проблем. Тут уже дело не в конфиденциальности, а в надежности и стабильности работы. Мастерить драйвера — это вам не прикладные программы писать. Малейшая небрежность/неосторожность превращается в сплошной геморрой. Зачем пускать к себе на компьютер _заведомо_ некорректно написанную программу?!

«Источники, приближенные к кругам разработчиков» сообщили, что все эти драйвера вставлены вовсе не из-за пакости, или желания навредить пользователю. Напротив! Они охраняют Keeper от нехороших программ, крадущих электронную наличность. Как говорится, все на благо пользователя, даже если это благо идет ему вопреки. Мыщъх повторяет еще раз: нормально спроектированный платежный клиент работает исключительно на прикладном уровне, а не вгрызается в систему как бульдозер в асфальт. Если на компьютер проникла зловредная программа, захватившая администраторские права (а такие права заполучить очень легко), она может вытворять с Keeper'ом все, что угодно и никакие драйвера не в состоянии ее остановить, поскольку, после того как зловредная программа загрузит свой собственный драйвер, она уровняет свои шансы с Keeper'ом, а в противостоянии двух драйверов обороняющаяся сторона всегда обречена на поражение.

Но не будем зацикливаться на текстовых строках и двинемся дальше. Посмотрим на список импортируемых API-функций. Для этого достаточно воспользоваться утилитой dumpbin.exe, входящей в штатную поставку компилятора MicrosoftVisualC++ и Platform SDK. Вызываем ее: «dumpbin.exe /EXPORTS WMClient.dll > output» и смотрим на результат:

Dump of file WMClient.dll

KERNEL32.dll

83 DeviceIoControl

353 Thread32Next

352 Thread32First

28C Process32Next

262 Module32Next

260 Module32First

204 Heap32ListNext

203 Heap32ListFirst

28A Process32First

6C CreateToolhelp32Snapshot

Листинг 4 функции, импортируемые Keeper'ом (фрагмент)

Функциисемейства TOOLHELP32 (CreateToolhelp32Snapshot(), Process32First(), Heap32ListFirst(), Heap32ListNext(), Module32First(), Module32Next(), Process32Next(), Thread32First() и Thread32Next()), служатдляполученияспискапроцессовипотоковимеющихсявсистеме. Спрашивается — зачем Keeper'у знать об этом?! Чтобы «отлавливать» троянские программы?! Непохоже… Троянские программы меняют свои имена как перчатки и к тому же никакого «черного списка» внутри Keeper'а нет. Судя по всему, он передает их на сервер и умные дядьки смотрят: а каким, собственного, программным обеспечением мы пользуемся? И, где гарантия, что увидев OllyDbg, PE-TOOLS и прочие хакерские утилиты они не ликвидируют наш аккаунт или не настучат «куда нужно»? Keeper – идеальное средство для удаленного наблюдения за миллионами машин, тем более, что своего любопытна он даже и не скрывает. Больше всего смущает наличие функций Heap32ListFirst() и Heap32ListNext(), выдающих карту памяти каждого из процессов. Сама по себе карта памяти не несет никакой информации, если только… кто-то очень хочет внедриться внутрь чужого процесса!

А функция DeviceIoControl() — это вообще ласты. Ее основное предназначение — посылать драйверам специальные управляющие IOCTL коды, с помощью которых, в частности, можно напрямую читать или писать на диск. Поскольку, разработчики (вот пионеры!) никак не замаскировали ее вызов, все IOCTL-коды видны в IDA Pro как на ладони! Давайте разберемся, что же такого делает Keeper с нашим оборудованием, чего нельзя было сделать с помощью нормальных API-функций?!

Переходим в IDA Pro, нажимаем <Shift-F4> для открытия окна «Name», пишем «DeviceIoControl» (полностью вводить имя необязательно, IDA Pro сама поставит курсор на него, как только поймет что же мы от нее хотим). Теперь нажимаем <ENTER> и оказываемся в секции импорта. По умолчанию IDA Pro отображает только первые две перекрестные ссылки, а чтобы увидеть остальные необходимо в меню «View» выбрать пункт «Open subview», а там — «Crossreferences» или просто нажать: <ALT-V>,<O>,<O>.

Рисунок 10 перекрестные ссылки, ведущие к функции DeviceIoControl()

Первая же перекрестная ссылка ведет нас к следующему коду, который нам сейчас и предстоит дешифровать:

.text:100B76C3push0; lpOverlapped

.text:100B76C5leaedx, [ebp+BytesReturned]

.text:100B76CBpushedx; lpBytesReturned

.text:100B76CCpush18h; nOutBufferSize

.text:100B76CEleaeax, [ebp+OutBuffer]

.text:100B76D4pusheax; lpOutBuffer

.text:100B76D5push0; nInBufferSize

.text:100B76D7push0; lpInBuffer

.text:100B76D9push74080h; dwIoControlCode

.text:100B76DEmovecx, [ebp+hObject]

.text:100B76E4pushecx; hDevice

.text:100B76E5callds:DeviceIoControl

Листинг 5 фрагмент Keeper'а, вызывающий функцию DeviceIoControl

Прокрутив дизассемблерный листинг вверх, мы узнаем, что в переменной [ebp + hObject] находится дескриптор, возвращенный функцией CreateFileA(), которой скормили строку «\\.\PhysicalDrive%d». Очень интересно! Значит, перед нами код, напрямую взаимодействующий с жестким диском. Но как именно он с ним взаимодействует? Ответ скрыт в IOCTL-коде равном 74080h. Все, что нам нужно — перевести его в удобочитаемую константу, а для этого необходимо знать как формируются IOCTL коды или… воспользоваться on-line калькулятором, доступном на http://www.osronline.com/article.cfm?article=229.

Рисунок 11 онлайновый декодер IOCTL кодов

Вводим IOCTL кодвокошко «VALUE» иполучаемполнуюрасшифровку: Device – DISK (0x7), Function – 0x20, Access – «FILE_READ_ACCESS», Method – «METHOD_BUFFERED». Ага, значит, чтение. Ну хорошо хоть не запись! Однако, запись еще впереди! Вот, например:

.text:100B7F63push0; lpOverlapped

.text:100B7F65movecx, [ebp+lpBytesReturned]

.text:100B7F68pushecx; lpBytesReturned

.text:100B7F69push210h; nOutBufferSize

.text:100B7F6Emovedx, [ebp+lpOutBuffer]

.text:100B7F71pushedx; lpOutBuffer

.text:100B7F72push20h; nInBufferSize

.text:100B7F74moveax, [ebp+lpInBuffer]

.text:100B7F77pusheax; lpInBuffer

.text:100B7F78push7C088h; dwIoControlCode

.text:100B7F7Dmovecx, [ebp+hDevice]

.text:100B7F80pushecx; hDevice

.text:100B7F81callds:DeviceIoControl

Листинг 6 еще один фрагмент Keeper'а, вызывающий функцию DeviceIoControl

Калькулятор говорит, что IOCTL код 7C088h обеспечивает как запись, так и чтение данных с диска на сектором уровне в обход файловой системы и всех, установленных ею ограничений. Возможно, что Keeper создает на жестком диске какой-то «тайник» или своеобразную метку, помогающую «людям в погонах» отождествить его. Или это просто Keeper так привязывается к оборудованию, чтобы его было нельзя запустить с чужого компьютера? Кто знает… полное исследование требует большой концентрации сил, ресурсов и времени, но вряд ли конечный результат стоит того, поскольку и без того ясно, что Keeper за зверь (а еще невинным муравьем прикидывается!)

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

Мыщъх категорически не рекомендует устанавливать эту штуку на свой компьютер. Вот если бы Keeper распространялся в открытых текстах с полностью специфицированными протоколами… Компания ничего бы не потеряла (Keeper все равно бесплатен), а только приобрела. Эксперты указали бы на ошибки, армия LINUX-пользователи не трахалась бы с Windows-эмуляторами, а спокойно переносила Keeper'а на настольные и мобильные системы, добавляя миллионы (!) новых клиентов. Почему же этого до сих пор не сделано?! Уж не потому ли, что Keeper'у есть что скрывать?!