C++ Исходник Sec_no_syscalls - Выполнение системных вызовов с флагом SEC_NO_CHANGE

Murasaki
Разработчик
Статус
Оффлайн
Регистрация
18 Мар 2020
Сообщения
431
Реакции[?]
870
Поинты[?]
206K
Ку, гайс, запилил себе либу для сисколлов, которую изначально я сделал для своего инжектора, ничего сверхъестественного я не намудрил, но подумал, что это будет забавный релиз в мою копилку. Так шо вот, такие дела.

Ссылка на репизиторий:
Пожалуйста, авторизуйтесь для просмотра ссылки.


Копипаста с моего README, только на русском:

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

Пример:
C++:
... random bytes
push rcx
jmp to_next_region
... random bytes

next_region:
... random bytes
pop r10
jmp to_next_region2
... random bytes

next_region2:
... random bytes
pop r10
jmp to_next_region3
... random bytes

next_region3:
... random bytes
mov eax, system_number
jmp to_next_region4
... random bytes

next_region4:
... random bytes
syscall
jmp to_next_region5
... random bytes

next_region5:
... random bytes
add rsp, 8
jmp to_next_region6
... random bytes

next_region6:
... random bytes
add rsp, 8
jmp to_next_region7
... random bytes

next_region7:
... random bytes
jmp qword ptr ds:[rsp-8]
... random bytes
Сами регионы маппятся несколько раз, первый раз регионам дается доступ к «PAGE_READWRITE» для возможности заполнить шеллкод, затем после установки шеллкодов происходит второй ремаппинг с защитой «PAGE_EXECUTE», чтобы в дальнейшем в регион ничего нельзя было записать.

Пример использования
C++:
#include "syscall/Syscall.hpp"
namespace antidebug {
    void HideThread ( ) {
        try {
            const auto res = c_syscall::Syscall<NTSTATUS> ( HASH ( "NtSetInformationThread" ), GetCurrentThread ( ), 0x11, 0, 0 );
            std::printf ( "NtSetInformationThread result: 0x%X\n", res );
        }
        catch ( std::exception& ex ) {
            std::printf ( "%s\n", ex.what ( ) );
        }
    }

    void CheckDebugObjectHandle ( ) {
        try {
            HANDLE debug_object;
            ULONG ret = NULL;

            const auto res = c_syscall::Syscall<NTSTATUS> ( HASH ( "NtQueryInformationProcess" ), GetCurrentProcess ( ), 0x1E, &debug_object, sizeof ( DWORD64 ), &ret );
            std::printf ( "NtQueryInformationProcess result: 0x%X\n", res );
        }
        catch ( std::exception& ex ) {
            std::printf ( "%s\n", ex.what ( ) );
        }
    }

    void CheckProcessDebugFlags ( ) {
        try {
            DWORD64 debug_flags;
            ULONG ret = NULL;

            const auto res = c_syscall::Syscall<NTSTATUS> ( HASH ( "NtQueryInformationProcess" ), GetCurrentProcess ( ), 0x1F, &debug_flags, sizeof ( DWORD ), &ret );
            std::printf ( "NtQueryInformationProcess result: 0x%X:0x%X\n", res, debug_flags );
        }
        catch ( std::exception& ex ) {
            std::printf ( "%s\n", ex.what ( ) );
        }
    }
}

int main ( ) {
    antidebug::HideThread ( );
    antidebug::CheckDebugObjectHandle ( );
    antidebug::CheckProcessDebugFlags ( );

    while ( true );
    return 0;
}

Проблемы
Несмотря на все это, библиотека сама по себе создает множество потенциальных паттернов для реверс-инжиниринга, например: вызов PEB или вызов импорта GetCurrentProcess, о котором я благополучно забыл.

В целом, вы можете накрыть эту библиотеку мутацией от приватных протекторов, по типу VMProtect.

Я не думаю, что буду вносить какие-либо изменения в эту библиотеку. Всего хорошего!
 
Забаненный
Статус
Оффлайн
Регистрация
24 Июн 2024
Сообщения
28
Реакции[?]
3
Поинты[?]
3K
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Ку, гайс, запилил себе либу для сисколлов, которую изначально я сделал для своего инжектора, ничего сверхъестественного я не намудрил, но подумал, что это будет забавный релиз в мою копилку. Так шо вот, такие дела.

Ссылка на репизиторий:
Пожалуйста, авторизуйтесь для просмотра ссылки.


Копипаста с моего README, только на русском:

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

Пример:
C++:
... random bytes
push rcx
jmp to_next_region
... random bytes

next_region:
... random bytes
pop r10
jmp to_next_region2
... random bytes

next_region2:
... random bytes
pop r10
jmp to_next_region3
... random bytes

next_region3:
... random bytes
mov eax, system_number
jmp to_next_region4
... random bytes

next_region4:
... random bytes
syscall
jmp to_next_region5
... random bytes

next_region5:
... random bytes
add rsp, 8
jmp to_next_region6
... random bytes

next_region6:
... random bytes
add rsp, 8
jmp to_next_region7
... random bytes

next_region7:
... random bytes
jmp qword ptr ds:[rsp-8]
... random bytes
Сами регионы маппятся несколько раз, первый раз регионам дается доступ к «PAGE_READWRITE» для возможности заполнить шеллкод, затем после установки шеллкодов происходит второй ремаппинг с защитой «PAGE_EXECUTE», чтобы в дальнейшем в регион ничего нельзя было записать.

