Unauthorized.

Грабим данные с flash-модулей и CD/DVD

2011.10.08

Грабим данные с flash-модулей и CD/DVD

Автор: (c)Крис Касперски ака мыщъх

Как сграбить содержимое флешек и CD/DVD-носителей (включая удаленные файлы!), не нарушив ни один пункт закона и оставшись при этом непойманным, неразоблаченным и непобитым? Мыщъх, покурив хорошей травы, разработал специальную технологию, описание которой и предлагает всем желающим (а также нежелающим, но просто интересующимся).

Скажите, а в Пизе ничего не пропадало?
народное

Введение

Ходят тут всякие! Спать, понимаешь, мешают. Зашел ко мне давеча в нору один такой тип. Флеш припер. Сует ее в разъем. Скопировать последний альбом Independent у меня хочет. А там у него на флешке сорцы интересные, конфиденциальная документация и фотки пикантные интимного характера с его пассией в главной роли. Знакомая ситуация не так ли? И вот этот кадр думает, что если ни на секунду не выпускать свою кровную малышку из рук, то у него никто ничего не сопрет. Наивный! Мыщъх озаботился этой проблемой еще со времен MS-DOS, когда программистам приходилось таскать за собой потрепанную папочку с дискетами пятидюймового форм-фактора, что придавало им сходство с инженерами (которыми они, по сути, и являлись, ибо "пользователей" тогда еще не существовало).

С тех пор многое что изменилось. Народ перешел на ZIP'ы, CD/DVD, флешки и прочие носители, вмещающие гигабайты полезных данных, которыми некоторые скряги упорно не хотят делиться, забыв главный девиз хакера, что код и данные - общенародное достяние. Ну, не хотят делиться и хрен с ними! Мы и сами возьмем! По этому поводу мыщъх говорит так - что на мой компьютер попало, то пропало. Хочешь сохранить свои данные в тайне - так не суй флеш куда попало!

Недетский грабеж съемных носителей

Рисунок 1. Недетский грабеж съемных носителей.

Обзор существующих утилит или как палятся хакеры

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

К сожалению, практически все они неработоспособны. Причем речь идет не о мелких ошибках реализации, а о глобальных конструктивных просчетах. Начнем с того, что многие граберы ныкают свои процессы от "диспетчера задач" и других утилит подобного типа, перехватывая ряд системных функций и не вполне корректно их обрабатывая, что приводит к многочисленным конфликтам и сбоям операционной системы. Зачем прятать процессы на своей собственной машине - мне в упор непонятно. Если грабер устанавливается сознательно (а это как раз и есть та ситуация, о которой мы говорим) - пусть он хоть как заныкается, я все равно знаю, что он есть. Посторонним же пользователям список процессов на моем компьютере ровным счетом ни о чем не говорит, да и не позволю я им ковыряться в недрах моей машины!

Но это все ладно! Прячут процессы - ну и хрен с ними! В конце концов, это никому не мешает (то есть, еще как мешает - антивирусы ругаются так, что уши вянут и приходится отключать кучу проактивных технологий и эвристических анализаторов, рискуя подцепить заразу).

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

Достаточно многие флешки оснащены индикатором

Рисунок 2. Достаточно многие флешки оснащены индикатором, препятствующему незаметному сливу данных.

Граберы классом повыше отслеживают момент первого обращения к съемному носителю и стягивают данные только во время "легальных" операций чтения/записи. Очевидным минусом этой технологии становится резко возросшая сложность реализации, требующая перехвата системных функций, который в Висте и 64-битных версиях XP не то, чтобы совсем невозможен, но существенно затруднен. Опять-таки - антивирусы, глюки и прочие никому не нужные прелести. До сих пор мне не встречался ни один добротный перехватчик, корректно работающий на многоЦПшных машинах (включая HT и многоядерные процессоры, которых с каждым днем становится все больше и больше).

