• XSS.stack #1 – первый литературный журнал от юзеров форума

Актуальность CRT в 2024

А можно тут поподробнее?
Привет, да там всё просто как табуретка, речь идет о IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG и структуры, которая под ним лежит. =)
В основном ты выставляешь security cookie, то бишь копипастишь свой куки туда, в идеале ещё модифицируешь битмапу в ntdll и патчишь __guard функции (выставляя там тупой джамп на свои же функции), хотя это необязательно и достаточно выставить простые джампы то ли по rax, то ли по rcx (если компилятор вдруг сгенерил nopы вместо функций, у кланга была такая проблема, на какой регистр джампить не помню, я уже давно виндой не пользуюсь просто), на этом обычно всё. Если ты ммапишь драйвер, то ситуация немного отличается, там куки придется вручную инициализировать. =)
 
Последнее редактирование:
А что это? Впервые слышу
Про security cookie знаю, видел даже где то реализацию их обработки, но вот про "битмапу в ntdll" слышу впервые
А что насчёт SEHandlerTable знаешь? (х32 офк)
Нет, насчет SEHandlerTable не знаю, я никогда его не хандлил, но ты можешь сам поковырять в этом направлении, если тебе это интересно, насколько я помню под x32 вообще ничего не нужно для корректной работы эксепшенов делать? Знатоки 32-битной малвари могут меня поправить. Что касается битмапов, они как раз и нужны для работы __guard функций, при каждом обращении к ним идёт обращение в ntdll и там чекается, что функция, к которой происходит обращение, валидна. Как я сказал, я не помню подробностей, потому что уже давно не пользуюсь виндой и не пишу малварь под неё, тебе нужно глянуть в LdrpValidateUserCallTarget в иде, ну или можешь сам поискать в интернете разбор CFG, вот например.
 

d4x0n3l

Никто ничего не боится юзать, просто это глупо при разработке, как Вы говорите не "легитного" софта. На счет того что под капотом malloc сидит RtlAllocateHeap, которая выделяет память в CRT-шном хипе, непонятно как созданном RtlAllocateHeap, плюс добавление CRT- шной структуры с размером блока. Вы вместо того чтоб сразу примерять все к созданию малвари и "палевности", лучше бы учли, что частое выделение памяти напрямую при помощи NtAllocateVirtualMemory приводит к дефрагментации оной, если не создавать свой сборщик мусора и дефрагментатор, как это реализовано в хип-функциях.
При использовании напрямую RtlAllocateHeap, мы в отличие чем при использовании malloc можем:
- указать из какой кучи будет происходить выделение и как оно будет происходить или лучше создать свою RtlCreateHeap
при этом:
- задать параметры фрагментации HEAP_NO_SERIALIZE, HEAP_GROWABLE, HEAP_GENERATE_EXCEPTIONS или же HeapSetInformation [(HeapOptimizeResources + HeapCompatibilityInformation), HEAP_OPTIMIZE_RESOURCES_CURRENT_VERSION + HEAP_LFH],
- задать параметры обработки ошибок (HeapEnableTerminationOnCorruption, HeapCompatibilityInformation)
- динамически "подтягивать" хип RtlCompactHeap
Есть даже "статья" на хабре, что malloc жрет память и не освобождает память, хз кем написанная:)
Но она частично ошибочна: память переходит в MEM_RESERVE после free т.к. память выделенная для кучи при ее создании не освободится, лишь будет помечена во внутренних структурах HEAP как пригодная для дальнейшего использования, ибо free не вызывает и не должно вызывать RtlDestroyHeap. Не ошибочно лишь то что malloc действительно выделяет память не в одной какой то куче, а в какой - тут хз.
Таким образом malloc не обладает ни гибкостью, ни прямой открытостью процесса ее работы, создана для использования, не задумываясь. Использовать ее для "ультра многопоточных" приложений считаю глупостью.
Хип (куча) - это та же память, выделенная NtAllocateVirtualMemory при запуске процесса, чьи параметры хранятся в виде сложной структуры HEAP и HEAP_ENTRY в PEB. Отличие этой памяти лишь в удобстве и простоте использования, т.к. реализован уровень абстракции от виртуальной памяти при помощи системных хип-функций, системных структур и заложенных автоматических сборщиков мусора и дефрагментаторов.
 
Последнее редактирование:
Пожалуйста, обратите внимание, что пользователь заблокирован
В этом году тред по теме crt гораздо интереснее, чем в прошлые разы
 

d4x0n3l

Лучше цитируйте мои сообщения, на которые отвечаете, от прямых упоминаний мне не приходят уведомления. =)

Никто ничего не боится юзать, просто это глупо при разработке, как Вы говорите не "легитного" софта. На счет того что под капотом malloc сидит RtlAllocateHeap, которая выделяет память в CRT-шном хипе, непонятно как созданном RtlAllocateHeap, плюс добавление CRT- шной структуры с размером блока.
Почему глупо? Потому, что вы не разобрались, как работает malloc...? В любом случае, вся ваша дальнейшая аргументация строится именно на этом, если что, код crt открыт, как и код самого malloc:
C++:
//
// malloc_base.cpp
//
//      Copyright (c) Microsoft Corporation. All rights reserved.
//
// Implementation of _malloc_base().  This is defined in a different source file
// from the malloc() function to allow malloc() to be replaced by the user.
//
#include <corecrt_internal.h>
#include <malloc.h>
#include <new.h>