Пример использования
C++:
#include "syscall/Syscall.hpp"
namespace antidebug {
    void HideThread ( ) {
        try {
            const auto res = c_syscall::Syscall<NTSTATUS> ( HASH ( "NtSetInformationThread" ), GetCurrentThread ( ), 0x11, 0, 0 );
            std::printf ( "NtSetInformationThread result: 0x%X\n", res );
        }
        catch ( std::exception& ex ) {
            std::printf ( "%s\n", ex.what ( ) );
        }
    }

    void CheckDebugObjectHandle ( ) {
        try {
            HANDLE debug_object;
            ULONG ret = NULL;

            const auto res = c_syscall::Syscall<NTSTATUS> ( HASH ( "NtQueryInformationProcess" ), GetCurrentProcess ( ), 0x1E, &debug_object, sizeof ( DWORD64 ), &ret );
            std::printf ( "NtQueryInformationProcess result: 0x%X\n", res );
        }
        catch ( std::exception& ex ) {
            std::printf ( "%s\n", ex.what ( ) );
        }
    }

    void CheckProcessDebugFlags ( ) {
        try {
            DWORD64 debug_flags;
            ULONG ret = NULL;

            const auto res = c_syscall::Syscall<NTSTATUS> ( HASH ( "NtQueryInformationProcess" ), GetCurrentProcess ( ), 0x1F, &debug_flags, sizeof ( DWORD ), &ret );
            std::printf ( "NtQueryInformationProcess result: 0x%X:0x%X\n", res, debug_flags );
        }
        catch ( std::exception& ex ) {
            std::printf ( "%s\n", ex.what ( ) );
        }
    }
}

int main ( ) {
    antidebug::HideThread ( );
    antidebug::CheckDebugObjectHandle ( );
    antidebug::CheckProcessDebugFlags ( );

    while ( true );
    return 0;
}

Проблемы
Несмотря на все это, библиотека сама по себе создает множество потенциальных паттернов для реверс-инжиниринга, например: вызов PEB или вызов импорта GetCurrentProcess, о котором я благополучно забыл.

В целом, вы можете накрыть эту библиотеку мутацией от приватных протекторов, по типу VMProtect.

Я не думаю, что буду вносить какие-либо изменения в эту библиотеку. Всего хорошего!
Привет, не могу пока ставить реакции, но напишу текстом, хорошая статья, хорошо написанный код, но я немного не вижу смысла в таком, просто разве нельзя, хукнув-брякнув NtMapViewOfSection, найти адресс где оно вызывается, и там уже увидеть откуда оно вызывается, и какой syscall number, в аргументах функции, но это конечно если в проекте отключена оптимизация, так что доеб с нихуя
 
Murasaki
Разработчик
Статус
Оффлайн
Регистрация
18 Мар 2020
Сообщения
431
Реакции[?]
870
Поинты[?]
206K
хукнув-брякнув NtMapViewOfSection, найти адресс где оно вызывается, и там уже увидеть откуда оно вызывается, и какой syscall number, в аргументах функции, но это конечно если в проекте отключена оптимизация, так что доеб с нихуя
привет, доеб довольно адекватный, спасибо
на самом деле, подобных моментов для атак довольно много, что является жирным минусом этой либы
далеко ходить не надо хд
1720715605059.png
1720715625761.png
 
Начинающий
Статус
Оффлайн
Регистрация
2 Фев 2022
Сообщения
69
Реакции[?]
14
Поинты[?]
19K
Ставим хук на NtCreateSection в SSDT -> убираем флаг SEC_NO_CHANGE и все накрылось пиздой :roflanEbalo:

Идея гуд, можно улучшить и потом юзать для подъеба реверсеров.
 
Murasaki
Разработчик
Статус
Оффлайн
Регистрация
18 Мар 2020
Сообщения
431
Реакции[?]
870
Поинты[?]
206K
Ставим хук на NtCreateSection в SSDT -> убираем флаг SEC_NO_CHANGE и все накрылось пиздой
нет смысла настолько далеко уходить, рискуя бсоднуть себя через N-е количество времени, это того просто не стоит, учитывая что я просто могу для проверки пытаться как-либо взаимодействовать с памятью, но уже находясь под виртой
алсо если либу ничем не протектить, то можно по голым байтам найти, которые используются при переборке системного номера и менять там что душе угодно

опять же на все это, мой ответ выше
на самом деле, подобных моментов для атак довольно много, что является жирным минусом этой либы
далеко ходить не надо хд
 
Начинающий
Статус
Оффлайн
Регистрация
22 Дек 2023
Сообщения
264
Реакции[?]
16
Поинты[?]
17K
Ставим хук на NtCreateSection в SSDT -> убираем флаг SEC_NO_CHANGE и все накрылось пиздой :roflanEbalo:
проще запустить через x64dbg с отладкой через эмуляцию и никто не узнает что запущен дебагер с виртой как и неограниченное кол-во бряков без записи в память и регистры
 
читрейд
Начинающий
Статус
Оффлайн
Регистрация
20 Июл 2019
Сообщения
14
Реакции[?]
4
Поинты[?]
0
09312398.jpg
Моя первая реакция после того как я увидел эту либу. :kappa:
 
Сверху Снизу