Недостаток номер два (самый главный) - емкость флешки (CD/DVD-дисков), как правило, намного больше размера легально копируемых файлов и утянуть их содержимое просто так не получится. Времени уйдет целая куча. Даже если флешка не оснащена индикатором, будет мигать индикатор жесткого диска (а куда еще складывать такое количество награбленных данных?! Не в память же! Хм... Ну, вообще-то можно и в память, только памяти должно быть много). Но сложности на этом не заканчиваются. При попытке отключения USB-устройства штатными средствами Windows, та просто откажется демонтировать флешку, пока с ней работает хотя бы одна программа. Следовательно, грабер должен отслеживать отключение USB-устройств, прекращая грабеж в аварийном порядке. Короче, весьма нехилый проект у нас получается. Реализовать его очень сложно. Отладить - еще сложнее, а утащить информацию, не вызывая подозрений у ее владельца, вообще невозможно.

По этому поводу говорят, что если нельзя, но очень сильно хочется, то все-таки можно! И сейчас мыщъх поделится рецептом программы, которую можно состряпать за пару вечеров и которая работает на любой, абсолютно любой, операционной системе - 9x, NT, W2K, XP, Висте и... даже Linux/BSD, поддерживает все типы сменных носителей, не вызывает конфликтов и, самое главное - распознать факт грабежа не сможет даже продвинутый пользователь, а грабить мы будем его подчистую - от первого до последнего байта, включая данные, принадлежащие удаленным файлам.

Грабеж по мыщъх'иному

Рисунок 3. Грабеж по мыщъх'иному - то есть внаглую.

Основные идеи и концепции

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

Между прочим, это была не шутка. Труднее всего обнаружить то, что находится у нас под глазами. Берем флеш (или CD/DVD), вставляем. Тут же всплывает "антивирус", имитирующий проверку файлов, а в действительности сливающий их на жесткий диск в какую-нибудь глубоко вложенную папку, такую, которая гарантированно не попадется жертве на глаза. Необходимость отслеживать обращения к съемным устройствам тут же отпадает. Мы и без всякой маскировки так замаскировались, что у жертвы и тени подозрений не возникает!

Поскольку обычные антивирусы так себя не ведут, то от копирования их интерфейса лучше воздержаться, иначе можно быстро погореть. Пусть это будет что-то совершенно никому неизвестное. Например, суперкрутой антивирус под названием "Selena Enterprise Edition". Чисто теоретически жертва может попросить нас прервать проверку флешки (CD/DVD), но тут ее легко обломать встречным вопросом: "с какого это такого перепугу мы должны чего-то прерывать?! уж не вируса, ты, милый человек, занести нам хочешь?!"

Разработка грабера

Рисунок 4. Разработка грабера, замаскированного под антивирус, в Microsoft Visual Studio 6.0.

Кстати говоря, с юридической точки зрения мы не совершаем никакого преступления, так как вправе копировать содержимое сменного носителя, добровольно вставленного в наш компьютер его правообладателем. Зачем копировать?! Ну... например, в целях кэширования, скажем. Другой вопрос, что распространять полученную таким путем информацию без согласия правообладателя как бы нельзя. "Как бы" потому, что факт несанкционированного распространения еще необходимо доказать. Если речь не идет о документах, представляющих коммерческую или государственную тайну, с убытками в особо крупных размерах, никакой суд заниматься подобными мелочами просто не будет. Такие дела недоказуемы в принципе! Вот упрется хакер рогом и будет гнуть линию, что согласие (устное) на дистрибуцию он получил. Кто не согласен - пускай докажет, что его (согласия) не было с учетом презумпции невиновности, которую еще никто не отменял.