// This function implements the logic of malloc().  It is called directly by the
// malloc() function in the Release CRT and is called by the debug heap in the
// Debug CRT.
//
// This function must be marked noinline, otherwise malloc and
// _malloc_base will have identical COMDATs, and the linker will fold
// them when calling one from the CRT. This is necessary because malloc
// needs to support users patching in custom implementations.
extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _malloc_base(size_t const size)
{
    // Ensure that the requested size is not too large:
    _VALIDATE_RETURN_NOEXC(_HEAP_MAXREQ >= size, ENOMEM, nullptr);

    // Ensure we request an allocation of at least one byte:
    size_t const actual_size = size == 0 ? 1 : size;

    for (;;)
    {
        void* const block = HeapAlloc(__acrt_heap, 0, actual_size);
        if (block)
            return block;

        // Otherwise, see if we need to call the new handler, and if so call it.
        // If the new handler fails, just return nullptr:
        if (_query_new_mode() == 0 || !_callnewh(actual_size))
        {
            errno = ENOMEM;
            return nullptr;
        }

        // The new handler was successful; try to allocate again...
    }
}
Напомню, что моя претензия к вам была в том, что вы не аргументировали и не объяснили свою позицию, например почему CRT - это "тормоза" и почему "тот же malloc, rand, memset,memcpy и другая хрень" нормально не отработают при маппинге в память, как и то, почему malloc "не нужен и неясен", хотя нет, почему он вам неясен я уже понял, этот вопрос закрыт, а вот к чему все эти ваши разъяснения про дефрагментацию памяти и статья более чем десятилетней давности на хабре, я всё ещё не понял, потому что отношения к моей претензии они не имеют и всё ещё не отвечают на поставленные вопросы, но в любом случае, возможно эта информация будет кому-то полезна. =)
Мне вот теперь мне интересно услышать нормальную аргументацию (не из разряда "хз"), почему использовать malloc в "ультра многопоточных" приложениях глупо. Если аргумент будет от скорости, то любые проблемы со скоростью решаются кастомными аллокаторами, о чем я вам и написал в своем предыдущем посте.

Edit:
Надеюсь вы поняли, что ваши аргументы касательно того, что не стоит использовать CRT, ибо вам не понятно, как и что там под капотом работает, даже не являются аргументами, особенно учитывая тот факт, что CRT открыт и вы можете скачать сурсы вместе с windows kit.
Но на всякий случай, чтобы вам было максимально понятно, что я хочу услышать от вас:
  1. Почему CRT это тормоза?
  2. Почему malloc, rand, memset и memcpy не отработают при маппинге в память (если всё замаплено как надо)?
  3. Почему malloc / new не нужен? (не нужно мне писать очередные объяснения не по теме и из разряда хз)
  4. Почему использовать malloc в "ультра многопоточных" приложениях глупо?
 
Последнее редактирование:
Пожалуйста, обратите внимание, что пользователь заблокирован
"ультра многопоточных"
Сразу стало интересно, что это за термин. Наверное, имеются ввиду те самые легендарные брутеры/чекеры с 4096 потоками, из-за которых уже был срач не так давно. Хотя мне так никто и не пояснил доходчиво, почему это лучше асинка с пулом по одному потоку на ядро, но окей.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
, то человек, который занимается криптом, уж тем более должен их знать и учитывать
Вы все пишете верно, но к сожалению, с крипторами в продаже все весьма грустно. Уже как-то писал, кто умеет - тот в привате, а в паблике в 99% копипаст. Там люди даже РЕ формат не знают, какой уж seh или tls

Хотя мне так никто и не пояснил доходчиво, почему это лучше асинка с пулом по одному потоку на ядро, но окей.
Хз о каком сраче речь, но те, кого я видел (кто кодит 1000 потоков локеры или брутеры) просто не могут осилить асинхрощину, вот и.
 
Вот где получается глобальный хендл CRT-шного хипа (вызывается в core_crt_dll_init() при инициализации CRT либы , либо если его не произошло - то при первом вызове malloc):
Декомпиляция msvcrt.dll Windows 11 23H2:

C:
//Не экспортируется.
__int64 __fastcall heap_init(int a1)

{
  __int64 result; // rax
  int HeapInformation; 
  HeapInformation = a1; // не понятный маневр
  result = (__int64)HeapCreate(0, 0x1000ui64, 0i64); //Без флагов
  crtheap = (HANDLE)result;
  if ( result )
  {
    //Писался код мелкософтом явно не по своей же документации:
    //HeapCompatibilityInformation
    //Включает функции кучи. Поддерживается только куча с низким уровнем фрагментации (LFH).
    //Однако для приложений нет необходимости включать LFH, так как система использует LFH по мере необходимости для обслуживания запросов на выделение памяти.
    //Т.е. нахера он тут не нужен в либе из Windows 11 23H2
    //Windows XP и Windows Server 2003: По умолчанию LFH не включен. Чтобы включить LFH для указанной кучи, задайте для переменной, на которую указывает параметр HeapInformation , значение 2. После включения LFH для кучи ее нельзя отключить.
    //Не понятно зачем это нужно, еще и 2 раза
    HeapInformation = 2; // вкл LFH, хотя этого не нужно в Win11
    HeapSetInformation((HANDLE)result, HeapCompatibilityInformation, &HeapInformation, 4ui64);
    HeapInformation = 2; // вкл LFH, хотя этого не нужно в Win11
    HeapSetInformation(crtheap, HeapCompatibilityInformation, &HeapInformation, 4ui64);
    return 1i64;
  }
  return result;
}

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

Асинхрошщину не всегда можно использовать, если юзаешь библиотеки ее не поддерживающие.
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх