Skip to content

GlobThe.Top

  • Продвинутый обход EDR: техники 2025 года Обход EDR
  • Обход EDR: техники 2026 года Обход EDR
  • win32k: Таблица обратных вызовов ядра — полный разбор 126 функций Reverse Engineering
  • win32kfull: переполнение буфера в NtUserGetRawInputDeviceInfo Vulnerability Research
  • Анатомия EDR Killer — техники обхода и отключения защиты в современных ransomware Malware Analysis
  • Обфускация кода C/WinAPI: от основ до продвинутых техник Обход EDR
  • Обход AMSI и ETW в 2026 — патчинг в памяти, unhooking, custom CLR hosting Evasion
  • CVE-2026-21509: APT28 — от фишинга до SYSTEM за 48 часов CVE

Скрытые баги на виду: Поиск уязвимостей внутри разделяемых библиотек

Posted on 1 апреля, 2026 By AkaTor
Download PDF

Категория: Vulnerability Research / Static Analysis
Уровень: Intermediate
Оригинал: core-jmp.org by Grzegorz Wypych (h0rac)
Инструмент: ByteRay — движок охоты за уязвимостями
Перевод: Aka Tor
Дата: Март 2026


Введение

Статья объясняет как движок ByteRay для охоты за уязвимостями обнаруживает баги безопасности внутри разделяемых библиотек, от которых зависят основные бинарники. Ключевая проблема — идентификация связей между источниками данных и опасными операциями (sinks), когда они пересекают границы разных бинарных файлов.

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


1. Демонстрационный случай

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

1.1 Основной бинарник — main_static.c

Принимает пользовательский ввод через аргументы командной строки или stdin, затем передаёт данные в функции внешних библиотек:

#include <stdio.h>
#include <string.h>
#include "libsink.h"
#include "libmemcpy_overflow.h"

// Source = argv[1] или stdin
int main(int argc, char **argv)
{
    char input[256];

    if (argc > 1) {
        // Источник: argv[1]
        const char *user_data = argv[1];
        int user_len = strlen(user_data);

        // Старый sink (strcpy overflow)
        dangerous_sink(user_data);

        // Новый sink (memcpy overflow)
        memcpy_overflow_sink(user_data, user_len);

    } else {
        // Источник: stdin
        printf("Enter some text: ");
        fflush(stdout);

        if (fgets(input, sizeof(input), stdin) == NULL) {
            return 1;
        }

        // удаляем newline
        input[strcspn(input, "\n")] = '\0';

        int user_len = strlen(input);

        // Старый sink (strcpy overflow)
        dangerous_sink(input);

        // Новый sink (memcpy overflow)
        memcpy_overflow_sink(input, user_len);
    }

    return 0;
}

1.2 libsink.c — переполнение через strcpy

#include <string.h>
#include <stdio.h>
#include "libsink.h"

// Sink в библиотеке .so
void __attribute__((noinline)) dangerous_sink(const char *user_data)
{
    char buf[16];

    // Переполнение
    strcpy(buf, user_data);

    // Предотвращение оптимизации компилятором
    printf("Copied data: %s\n", buf);
}

libsink-aarch64-linux-gnu.so disassembly

1.3 libmemcpy_overflow.c — переполнение через контролируемую длину memcpy

#include <stdio.h>
#include <string.h>

// Stack overflow через заражённую длину в memcpy
void __attribute__((noinline))
memcpy_overflow_sink(const char *user_input, int user_size)
{
    char local[16];

    // БАГ: контролируемая пользователем длина
    memcpy(local, user_input, user_size);

    // Предотвращение оптимизации
    printf("Copied: %s (len=%d)\n", local, user_size);
}

libmemcpy_overflow-aarch64-linux-gnu.so disassembly


2. Анализ с ByteRay

После компиляции получаем 3 файла, основной бинарник включает обе библиотеки плюс стандартную libc:

readelf -d main_static2-aarch64-linux-gnu