Впрочем, мы ушли в перпендикуляр. Возвращаясь к смысловую плоскость обсуждаемой темы, обратим внимание на замечательное обстоятельство, что сами по себе граберы не могут быть законными или незаконными. Даже если они умышленно имитируют работу антивируса - ну и что с того?! Кого они этим вводят в заблуждение? Пользователя грабера?! Так ведь, нифига подобного (ибо в прилагаемой к ним документации все сказано). Владельца флешки или CD/DVD?! Ну... так это он сам себя обманул. Мало ли, что ему там почудилось на экране. Selena - это вполне нормальный антивирус, точнее часть антивирусного комплекса, копирующего данные с внешних носителей в специальную папку, чтобы при обнаружении заразы было можно установить ее источник.

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

Хакеру нужны не только мозги

Рисунок 5. Хакеру нужны не только мозги, но и длинные ноги, чтобы успеть смотаться пока его не защемили.

Технические детали реализации

В состав Win32 API входит любопытная функция FindFirstChangeNotification, генерирующая уведомления при изменении содержимого заданной директории. Достаточно передать ей букву оптического привода, и можно отслеживать вставку новых CD/DVD дисков. Если у нас имеется более одного привода, функция FindFirstChangeNotification должна вызываться "персонально" для каждого из них.

// передаем функции имя буквы привода оптических дисков
// (в данном случае, это диск "G:\\")

HANDLE cnh = FindFirstChangeNotification("G:\\", FALSE,
                        FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME);

// отслеживаем изменения в бесконечном цикле
// тут необходимо добавить код для выхода из цикла по или другой hotkey

while (1)
{
        // ждем изменений в файловой системе заданного диска
        // или более конкретно - вставки [нового] диска в привод

        DWORD wr = WaitForSingleObject(cnh, INFINITE);

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

}

// после выхода из цикла сообщаем системе,
// что мы больше не хотим получать никаких уведомлений

FindCloseChangeNotification(cnh);

Листинг 1. Пример использования функции FindFirstChangeNotification для отслеживания вставки новых оптических дисков в привод.

Получать уведомления о вставке флешек, автоматически монтирующих себя на новые диски, несколько сложнее и мыщъх'у так и не удалось найти элегантный и документированный способ, поддерживаемый всеми системами семейства Windows, да он к этому, по правде сказать, не особенно стремился, ограничившись периодическим (раз в несколько секунд) вызовом API-функции QueryDosDevice, возвращающий список имеющихся дисков (или GetLogicalDrives, которая работает быстрее и реализована на всех платформах, а не только на линейке NT, но вместо букв возвращает битовую маску, с которой еще предстоит разобраться).

Сделать это можно, например, так:

// получаем битовую маску с перечнем дисков,
// смонтированных на соответствующую им букву

DWORD dwLogicalDrives = GetLogicalDrives();

// разбираем все биты один за другим
for (nDrive = 0; nDrive < 32; nDrive++)
{
        // такой диск существует?
        if (dwLogicalDrives & (1 << nDrive))
        {
                 // определяем характеристики диска
                uType = GetDriveType(szBuffer);
                if ((uType == DRIVE_REMOVABLE) || (uType == DRIVE_CDROM))
                {
                        // это наш клиент!!!
                        // грабим его по полной программе
                }
        }
}

Листинг 2. Пример использования функции GetLogicalDrives.

Падение производительности настолько несущественно, что о нем не стоит и говорить. В принципе, в W2K (и более поздних версиях) существует возможность насильственного монтирования флешки не на диск, а в поддиректорию, которую уже можно "скормить" функции FindFirstChangeNotification, но это уже никому не нужное извращение.

Грабить файлы лучше всего не блочно (функциями ReadFile/WriteFile), а через CopyFileEx - это проще и более производительно. В остальном грабеж реализуется вполне стандартно и не должен вызывать сложностей даже у начинающих программистов, терзающих Visual Basic или DELPHI.

Грабим удаленные файлы

