Реверс-инженеру на заметку: динамическое распределение памяти | OTUS

Курсы

Программирование
iOS Developer. Basic
-23%
Python Developer. Professional
-13%
Разработчик на Spring Framework
-23%
Golang Developer. Professional
-17%
Python Developer. Basic
-16%
iOS Developer. Professional
-13%
Node.js Developer
-15%
Unity Game Developer. Professional
-11%
React.js Developer
-12%
Android Developer. Professional
-7%
Software Architect
-12%
C++ Developer. Professional
-8%
Разработчик C#
-8%
Backend-разработчик на PHP Архитектура и шаблоны проектирования
-12%
Программист С Базы данных Framework Laravel PostgreSQL Reverse-Engineering. Professional CI/CD Agile Project Manager Нереляционные базы данных Супер - интенсив по паттернам проектирования Супер-практикум по использованию и настройке GIT IoT-разработчик Advanced Fullstack JavaScript developer Супер-интенсив "Azure для разработчиков"
Инфраструктура
Мониторинг и логирование: Zabbix, Prometheus, ELK
-17%
DevOps практики и инструменты
-18%
Архитектор сетей
-21%
Инфраструктурная платформа на основе Kubernetes
-22%
Супер-интенсив «IaC Ansible»
-16%
Супер-интенсив по управлению миграциями (DBVC)
-16%
Administrator Linux.Basic
-10%
Супер-интенсив «ELK»
-10%
Administrator Linux. Professional MS SQL Server Developer Безопасность Linux PostgreSQL Reverse-Engineering. Professional CI/CD VOIP инженер Супер-практикум по работе с протоколом BGP Супер - интенсив по паттернам проектирования Супер - интенсив по Kubernetes Супер-интенсив «СУБД в высоконагруженных системах»
Специализации Курсы в разработке Подготовительные курсы
+7 499 938-92-02

Реверс-инженеру на заметку: динамическое распределение памяти

В этой статье мы рассмотрим следующие виды динамического распределения памяти: 1. malloc. 2. calloc. 3. realloc.

Понимая эти аспекты, вы сможете быстрее продвинуться в сфере изучении реверс-инжиниринга.

Динамическое выделение памяти malloc

В первую очередь посмотрим наш код на языке программирования C:

int malloc_ex() {
    char *mem_alloc;
    // выделяем память под 11 символов
    mem_alloc = malloc(11 * sizeof(char));

    // записываем в память строку "Hello World"
    strcpy(mem_alloc, "Hello World");

    printf("malloc-mem_alloc: %s\n", mem_alloc);

    // освобождаем выделенную память
    free(mem_alloc);

    return 0;
}

Итак, в данной функции было выделено место под 11 символов посредством malloc(), а потом в выделенное пространство памяти была скопирована строка «Hello World».

Теперь посмотрим, как это выглядит в машинном коде. Но прежде обратите внимание на инструкции «nop». Они были размещены специально при подготовке статьи, чтобы разные части кода были более просты для понимания.

Машинный код динамического распределения памяти посредством malloc:

reverse_dev_pic_18_1-20219-357eb2.jpeg

В процессе применения malloc() размер выделенной памяти поначалу помещается в регистр edi. Потом системная функция _malloc вызывается в целях выделения памяти, а затем выделенное пространство памяти сохраняется в переменной ptr. Далее «Hello World» разбивается на «Hello Wo» и «rld», т. к. строка копируется в выделенную область памяти. И, в конце концов, осуществляется вывод на экран снова скопированной строки «Hello World» с последующим освобождением памяти посредством функции _free.

Динамическое чистое выделение памяти calloc

Как и прежде, сначала смотрим на наш код:

int calloc_ex() {
    char *mem_alloc;
    // выделяем память под 11 символов
    mem_alloc = calloc(11 * sizeof(char));

    // записываем в память строку "Hello World"
    strcpy(mem_alloc, "Hello World");

    printf("calloc-mem_alloc: %s\n", mem_alloc);

    // освобождаем выделенную память
    free(mem_alloc);

    return 0;
}

Как и в случае с методом malloc(), место для одиннадцати символов выделяется, а в указанное пространство копируется строка «Hello World». Потом вновь перемещённый «Hello World» распечатывается с последующим освобождением выделенного пространства памяти.

Машинный код динамического распределения памяти посредством calloc:

reverse_dev_pic_19_1-20219-214b15.jpeg

Динамическое распределение памяти с помощью calloc() по сути, выглядит в машинном коде почти так же, как и в случае с malloc(). Пространство для одиннадцати символов выделяется посредством системной функции _calloc. Потом строка «Hello World» разбивается на «Hello Wo» и «rld», так как она копируется во вновь выделенное пространство памяти. Далее происходит вывод на экран вновь перемещённой строки “Hello World» с последующим освобождением выделенной области памяти посредством функции _free.

Динамическое перераспределение памяти realloc

Смотрим код.

int realloc_free() {
    char *mem_alloc;

    // выделяем память под 11 символов
    mem_alloc = malloc(11 * sizeof(char));

    // записываем в память строку "Hello World"
    strcpy(mem_alloc, "Hello World");

    printf("malloc-mem_alloc: %s\n", mem_alloc);

    // выделяем память под 11 символов
    mem_alloc = realloc(mem_alloc, 21 * sizeof(char));

    // записываем в память строку "Hello World"
    strcpy(mem_alloc, "1337 h4x0r @nonymoose");

    printf("realloc-free-mem_alloc realloc: %s\n", mem_alloc);

    // освобождаем выделенную память
    free(mem_alloc);

    return 0;
}

В данной функции память для одиннадцати символов мы выделяем посредством malloc(). Потом в только что выделенную область памяти копируется «Hello World», что происходит прежде, чем указанное расположение памяти перераспределится для соответствия 21 символу.

В результате, «1337 h4x0r @nonymoose» копируется в только что перераспределённую область. В конечном итоге, происходит вывод на экран, и память освобождается.

Машинный код динамического распределения памяти посредством realloc:

reverse_dev_pic_20_1-20219-61c2a1.jpg

В первую очередь, происходит выделение памяти посредством malloc(). Потом, когда выведется на экран только что перемещённая строка «Hello World», будет вызван realloc() для переменной ptr (она представляет в коде переменную mem_alloc ), а также передан новый размер 0x15 (21). Далее «1337 h4x0r @nonymoose» разобьётся на «1337 h4x», «0r @nony», «moos» и «e», так как он копируется в только что перераспределённую область памяти. В конце концов, пространство будет освобождено посредством функции _free.

Источник

Не пропустите новые полезные статьи!

Спасибо за подписку!

Мы отправили вам письмо для подтверждения вашего email.
С уважением, OTUS!

Автор
0 комментариев
Для комментирования необходимо авторизоваться