Как написать криптор на c

Как написать криптор на c

Содержание статьи

Web мы спасли от антивирусов несколько месяцев назад. Это было нетрудно — область относительно новая, не освоенная. С исполнимыми же файлами антивирусы борются уже десятилетиями. Побороть EXE-модуль будет сложнее, но… мы справимся :).

Выпуск 1. Ознакомительный

Ты уже знаешь, что я считаю антивирусы абсолютно бесполезными — хотя бы по той причине, что они помогают только от самых примитивных зверьков, которые в условиях современного денежного малварьбизнеса встречаются не так часто. Современные злокодеры, подогретые денежными вливаниями, научились программировать довольно жестко, но есть у них одна маленькая проблема — криптовка — достаточно сложная штука, для написания которой нужны глубокие знания PE-формата, ассемблера и системного программирования. Из-за высокого «входного барьера» в этой области мало профессионалов.

И найти хорошего криптора ой как сложно.

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

Идеальным местом для обмена, наверное, будет GitHub, и туда я залью исходники написанного нами сегодня криптора — он будет доступен по адресу http://github.com/presidentua/ExePacker.

Кроме того, в решении проблемы здорово помогло бы использование высокоуровневых языков программирования. В паблике сейчас валяются исходники крипторов на С++ или VisualBasic’е, но ведь от этого проще не становится, поскольку разобраться в написанном коде — ой как непросто. На Python’е все выглядит в разы лучше, поэтому именно его мы сегодня и будем использовать. В общем, заложим фундамент этой благородной миссии. Присоединяйся!

Выпуск 2. PE-файл

Структура PE-файла довольно сложная, поэтому подробная документация будет ждать тебя на диске, а здесь я представлю твоему вниманию лишь избранные моменты.

PE-файл представляет набор разных служебных структур, связанных между собой, и набор данных, которые размещены в секторах. Загрузчик Windows’a читает структуры, обрабатывает их (например, импортирует DLL’ки) и потом передает управление на инструкцию, указанную в поле «Entry Point».

Теперь посмотрим, что же нужно нам сделать, чтобы изменить файл и при этом не испортить его.

Читайте также:  Сравнение графических процессоров смартфонов

Выпуск 3. Теоретический криптор

Для начала выберем файл, который будет у нас исполнять функции лабораторной мыши. Чтобы сделать приятное Андрюшку :), мы, пожалуй, будем издеваться над Putty.exe. Упрощенно его структура будет выглядеть так:

  1. Служебные данные
  2. Первая кодовая секция
  3. Другие секции с данными

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