Флешки, используемые для обмена данными между компьютерами, несут на своем борту много интересного. Конечно, с течением времени шансы на восстановление удаленного файла стремительно уменьшаются и в какой-то момент он оказывается полностью перезаписан свежими данными, однако если флешка была заполнена до отказа, а затем отформатирована, то вновь записываемые файлы затрут старые очень нескоро (особенно, если объем флешки измеряется гигабайтами). В общем, покопавшись в мусорной куче гниющих останков, мы с ненулевой вероятностью найдем что-то очень интересное - такое, чего другим путем раздобыть просто нельзя. Ну, так чего же мы ждем, почему стоим?! То есть, сидим. А нужно открывать документацию и кодить, кодить, кодить...

Естественно, стратегию грабежа придется радикально изменить, развернув концепцию на 360 градусов. Передаем API-функции CreateFile имя диска в виде "\\\\.\\R:" (где "R" - буква, ассоциированная с флешкой) и читаем содержимое устройства функцией ReadFile блоками, кратными размеру сектора, например, по 2048 байт (внимание: процесс-грабер должен в обязательном порядке обладать правами администратора, которые ему можно делегировать, например, через штатную утилиту runas, иначе ничего не получится).

Минимально работающий листинг, реализующий эту затею, выглядит так:

main(int argc, char **argv)
{
        int a; FILE *f; HANDLE h; char *buf; DWORD x_read; char buf_n[1024];
        buf = malloc(2048); // выделяем память

        // открываем устройство
        // (в данном случае - диск G:)

        h = CreateFile("\\\\.\\G:", GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);

        // позиционируем указатель на первый читаемый блок
        SetFilePointer(h, 0, NULL, FILE_BEGIN);

        // читаем блоки c нулевого по 666
        for (a = 0; a <= 666; a++)
        {
                // читаем очередной блок
                if (ReadFile(h, buf, 2048, &x_read, NULL) && x_read)
                {
                        // записываем только что считанный блок в файл C:\grab.dat
                        sprintf(buf_n, "%s[%04d].dat", "C:\\grab.dat", a);
                        if (f = fopen(buf_n, "wb"))
                                { fwrite(buf, 1, x_read, f); fclose(f); }
        }
}

Листинг 3. Фрагмент программы, читающей образы флешек и CD/DVD дисков (полный исходный текст можно найти в книге "Техника защиты CD от копирования).

Полученный образ флешки можно впоследствии "залить" на свою собственную флешку, заменив функцию ReadFile на WriteFile, после чего натравить на нее любую из многочисленных утилит предназначенных для восстановления удаленных файлов или (если флешки такого объема у нас нет) запустить Linux/BSD, смонтировать образ как "настоящий" диск и восстановить файлы вручную с помощью hex-редактора.

Техника восстановления подробно описана в моей книге "Data Recovery - tips and solutions", русская редакция которой лежит на http://nezumi.org.ru/, а недавно по просьбе читателей выложен архив прилагаемого к ней лазерного диска со всеми исходными текстами простейший программ для восстановления.

Утянуть удаленное содержимое с CD/DVD-R/RW носителей на порядок сложнее и чтобы добраться до "захороненных" данных, необходимо спуститься на один уровень вглубь, получив прямой доступ к приводу через интерфейс ASPI или SPTI. Оба подробно описаны в "Технике защиты компакт-дисков от копирования", там же рассказывается как самостоятельно восстановить данные после быстрой очистки. Полная очистка, увы, гробит содержимое CD/DVD-RW безвозвратно, однако она используется лишь некоторыми пользователями.

Удаленные файлы тоже можно грабить

Рисунок 6. Удаленные файлы тоже можно грабить!

Как не ограбить самого себя

Чтобы не вызывать у жертвы никаких подозрений, грабер следует держать на своем компьютере постоянно запущенным (например, закинутым в автозагрузку или в один из многочисленных ключей автозапуска, находящийся в системном реестре). Любые дополнительные действия, выполняемые нами перед вставкой чужой флешки или лазерного диска выглядят довольно странными и не вполне адекватными (ну вообще-то, можно, конечно прикинуться параноиком, типа вот меня давеча поимели, так что сейчас любой носитель в обязательном порядке проходит жесткий бактериологический контроль "антивирусом", но если жертва думает головой, она быстро раскусит что это за контроль такой и начнет щемить хакера по полной программе, особенно после обнаружения интимных фотографий своей пассии на диких просторах Интернета).

Короче, лучше держать "антивирус" постоянно активным. Только это же ведь напряг сплошной!!! Не успел еще вставить новый диск (свой диск, а не чужой!!!) и уже во всю пошел грабеж, отнимающий время и убивающий нервные клетки. Значит, будем хитрить (тем более, что нам это не впервой).

"Антивирус" должен позволять быстро отменять проверку текущего диска нажатием , или любой другой привычной комбинации, запоминая его серийный номер в скрытом конфигурационном файле, и никогда больше его не проверять. Другими словами, необходимо добавить в грабер поддержку "белого" списка своих дисков, опознаваемых по серийному номеру или метке тома. Однако, метка - довольно ненадежное средство. Например, Nero по умолчанию метит все прожигаемые им диски ключевым словом "NEW", а при форматировании флешек и ZIP'ов метка обычно вообще не назначается.

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

За чтение серийного номера отвечает API-функция GetFileInformationByHandle, возвращающая его в следующей структуре:

typedef struct _BY_HANDLE_FILE_INFORMATION {
        DWORD dwFileAttributes;
        FILETIME ftCreationTime;
        FILETIME ftLastAccessTime;
        FILETIME ftLastWriteTime;
        DWORD dwVolumeSerialNumber;
        DWORD nFileSizeHigh;
        DWORD nFileSizeLow;
        DWORD nNumberOfLinks;
        DWORD nFileIndexHigh;
        DWORD nFileIndexLow;
} BY_HANDLE_FILE_INFORMATION;

Листинг 4. Серийный номер диска (выделен полужирным), возвращаемый функцией GetFileInformationByHandle.

Также следует предусмотреть комбинацию горячих клавиш, блокирующую запуск грабера при вставке носителя (типа Shift'a, отключающего автозапуск). Впрочем, это уже детали, допускающие бесчисленные вариации. Лично мыщъх поступил так - если в момент вставки нового диска на переднем плане находится FAR, то грабер не запускается. Если же FAR отсутствует или вращается в бэкграунде, а работа со сменными носителями осуществляется через "Проводника" - это расценивается как сигнал к атаке. Внешне выглядит вполне невинно и никаких подозрений не вызывает.

Замечания по реализации грабера под Linux/BSD

Linux/BSD встречаются на десктопных системах не то, чтобы часто, но ведь и экзотикой их уже не назовешь. Они также поддерживают флешки вместе с лазерными дисками и другими съемными носителями, только вот готовых утилит грабежа под них что-то не наблюдается. Ну, совсем никаких - даже самых примитивных и захудалых.

Механизм уведомлений об изменениях в файловой системе в UNIX-клонах реализован сильно по-разному и написать переносимый грабер просто так не получится. Впрочем, ловить уведомления совершенно необязательно. Достаточно написать свою обертку вокруг штатной утилиты mount (по типу вируса-спутника), которая при попытке монтирования съемных носителей, передает управление настоящему mount'у и тут же запускает грабер, замаскированный под антивирус. Как говориться, дешево и сердито. Зато системно-независимо и надежно (кстати, описанный прием распространяется в том числе и на auto-mount).

Грабеж образов с носителей осуществляется путем открытия соответствующих устройств (перечисленных в каталоге /dev) системным вызовом open с последующим чтением их содержимого системным вызовом read.

В общем, написать приличный UNIX-грабер (даже не будучи гуру) совсем несложно.

Заключение

Грабеж - не такое уж сложное дело, если к реализации грабера подойти с головой. Не нужно использовать готовые шпионские утилиты - все они барахло! Лучше всегда написать свое, заточенное строго под самого себя (любимого), чем брать чужой глюкодром.

https://nebka.ru/?uid=1&post=20956