Техническая поддержка :

Современные решения

для защиты Windows программ

и восстановления исходного кода
Автор: Чубченко Сергей. Дата публикации: 11.06.2004


Скрамблер UPX своими руками


Введение

Написать эту статью меня побудило то, что совсем недавно я написал программу PeStubOEP, одной из функций которой был скрамблер сигнатур различных упаковщиков. Чтобы не ждать лишних вопросов сразу оговорюсь: мы будем писать только скрамблер UPX, описание остальных же функций PeStubOEP намеренно не войдет в эту статью. "Что же такое скрамблер?", - спросите Вы. Это небольшая программа для затирки сигнатуры упаковщика, в которой он хранит служебную информацию для распаковки. Если кто-то забыл, то напомню, что если запустить UPX с ключом -d, то он распакует упакованный файл, но только в случае не поврежденной сигнатуры. Также мы научимся изменять имена секций, так как не очень то весело видеть следующий расклад:

.UPX0сюда UPX кладет информацию из .tls
.UPX1здесь располагается весь упакованный код и данные программы
.rsrcресурсы (не рекомендую переименовывать эту секцию для совместимости со старыми версиями операционки)


Некоторые начальные сведения о PE формате

Рассматривать PE формат подробно и расписывать все структуры я думаю не имеет смысла, так как нам понадобится только информация о расположении PE заголовка и адрес начала секций.
Так вот, несмотря на то, что многие любительские упаковщики любят удалять dos заголовок, по смещению &H3C всегда находится адрес на начало PE заголовка (его там нет, только если программа была написана под DOS). Теперь, когда мы нашли адрес начала PE заголовка, найдем адрес начала описания секций. Как не странно, описание секций всегда начинается со смещения (PeOffset + &HF9), где PeOffset - адрес начала PE заголовка.
Осталось только определить число секций, а оно хранится по смещению (PeOffset + 6) в основном PE заголовке
Теперь, когда мы все нашли, не мешало бы разобраться со структурой описания секций. Ниже я приведу ее вариант для Visual Basic 6.0:

CODE NOW!
Public Type pe_section_header
    section_name As String * 8 ' Имя секции [8 байт]
    section_size As Long       ' Размер секции в памяти
    section_rva As Long        ' Адрес загрузки секции в памяти
    section_size2 As Long      ' Размер секции в файле
    section_start As Long      ' Смещение начала секции в файле
    reserved As String * 12
    section_flags As Long      ' Флаги секции
End Type


Структуры, подобные приведенной выше идут одна за другой, а их количество равно числу секций в файле.

Некоторые начальные сведения о формате UPX сигнатуры

Начну с того, что нижеприведенная структура идентична для UPX 1.24 и 1.90, а также вряд ли поменяется в следующих версиях упаковщика, посему я думаю, что можно смело пользоваться данной структурой.
Так вот, сама структура содержит в себе поля, необходимые для нормальной распаковки файлов UPX'ом и всегда начинается с "UPX!". Этим мы и будем пользоваться для нахождения адреса начала сигнатуры. Ах да, вот сама структура:

CODE NOW!
Public Type UPX_STRUCT
    upxMagic As String * 4     ' Символы "UPX!"
    upxVersion As Byte         ' Версия UPX'а (например: 0C значит 1.24, 0D - 1.90)
    upxFormat As Byte          ' Определяет формат файла (PE, ELF, DOS и т.д.) PE - 09
    upxMethod As Byte          ' Метод сжатия (если NRV или UCL, то 02)
    upxLevel As Byte           ' Степень сжатия (от 0 до 10)
    upxU_adler As Long         ' CRC части экзешника в распакованном виде
    upxC_adler As Long         ' CRC части экзешника в запакованном виде
    upxU_len As Long           ' Размер части экзешника в распакованном виде
    upxC_len As Long           ' Размер части экзешника в запакованном виде
    upxU_file_size As Long     ' Размер распакованного экзешника.
    upxFilter As Integer       ' Метод распаковки
    upxCRC As Byte             ' CRC сигнатуры
End Type


Пишем скрамблер