В результате получится следующая структура:

  1. Служебные данные
  2. Первая кодовая секция
  1. Наша первая программа, которая передаст управление на 4.2
  2. Шифрованный код первой секции
  • Другие секции с данными
  • Добавленная секция
    1. Часть кодовой секции, перезаписанной программой 2.1
    2. Вторая программа, которая оригинальный код из 4.1 поместит на 2.1, а потом расшифрует кодовую секцию и передаст на нее управление.
    3. Выпуск 4. Практический криптор

      Ну наконец-то мы добрались до сердца нашей статьи. Для работы криптора нам понадобится модуль pefile (будем использовать несколько модифицированную версию), и с помощью либы откроем Putty:

      import pefile
      pe = pefile.PE("putty.exe")

      Теперь, если ты напишешь «print pe», то увидишь подробную инфу обо всех характеристиках файла, по этой инфе я советую искать нужные для изменения поля в файле. А о внутренней работе модуля обязательно прочитай во врезке. Теперь немного математики. У нас будут две программы, которые нужно внедрить в файл. Они будут занимать где-то по 512 байт каждая максимум. Поэтому для размещения добавим новую секцию в 1024 килобайт вызовом:

      Закриптуем первую секцию XOR’ом с ключом «1»:

      Магия, правда? :). А теперь прикинь, что все это пришлось бы писать на С++!

      Поскольку в начале программы будет наш код, то сохраним оригинальный код, скопировав его в последнюю секцию. Адрес первой секции в файле находится в переменной — pe.sections[0]. PointerToRawData, а последней, соответственно — в pe.sections[-1].PointerToRawData:

      pe.data_copy(pe.sections[0].PointerToRawData, pe.sections[-1].PointerToRawData, 512)

      Оригинальный код сохранен, и мы приступим к написанию первой программы. Конечно же, писать мы ее будем на ассемблере, используя FASM для компиляции. Создадим файлик pack.tpl.asm с содержанием:

      use32
      mov eax, << go >>
      jmp eax

      Ты, наверное, уже догадался, что это не готовый исходник, это лишь шаблон для шаблонизатора из TornadoWeb, а его мы уже отлично знаем, ведь именно его мы использовали при написании HTML-морфера. Сгенерируем первую программу:

      Читайте также:  Троллинг людей в вк

      asm = Template(open("pack.tpl.asm", "r").read()).generate(
      go=pe.OPTIONAL_HEADER.ImageBase + pe.sections[-1].VirtualAddress+512,
      )
      with open("pack.asm", "w") as f:
      f.write(asm)
      os.system(r"c:fasmwFASM.EXE pack.asm")

      В переменной go мы передаем адрес в памяти, где будет наша вторая программа — то есть, в последней секции, начиная с 512 байта. А в последней строчке компилим результат на FASM’е. Теперь запишем получившийся код в начало первой секции:

      new_pack = open("pack.bin", "rb").read()
      pe.data_replace(offset=pe.sections[0].PointerToRawData, new_data=new_pack)

      Вторую программу запишем в файл copy.tpl.asm. Размер у нее более внушительный, поэтому полный код смотри на диске. Там содержится два цикла, один скопирует 512 байт оригинальной программы с последней секции в первую, а второй цикл расшифрует всю первую секцию. После этого передается управление на оригинальную программу.

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

      copy_from = pe.OPTIONAL_HEADER.ImageBase+pe.sections[-1].VirtualAddress
      copy_to = pe.OPTIONAL_HEADER.ImageBase+pe.sections[0].VirtualAddress
      oep = pe.OPTIONAL_HEADER.ImageBase+pe.OPTIONAL_HEADER.AddressOfEntryPoint
      asm = Template(open("copy.tpl.asm", "r").read()).generate( copy_from=copy_from, copy_to=copy_to, copy_len=512, xor_len=pe.sections[0].Misc_VirtualSize, key_encode=1, original_oep=oep,)

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

      new_copy = open("copy.bin", "rb").read()
      pe.data_replace(offset=pe.sections[-1].PointerToRawData+512, new_data=new_copy)
      pe.sections[0].Characteristics |= pefi le.SECTION_CHARACTERISTICS["IMAGE_SCN_MEM_WRITE"]
      pe.OPTIONAL_HEADER.AddressOfEntryPoint = pe.sections[0].VirtualAddress
      pe.write(fi lename="result.exe")

      Выпуск 5. Завершающий

      Если собрать кусочки кода вместе, то будет у нас всего 50 строк. Всего лишь 50 — и криптор готов! А теперь прикинь, сколько строк содержала бы программа на С? Конечно, это еще далеко не готовый продукт, над ним нужно работать и работать. Чтобы довести систему до реального криптора, нужно добавить как минимум шифрование ресурсов и импорта, а также антиэмуляцию. О том как теоретически эти проблемы решить, смотри во врезках. Удачи!

      Желательный функционал 1. Обход песочниц

      В крипторе нужно делать проверки на запуск в виртуальной машине, SandBox’е или анализаторе типа анубиса. Чтобы их зедетектить, нужно провести небольшое исследование и написать программу, которая будет на экран выводить разные внутренние параметры системы, а дальше — проверить этот файл на том же анубисе и в скриншоте посмотреть параметры, которые показала наша прога. Дальше все просто — при запуске на системе с подобными параметрами — просто уходим в цикл.

      Обязательный функционал 2. Шифрование ресурсов и импорта

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

      Читайте также:  Жена ходит в клуб

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

      Обязательный функционал 1. АнтиЭмуляция

      Кроме избавления от внешних сигнатур, очень важно, чтобы антивирус в своем эмуляторе не добрался до исходного файла. Для этого нужна антиэмуляция. Раньше были очень популярны приемы, основанные на предположении, что эмулятор не понимает все инструкции процессора. Сейчас же ситуация изменилась, и самые эффективные приемы основаны на использовании Windows API. Согласись, что антивирус вряд ли сможет эмулировать все API.

      Вот тебе такая идейка для реализации:

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

      PS:Никогда не останавливай программу с ошибкой, это лишь прибавит криптору лишний вес. Вечный цикл получения сообщений от Windows — лучший способ.

      Внутренности Антивирусов

      В упрощенном виде, антивирус — это набор правил (сигнатур) и система, которая проверяет файл по этим правилам.

      К примеру, пусть в антивирусе будут такие сигнатуры:

      • секция с кодом, записываемая +10;
      • после запуска прописывается в авторан +30;
      • вторая секция с именем Zeus +30;
      • меньше 4 энтропия кодовой секции +20;
      • есть сертификат от майкрософта -10.

      Дальше антивирь проверяет те правила, которые возможно проверить без запуска EXE, потом в эмуляторе запускает файл и проверяет все остальные правила. А после этого подсчитывает сумму, если она больше 100, значит вирус, если меньше — значит не вирус.

      Как работает pefile

      При загрузке в pefile экзэхи, библиотека сохраняет сам файл в pe.data, а потом обрабатывает его и создает массив структур pe.structures. Структура — это объект, у которого есть адрес. Адрес, по которому она находится в файле, и есть набор полей.

      Ссылка на основную публикацию
      Как изменить учетную запись в аутлуке
      После установки учетной записи в программе Microsoft Outlook, иногда требуется дополнительная настройка отдельных параметров. Также, бывают случаи, когда поставщик почтовых...
      Драйвер для веб камеры на ноутбук acer
      by Acer Inc. After you upgrade your computer to Windows 10, if your Acer Camera Drivers are not working, you...
      Драйвер для микро сд карты
      SD(miniSD,microSD) флеш-карточки формата SDHC (Secure Digital High Capacity), допускают объем от 2 до 32 гигабайт. Эти карточки имеют такой же...
      Как изменить ттл на компьютере
      TTL (Time To Live) — это значение времени, на протяжении которого пакет с данными блуждает по сети со способностью передачи...
      Adblock detector