Главная » C++ энциклопедия » C » C++. Делаем свою секцию данных в PE
Категория: C++ энциклопедия » C
  • 85

18 мая 2011

Автор: RZah

PE (Portable Executable) - формат исполняемых файлов, объектного кода и динамических библиотек, используемый в 32- и 64-битных версиях операционной системы Microsoft Windows. Формат PE представляет собой структуру данных, содержащую всю информацию, необходимую PE загрузчику для проецирования файла в память (по материалам Wikipedia). Сегодня мы поговорим о том как сделать собственную секцию данных в PE файле.

А зачем?

Во-первых, некоторые компиляторы вольны вставлять строковые данные в сегмент кода, тем самым засоряя его. Насколько мне известно, компиляторы, некогда существовавшей Borland особенно этим грешили.
Во-вторых, это хороший способ спрятать свои данные от юных крэкеров, а в совокупности с хорошим крипто алгоритмом можно отпугнуть и крэкера средней руки. Профи этим, конечно же не остановить и тут надо хорошенько “поломать голову”, но это уже другая история. И так давай проведем пару экспериментов и посмотрим, что из этого выйдет. Для опытов нам потребуется:

1. Компилятор C++ (Майкрософсткий). Я буду использовать Visual Studio 2005;
2. IDA Pro. Можно использовать dumpbin (входит в поставку Visual Studio). Если ни того ни другого у тебя нет, то можно использовать любой HEX редактор, ну или утилиту для просмотра секций PE файла. Для наглядности я буду применять IDA Pro.

С инструментами разобрались. Теперь давай напишем небольшую программу для наших экспериментов. Полный код программы:

#include "stdafx.h"
#include "windows.h"

//Объявляем константы
#define UserName "Ghost Rider";
#define Password "12345";

//Левые данные
#define Login_for_Admin "Super Admin";
#define Password_Admin "Admin Password=12345";

int _tmain(int argc, _TCHAR* argv[])
{
    char buffer_nik[50]; //буфер под ввод ника
    char buffer_pas[20]; //буфер под ввод пароля

    //Ввод ника
    printf("Vvedite nik: > ");
    fgets(&buffer_nik[0],50,stdin);

    //ввод пароля
    printf("Vvedite parol: > ");
    fgets(&buffer_pas[0],20,stdin);


    //сравнение введенных данных с константами
    if ((strcmp(&buffer_nik[0],UserName))&(strcmp(&buffer_pas[0],Password)))
        printf("OK.");
    else
        printf("Wrong Pas or Nik");
    return 0;
}


Не будем подробно рассматривать этот код (все пояснения я привел в комментариях), а сразу откомпилируем его, а затем откроем получившийся exe’шник в IDA Pro. После анализа файла, IDA любезно предоставит тебе всю необходимую информацию. Однако нас интересуют секции данных, поэтому щелкай по вкладке “String window”. Ты увидишь изображение как на рисунке 1.

C++. Делаем свою секцию данных в PE

Рисунок 1. Смотрим секции данных в Ida Pro


На рисунке 1 нам видно, что все наши данные хранятся в открытом виде в секции .rdata (следует заметить, что названия секций не всегда предваряются точкой, просто так принято).

И про dumpbin я не забыл

В командной строке набирай dumpbin (не забудь набрать полный путь к dumpbin) /RAWdata:BYTES /SECTION:.rdata example.exe (путь к нашему exe’шнику). Эта команда позволяет вывести содержимое определенной секции. Выходную информацию можно перенаправить в файл (так проще разбираться). Для этого дописываем в конце example.exe >file.txt. Если опустить параметр /RAWdata:BYTES, то dumpbin выведет информацию о секции .rdata - смещение, адрес секции (см. рисунок 2) и т.д.

C++. Делаем свою секцию данных в PE

Рисунок 2. Секция .rdata


Чтобы узнать названия всех секций надо просто набрать dumpbin example.exe (см. рисунок 3).

C++. Делаем свою секцию данных в PE

Рисунок 3. Названия секций


Чтобы узнать все используемые опции и их описания набери dumpbin /?. Ладно, с этим вроде бы разобрались, идем дальше. А дальше у нас по плану создание собственной секции и размещение в ней данных.
Создание новых секций, да и распределение данных по ним никак не оговорено в стандартах, поэтому каждый компилятор сам себе хозяин в этом плане (для получения подробной информации обратись к документации используемого компилятора). Однако общие правила все же есть:

- Секции .idata, .data, .rdata – содержат данные программы (строки, числа и все остальное, что не жалко);

- .text – сам код программы. В секции .bss обычно находятся неинициализированные переменные и все в этом духе.

Поскольку мы воспользовались компилятором C++, то все ниже описанное будет работать только в нем (однако принцип для всех и вся один и тот же, лишь реализация разная, но с одной оговоркой, если компилятор вообще поддерживает создание новых секций). Если же ты столкнулся с таким компилятором, то я знаю только два пути решения проблемы с созданием новой секции. Первый - сменить компилятор, второй - взять в руки дизассемблер + другие “низкоуровневые” инструменты и вручную начинать ковырять свежеиспеченный exe’шник. Для того чтобы создать новую секцию данных в C++ воспользуемся программой data_seg. Запишем данные во вновь созданную секцию и вернемся к старой секции.

#include "stdafx.h"
#include "windows.h"

//Объявляем данные в новой секции
#pragma data_seg(".Ghost_Rider")
char UserName[]="Ghost Rider";
char Password[]="12345";

//возвращаемся к старой секции (.rdata в нашем случае, по умолчанию вообще-то .data )
#pragma data_seg()
//Левые данные
char Login_for_Admin[]="Super Admin";
char Password_Admin[]="Admin Password=12345";

int _tmain(int argc, _TCHAR* argv[])
{
    char buffer_nik[50]; //буфер под ввод ника
    char buffer_pas[20]; //буфер под ввод пароля

    //Ввод ника
    printf("Vvedite nik: > ");
    fgets(&buffer_nik[0],50,stdin);

    //ввод пароля
    printf("Vvedite parol: > ");
    fgets(&buffer_pas[0],20,stdin);


    //сравнение введенных данных с константами
    if ((strcmp(&buffer_nik[0],UserName))&(strcmp(&buffer_pas[0],Password)))

        printf("OK.");
    else
        printf("Wrong Pas or Nik");

    return 0;
}


Выполняй компилирование и открывай полученный бинарник в IDA Pro (см. рисунок 4).

C++. Делаем свою секцию данных в PE

Рисунок 4. Новая секция (Ida Pro)


На рисунке 4 я выделил нашу новую секцию и данные в ней. Помнишь, я говорил, что в отношении секций данных компилятор сам себе хозяин. Это прямое тому подтверждение – в коде мы назвали секцию Ghost_Rider, а в дизассемблированном виде получаем Ghost_R (компилятор обрезает длинные имена секций). Давай посмотрим через dumpbin все наши секции (см. рисунок 5).

C++. Делаем свою секцию данных в PE

Рисунок 5. Секция .Ghost_R


Новая секция готова

Теперь остается реализовать (пусть даже простой) алгоритм шифрования к данным и они будут скрыты от посторонних глаз. В неизвестную секцию мало кто полезет (а вдруг она используется программой в целях поддержания работоспособности или еще чего). Кроме того шифрование неплохая защита от новичков-крякеров, а может и больше, кто знает. На этом все, до встречи.

Исходник прилагается:

Source.zip
Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.
18 мая 2011 15:17
Avatar
  • admin

  • Группа: Администраторы
  • Публикаций: 773
  • Комментариев: 30
Очень интересно =)
Регистрация: 7.03.2011
Информация
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.