Как ни странно полученных нами знаний из первых двух пунктов вполне достаточно, чтобы переименовать все секции в файле например на ".code" и стереть все данные из UPX сигнатуры.
Для начала запустим Visual Basic 6.0, создадим новый проект, удалим из него форму и добавим модуль. Наша программа будет работать с командной строкой. Ниже я приведу простейшую реализацию этой задачи. Для того чтобы не повторятся, я убрал объявления вышеописанных структур:

CODE NOW!
'глобальный массив секций
Public sSections() As pe_section_header

Private Sub Main()
'считываем данные из командной строки
sFileName = Command$
'если программа была запущена без параметров - выводим сообщение
'об ошибке и выходим
If sFileName = "" Then MsgBox "Вы не передали имя файла в командной строке", _
vbCritical, "Ошибка": Exit Sub
'удаляем лишние кавычки
If Left$(sFileName, 1) = Chr(34) Then sFileName = Mid$(sFileName, 2, _
Len(sFileName) - 2)
'объявляем переменные
Dim sPeOffset As Long, sFindUPX As String * 5000, sUPX As UPX_STRUCT, _
sNumberSections As Integer
'создадим резервную копию
FileCopy sFileName, Left$(sFileName, Len(sFileName) - 3) & "bak"
'откроем файл
sFile = FreeFile
Open sFileName For Binary As #sFile
'считаем адрес PE заголовка
Get #sFile, &H3C + 1, sPeOffset
'определим число секций
Get #sFile, sPeOffset + 7, sNumberSections
'найдем адрес начала описания секций
sSectionsStart = sPeOffset + &HF9
'ищем сигнатуру UPX в первых 5000 байт программы
Get #sFile, 1, sFindUPX
sFind = InStr(1, sFindUPX, "UPX!")
'если нашли - грузим
If sFind > 0 Then
  Get #sFile, sFind, sUPX
  'заполняем все поля ерундой
  sUPX.upxMagic = "    ": sUPX.upxVersion = 0
  sUPX.upxC_adler = 0: sUPX.upxC_len = 0
  sUPX.upxCRC = &HFF: sUPX.upxFilter = 0
  sUPX.upxFormat = 0: sUPX.upxMethod = 0
  sUPX.upxU_adler = 0: sUPX.upxU_file_size = 0
  sUPX.upxU_len = 0: sUPX.upxVersion = 11
  'сохраняем изменения
  Put #sFile, sFind, sUPX
'если не нашли - выводим сообщение об ошибке и выходим
Else
  MsgBox "Ошибка: файл '" & sFileName & "' не содержит сигнатуру UPX", _
  vbCritical, "Скрамблер UPX": Close #sFile: Exit Sub
End If
'создаем массив секций
ReDim sSections(sNumberSections - 1)
Get #sFile, sSectionsStart, sSections
'установим новое имя секций
For i = 0 To sNumberSections - 1
  sSections(i).section_name = ".sux"
Next
'сохраним измененные данные
Put #sFile, sSectionsStart, sSections
'закроем файл
Close #sFile
'сообщим, что операция прошла успешно
MsgBox "Файл '" & sFileName & "' успешно обработан", vbInformation, "Скрамблер UPX"
End Sub


PS: Не удивляйтесь что к каждому смещению при считывании прибавляется единица - это особенности Visual Basic'а (все адреса в файле считаются не с 0 как принято в C++ а с 1).

Заключение

Теперь Вы знаете как можно написать свой UPX скрамблер и у Вас больше не возникает вопросов по этой теме. Если же они все таки возникли, рекомендую изучить побольше информации про формат EXE файлов. И почаще читайте форумы по программированию. Если у Вас есть желание, то вскоре к Вам придет навык написания программ для работы с PE форматом. Желаю Вам удачи в программировании!

Исходники из статьи


Комментарии

отсутствуют

Добавление комментария


Ваше имя (на форуме):

Ваш пароль (на форуме):

Комментарии могут добавлять только пользователи,
зарегистрированные на форуме данного сайта. Если Вы не
зарегистрированы, то сначала зарегистрируйтесь тут

Комментарий:





Главная     Программы     Статьи     Разное     Форум     Контакты