Dynamic section at offset 0xfda8 contains 28 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [./libsink-aarch64-linux-gnu.so]
 0x0000000000000001 (NEEDED)             Shared library: [./libmemcpy_overflow-aarch64-linux-gnu.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

Уязвимости очевидны при просмотре исходного кода, но из дизассемблирования бинарника это значительно сложнее. Если мы посетим вызов первой уязвимой библиотечной функции dangerous_sink, мы увидим что она просто возвращает указатель из .got (GLOBAL OFFSET TABLE). Анализируя только основной бинарник, мы не найдём бага потому что не видим уязвимый дизассемблированный код.

2.1 Запуск анализа

ByteRay выполняет:

  • Загрузку и анализ базы данных нескольких бинарников
  • Обратную рекурсивную трассировку параметров для определения происхождения данных
  • Прямое распространение заражения (taint propagation) для локализации опасных sink’ов
  • Разрешение межбиблиотечных вызовов функций через GOT (Global Offset Table)

Запуск с флагом --library=true:

python3 -m vulnhunt tests/analysis/libload/main_static2-aarch64-linux-gnu \
    --output-directory=libtest --library=true

Альтернативный вариант с указанием директории библиотек:

python3 -m vulnhunt tests/analysis/libload/main_static-aarch64-linux-gnu \
    --output-directory=libtest --lib_dirs=test_libload/lib --library=true

Проверка зависимостей бинарника:

readelf -d main_static2-aarch64-linux-gnu

2.2 Дизассемблирование

main_static2-aarch64-linux-gnu disassembly

main_static2-aarch64-linux-gnu disassembly detail

ByteRay analysis output


2.3 Вывод движка

Полный вывод ByteRay (сокращённо ключевые моменты):

 ____        _       ____
| __ ) _   _| |_ ___|  _ \ __ _ _   _
|  _ \| | | | __/ _ \ |_) / _` | | | |
| |_) | |_| | ||  __/  _ < (_| | |_| |
|____/ \__, |\__\___|_| \_\__,_|\__, |
       |___/                    |___/

[info] Loaded database: main_static2-aarch64-linux-gnu.bndb
[info] Loaded external library: ./libsink-aarch64-linux-gnu.so
[info] Loaded external library: ./libmemcpy_overflow-aarch64-linux-gnu.so
[debug] Skipping system library libc.so.6

[*] 'main_static2-aarch64-linux-gnu'
    Arch:     aarch64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      PIE enabled

[info] stackoverflow module enabled...
[debug] func_name: main, func_addr: 0x400a14, func_sinks: ['strlen', 'printf', 'strlen'],
        func_sources: ['fgets']
[debug] func_name: dangerous_sink, func_addr: 0x400634, func_sinks: ['strcpy', 'printf'],
        func_sources: []
[debug] func_name: memcpy_overflow_sink, func_addr: 0x400634, func_sinks: ['memcpy', 'printf'],
        func_sources: []

[info] Start of analysis: main_static2-aarch64-linux-gnu
-------------------------------------------------------------------------------------
[info] 0x400a20: Tracing var_130#1 = argv#0
[info] Forward recursive param use search...
[info] 0x400a34: Tracing param: x0_2#13 = [x0_1#12 + 8].q @ mem#0
[info] 0x400a48: Tracing param: x0_5#16 = user_data#1
[info]  Resolved [dangerous_sink] by address: 0x400860
[info]  Found param: x0_2#13 = [x0_1#12 + 8].q @ mem#0
[info] Visit [dangerous_sink] function
[info]  Resolved [memcpy_overflow_sink] by address: 0x400850
[info]  Found param usage in sign extension operation: x1#4 = zx.q(user_len#1)
[info] Visit [memcpy_overflow_sink] function
[info] Source fgets detected
[info] End of analysis: main_static2-aarch64-linux-gnu
-------------------------------------------------------------------------------------
[info] Start of analysis: libsink-aarch64-linux-gnu.so
-------------------------------------------------------------------------------------
[info]  Resolved [strcpy] by address: 0x400530
[info] Sink strcpy detected
[info] Reverse recursive search for: mem#1 = 0x400530(x0#1, x1#1)
[info]  Found param: x0#1 = &buf
[info] Possible type stack overflow detected at 0x400648
[info] Variable x1#1 = var_18#1 computed without bounds checking
[info] Destination buffer size: 16 (0x10)
[info] End of analysis: libsink-aarch64-linux-gnu.so
-------------------------------------------------------------------------------------
[info] Start of analysis: libmemcpy_overflow-aarch64-linux-gnu.so
-------------------------------------------------------------------------------------
[info]  Resolved [memcpy] by address: 0x400530
[info] Sink memcpy detected
[info] Possible type stack overflow detected at 0x400648
[info] Variable w2#1 = w1#1 computed without bounds checking
[info] Destination buffer size: 16 (0x10)
[info] End of analysis: libmemcpy_overflow-aarch64-linux-gnu.so
-------------------------------------------------------------------------------------

3. Результаты анализа

ByteRay успешно обнаружил обе уязвимости:

  1. strcpy overflow в libsink-aarch64-linux-gnu.so по адресу 0x400648 — dangerous_sink() вызывает strcpy(buf[16], user_data) без проверки длины
  2. memcpy overflow через заражённый параметр длины в libmemcpy_overflow-aarch64-linux-gnu.so — memcpy_overflow_sink() использует контролируемый пользователем user_size как длину для memcpy в 16-байтный буфер

Движок проследил поток данных от источников argv[1] и fgets() через вызовы библиотечных функций, идентифицируя что контролируемый пользователем ввод достигает небезопасных операций без валидации.


4. Технический подход

Ключевой инсайт статьи: «Уязвимости часто находятся в коде который разработчики редко проверяют». Изоляция анализа библиотечного кода предотвращает обнаружение уязвимостей, требующих трассировки потока данных через границы бинарников.

ByteRay решает это через:

  • Cross-binary taint analysis — трассировка пользовательского ввода (sources) из argv или stdin
  • Отслеживание распространения данных через вызовы функций между бинарниками
  • Идентификация опасных sink’ов (strcpy, memcpy) без валидации границ
  • Маппинг цепочек параметров между бинарниками через GOT/PLT

Заключение

Эта методология раскрывает уязвимости, прячущиеся в часто используемых разделяемых библиотеках — коде, который разработчики редко проверяют индивидуально, делая баги «скрытыми на виду». Межбинарный анализ потока данных является критически важным для полного покрытия поверхности атаки в современных приложениях.

Ссылки

  • core-jmp.org — оригинал
  • Автор: Grzegorz Wypych (h0rac)
  • Инструмент: ByteRay vulnerability hunting engine
Vulnerability Research

Навигация по записям

Previous Post: Внутри WMI: Трассировка Windows Management от потребителей до COM-провайдеров
Next Post: Обход Code Integrity: Использование BYOVD для получения примитивов чтения/записи ядра

Related Posts

  • CVE-2026-20811: Асинхронные окна Windows пошли не так — эксплуатация Type Confusion в Win32k Vulnerability Research
  • win32kfull: переполнение буфера в NtUserGetRawInputDeviceInfo Vulnerability Research

Archives

  • Апрель 2026
  • Март 2026

Categories

  • Browser Exploitation
  • CVE
  • Evasion
  • Injection
  • Lateral Movement
  • Linux Kernel Exploitation
  • Malware Analysis
  • Persistence
  • Privesc
  • Reverse Engineering
  • Uncategorized
  • Vulnerability Research
  • Windows Internals
  • Windows Kernel
  • Windows Persistence
  • Обход EDR

Recent Posts

  • win32k: Таблица обратных вызовов ядра — полный разбор 126 функций
  • win32kfull: переполнение буфера в NtUserGetRawInputDeviceInfo
  • Как Windows раздаёт обновления по сети: полный реверс P2P протокола Windows Update
  • Token Manipulation 2026 — Impersonation, Potato Attacks, Token Theft: от сервисного аккаунта до SYSTEM
  • Анатомия EDR Killer — техники обхода и отключения защиты в современных ransomware

Recent Comments

Нет комментариев для просмотра.
  • win32k: Таблица обратных вызовов ядра — полный разбор 126 функций Reverse Engineering
  • Продвинутый обход EDR: техники 2025 года Обход EDR
  • Внутри WMI: Трассировка Windows Management от потребителей до COM-провайдеров Windows Internals
  • Protected Process Light (PPL) в 2026 — как Windows защищает критические процессы и как это обходят Uncategorized
  • CVE-2026-21509: APT28 — от фишинга до SYSTEM за 48 часов CVE
  • Как EDR видит угрозы — и где он слепнет Обход EDR
  • win32kfull: переполнение буфера в NtUserGetRawInputDeviceInfo Vulnerability Research
  • Обфускация кода C/WinAPI: от основ до продвинутых техник Обход EDR

Copyright © 2026 GlobThe.Top.

Powered by PressBook News Dark theme