На что влияет NtGlobalFlag ?

Тема в разделе "WASM.WIN32", создана пользователем Asterix, 3 июн 2005.

  1. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    subj

    Если его обнулить под отладчиком, как это повлияет на приложение

    и на отладчик?
     
  2. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Ага, ты и до NtGlobalFlag добрался ;)

    А чего сам-то не проверишь ?

    Ежели там 70h стоит - флаги enable heap-checking в соответствии с учением Four-F, то ИМХО для приложения вроде бы ничего страшного быть не должно, а для отладчика - интересно, надо бы проверить ...
     
  3. bogrus

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine
    Можно смотреть по bp 7FFDF068 или bp RtlGetNtGlobalFlags, загрузчик этот флаг насилует во всю, а приложению, например простому (Hello World) оно не сдалось, а так (в VB\Delphi ...) чуть ли не каждая ф-ция в NT приводит к вызову RtlGetNtGlobalFlags, я думаю что на результат этих ф-ций влиять флаг не должен, только на "окружение" и вот если его обнулить, то отладчик например перестанет получать LDR строки
     
  4. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576




    Тут практического исследования вряд ли достаточно, нужна

    теория.







    Я так понял что он и сейчас, т.е. при 0x70 не получает,

    нужно устанавливать в 0x72
     
  5. bogrus

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine




    Да, второй бит для этого, а 0x70 это вроде по умолчанию, но у каждого могут быть свои настройки (см. Gflags.exe)
     
  6. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Ну, чего не договариваем ?



    bogrus, ты же наверняка знаешь, что несмотря на большое число обращений к NtGlobalFlags реально интересные флажки 70h используются в одном определенном месте, а именно в RtlCreateHeap и попадают они именно в дворд по адресу ProcessHeap+10h со всеми вытекающими отсюда последствиями типа BAADF00D, ABABA.. и FEEE ;)



    Кстати в XP SP2 флаги 70h трансформируются в ProcessHeap[10h] = 40000060h, а как в NT и w2k ?
     
  7. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Asterix

    > "нужна теория"



    Из теории мне известны две вещи:

    1) Cогласно Four-F флаги 0х70 разрешают дополнительный контроль валидности операций с блоками кучи.

    2) Известен механизм контроля валидности операций с блоками кучи в режиме отладки в NT-системах (см.например Using SoftIce).

    В частности для контроля записи за пределы выделенного размера HeapAlloc выделяет больше памяти чем запрашивается и дописывает в конец выделенного блока данных 8 байт хвостового маркера ABAB..ABh. Соответственно при освобождении блока HeapFree проверяет целостность этого маркера и в случае несовпадения сигнализирует отладчику (если таковой есть), вызывая DbgPrint и DbgBreakPoint (=int3). Если отладчика нет или он игнорирует int3 HeapFree возвращает false, устанавливает LastError (или генерит исключение если установлен флаг HEAP_GENERATE_EXCEPTIONS) и не освобождает блок.

    Для контроля записи в свободный блок HeapFree заполняет освободившееся место сигнатурой FEEEFEEE. Соответсвенно HeapAlloc\Realloc в режиме отладки проверяют не только валидность заголовка блока, но и указанной сигнатуры и при ее разрушении также сигнализируют отладчику.



    Вот теперь вопрос - как HeapAlloc и HeapFree определяют, что включен отладочный режим. "Практическое исследование" для winXP (SP2) показывает:

    1) Несмотря на большое число вызовов RtlGetNtGlobalFlags в ntdll (около 30) обращение к флагам 0х70 осуществляется только в RtlCreateHeap. (Кстати бОльшая часть других вызовов идет в Heap-функциях на предмет проверки флага 0х800 - что это за флаг интересно знать ???)

    2) В RtlCreateHeap часть флагов NtGlobalFlag OR-ятся с частью флагов Flags (флагами создания кучи) и копируются в дворд заголовка кучи по адресу Base+10h (для главной кучи Base = ProcessHeap). Соответсвенно без отладчика этот дворд обычно = 0, а с отладчиком <> 0 ("очередной" IsDebuggerPresent от bogrus'а). Флаги NtGlobalFlag копируются со смещением: х10 -> x20, x20 -> x40, x40 -> x40000000, x80 -> x20000000, x200000 -> x80. Соответсвенно флаги х70 превращаются в х40000060.

    3) RtlAllocateHeap и RtlFreeHeap уже не проверяют флаги x70 NtGlobalFlag и работают только с флагами заголовка кучи dword[HeapBase+10h]. Эти флаги OR-ятся с флагами Flags, передаваемыми в качестве параметров в эти функции (!). В зависимости от того = 0 результирующие флаги или нет обработка идет по разным веткам - debugged или нет.

    4) Тут вырисовывается интересная картина - получается что "отладочный режим" контроля блоков кучи (запись и контроль сигнатур) может быть не только глобальным (флаги [ProcessHeap+10h]), но и локальным для каждого HeapAlloc\HeapFree и значит блоки кучи в принципе могут быть разными (с сигнатурами и без, если глобальные флаги не установлены). Значит эти флаги должны копироваться в поле Flags заголовка блока (и эти флаги действительно отличаются в отладочном режиме).

    Поэтому, возможно, что сброс флагов [ProcessHeap+10h] уже в процессе работы скучей не приведет к ошибкам. По крайней мере если тупо занулить эти флаги под отладчиком, то последующее выделение\освобождение блоков памяти идет без всяких сигнатур - также как и без отладчика и ничего явно "катастрофического" не происходит.

    5) Если под отладчиком запортить хвостовой маркер выделенного блока, то тоже получается интересная картина. RtlFreeHeep обнаруживает "коррупцию" и начинает "бить тревогу" - вроде как готовит сообщение DbgPrint, но что интересно DbgBreakPoint выдает только при IsDebuggerPresent. Поэтому, если обнулить PEB.BeingDebugged, то никакого int3 не вырабатывается и функция просто возвращает false, не освобождая блок (ес-но если не установлен флаг HEAP_GENERATE_EXCEPTIONS).



    Выводы:

    По крайней мере в WinXP (SP2) обнулить флаги х70 NtGlobalFlag можно ИМХО безболезненно. Это приведет к тому, что вновь создаваемые RtlCreateHeap кучи будут работать в обычном (неотладочном) режиме без дописывания контрольных сигнатур. Но чтобы отладочный режим не успел "наследить" нужно сбрасывать эти флаги до создания первой кучи процесса. Иначе остаются другие возможности выявления отладки по [HeapBase+10h] или "прогулке" по куче в поисках сигнатур ABABABAB и FEEEFEE.
     
  8. bogrus

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine
    Я вот ещё шо нашел, кроме менеджера памяти есть весьма интересные флажки (FLG_APPLICATION_VERIFIER например), чуть попозже попробую тоже чёт поисследовать (только с моря приехал)

    Global Flags Table

    The following table lists the flags that Gflags changes, the hexadecimal value and abbreviation for each flag, and the destination (R for registry, K for kernel, I for image file) in which the flag is valid.

    For a detailed description of each flag, see the Gflags Flag Reference
    Код (Text):
    1. ;==================================================================== =
    2. Symbolic name                   Hexadecimal Value       Destination
    3. ;=====================================================================
    4. FLG_DISABLE_DBGPRINT            0x08000000              R,K
    5. FLG_KERNEL_STACK_TRACE_DB       0x2000                  R
    6. FLG_USER_STACK_TRACE_DB         0x1000                  R,K,I
    7. FLG_DEBUG_INITIAL_COMMAND       0x4                     R,K
    8. FLG_DEBUG_INITIAL_COMMAND_EX    0x04000000              R, K
    9. FLG_HEAP_DISABLE_COALESCING     0x00200000              R,K,I
    10. FLG_DISABLE_PAGE_KERNEL_STACKS  0x80000                 R,K
    11. FLG_DISABLE_PROTDLLS            0x80000000              R,K,I
    12. FLG_DISABLE_STACK_EXTENSION     0x10000                 I
    13. FLG_CRITSEC_EVENT_CREATION      0x10000000              R,K,I
    14. FLG_APPLICATION_VERIFIER        0x100                   R,K,I
    15. FLG_ENABLE_HANDLE_EXCEPTIONS    0x40000000              R,K
    16. FLG_ENABLE_CLOSE_EXCEPTIONS     0x00400000              R,K
    17. FLG_ENABLE_CSRDEBUG             0x20000                 R,K
    18. FLG_ENABLE_EXCEPTION_LOGGING    0x00800000              R,K
    19. FLG_HEAP_ENABLE_FREE_CHECK      0x20                    R,K,I
    20. FLG_HEAP_VALIDATE_PARAMETERS    0x40                    R,K,I
    21. FLG_HEAP_ENABLE_TAGGING         0x800                   R,K,I
    22. FLG_HEAP_ENABLE_TAG_BY_DLL      0x8000                  R,K,I
    23. FLG_HEAP_ENABLE_TAIL_CHECK      0x10                    R,K,I
    24. FLG_HEAP_VALIDATE_ALL           0x80                    R,K,I
    25. FLG_ENABLE_KDEBUG_SYMBOL_LOAD   0x40000                 R,K
    26. FLG_ENABLE_HANDLE_TYPE_TAGGING  0x01000000              R,K
    27. FLG_HEAP_PAGE_ALLOCS            0x02000000              R,K,I
    28. FLG_POOL_ENABLE_TAGGING         0x400                   R
    29. FLG_ENABLE_SYSTEM_CRIT_BREAKS   0x100000                R, K, I
    30. FLG_LDR_TOP_DOWN                0x20000000              R, K, I
    31. FLG_MAINTAIN_OBJECT_TYPELIST    0x4000                  R,K
    32. FLG_SHOW_LDR_SNAPS              0x2                     R,K,I
    33. FLG_STOP_ON_EXCEPTION           0x1                     R,K,I
    34. FLG_STOP_ON_HUNG_GUI            0x8                     K
    35. ;=====================================================================
     
  9. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    leo



    Спасибо за подробную информацию.







    Момент когда

    DBEvent.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT

    подойдет?

    Вот только я еще не пробовал будет ли в этот момент

    уже установлен NtGlobalFlag, и кстати PEB.BeingDebugged

    тоже не мешало бы проверить в этот момент, займусь

    как появится время.
     
  10. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Вывод получается "неутешительный"



    До того как система выдает отладчику первый DebugBreakPoint она успевает создать 3 "кучки" - основную кучу процесса (PEB.ProcessHeap), кучу для LDR (база PEB.LDR - вниз на 10000h) и еще какую-то (Olly называет ее Map). Разумеется все эти кучи имеют отладочные флаги HeapFlags = x40000060 и все выделенные блоки обильно загажены хвостовыми маркерами ABAB'ами, а свободные FEEE.



    Вот кстати я и нашел для себя объяснение почему PEB.LDR отличается на 10h под отладчиком и без - потому, что перед этим блоком вставлены 8 байт хвостового маркера ABABA.. и 8 байт нулей для выравнивания. Сбылась мечта идиота - надеялся хоть какие следы в памяти найти, а тут как слоны на водопой прошли ;) Десятки килобайт - бери любой блок памяти и разматывай клубочек по цепочке ;)



    Как думаете бороться с этим мусором, господа ? Или ну его ?



    PS: Да, ведь еще DebugActiveProcess есть ...
     
  11. bogrus

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine
    Уже давно ясно, что способов определения отладчика мильён, если не использовать только один (IsDebuggerPresent, DebugActiveProcess, etc), а десятки размазанных по коду, то только так можно отшить лентяев или замедлить исследование, а боротся просто: если видишь выгоду во взломе, то тупо трассируешь\патчишь до победного :)
     
  12. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Еще один вывод - для кого "утешительный", для кого как ;)



    Если отладчик аттачится к запущенной проге (через DebugActiveProcess), то ес-но во всех хипах все чисто, NtGlobalFlag = 0 и соответственно вызов HeapCreate создает новую кучу без всяких следов отладки. Все шито-крыто, если не считать убогого байтика BeingDebugged :)



    bogrus

    > "Можно смотреть по bp 7FFDF068"

    А почему ты считаешь, что PEB лежит по фиксированному адресу (и Four-F кстати на это тоже "намекает") ?

    А вот у меня под XP SP2 частенько "проскакивали" и другие значения (и без отладчика и с отладчиком),

    типа 7FFD?000. С чего бы это ?
     
  13. bogrus

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine
    leo




    Теперь не считаю :) на XP я не игрался, а вообще я могу часто выдавать то, в чем наверняка не уверен, специально чтобы от кого-то получить подтверждение\опровержение



    p.s. помню на reng.ru читал люди знают как легко уронить отладчики 3-го кольца ... но не скажут :)) Если так, то более менее крыша пошита у сайса :)
     
  14. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    Интересная вещь получается, если сбросить Peb.NtGlobalFlag

    очень рано то приложение не загружается в отладчик,

    в частности в OllyDbg
     
  15. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    bogrus

    у тебя есть мыло нормальное?

    Есть пара вопросов =)
     
  16. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Asterix

    > "если сбросить Peb.NtGlobalFlag очень рано то приложение не загружается в отладчик"

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

    Ты перед тем как сбрасывать флаги, смотрел значение - может там при загрузке кроме 70h еще чего установлено ?
     
  17. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576




    Нет, не смотрел, пробовал на

    DBEvent.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT

    сбрасывать но там действительно в этот момент что-то не то,

    потом пробовал при получении первого сообщения о загрузке

    DLL(LOAD_DLL_DEBUG_EVENT) сбрасывать, прога(моя прога) вроде сразу выходит,

    но все-равно сбросил чуть позже, вроде нормально пашет,

    т.е. без последствий и [Peb.ProcessHeap+10h] тоже

    заодно обнулил :derisive:
     
  18. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Это я к тому, что может на ранних стадиях нужно не сбрасывать в 0, а достаточно AND делать с (not 70h).

    А с ProcessHeap+10h я не совсем понял - оно само стало нулем или ты уже установленное значение сам занулил. Если принудительно занулил, то остается еще аналогичные флаги в куче LDR, ну и хвостовые маркеры уже понатыканы:
    Код (Text):
    1. IsDebuggerPresent_byLDR_1:
    2.   mov eax,fs:[30h]
    3.   mov eax,[eax+0Ch]  ;PEB.LDR
    4.   and eax,0FFFF0000h ;базовый адрес кучи LDR
    5.   mov eax,[eax+10h]  ;<> 0 - отладка (HeapFlags <> 0)
    6.   ret
    7.  
    8. IsDebuggerPresent_byLDR_2:
    9.   mov eax,fs:[30h]
    10.   mov eax,[eax+0Ch]
    11.   movzx eax,byte[eax-3] ;флаги блока кучи
    12.   and eax, 2+4          ;<> 0 отладка (установлены флаги tail_checking=2 и free_checking=4)
    13.   ret
    14.  
    15. Кроме флагов можно проверить хвостовой маркер - будет чуть посложнее:
    16. IsDebuggerPresent_byLDR_3:
    17.   mov eax,fs:[30h]
    18.   mov eax,[eax+0Ch]
    19.   movzx eсx,byte[eax-2]   ;число служебных байт в блоке
    20.   movzx edx,word[eax-8]   ;общий размер блока в единицах 8 байт
    21.   sub eax,ecx
    22.   mov eax,[eax+edx*8]     ;хвост
    23.   xor eax,0ABABABABh      ;= 0 - отладка (хвостовой маркер)
    24.   ;sub eax,1
    25.   ;sbb eax,eax            ;<> 0 - отладка
    26.   ret
    Также можно проверять предыдущие или последующие блоки



    PS: Поправил, т.к. в первоначальном варианте с ABAB-ой я явно поспешил :dntknw:
     
  19. bogrus

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine
    Asterix мыло нормально работает, письмо получил, я просто ящик проверяю 1-2 в день



    Если обнулять NtGlobalFlag (биты 0x70) после system DbgBreakPoint то уже не помогает, а вот если до запуска (через реестр)



    [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\test.exe]

    "GlobalFlag"="0x00000000"

    "Debugger"="d:\\masm32\\ollydbg\\ollydbg.exe"



    Или сразу после первой LDR строки - тогда isdebug.exe не срабатывает, LDR опять же видимо включается только через реестр, с CREATE_PROCESS_DEBUG_EVENT я не пробовал, но он раньше чем первый OUTPUT_DEBUG_STRING_EVENT, должно было у тебя работать, LOAD_DLL_DEBUG_EVENT в w2k тоже идет раньше (в других не уверен)
     
  20. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    bogrus





    есть сомнение что нормально, мне пришло письмо "отбойник"

    о невозможности доставить письмо, ответа от тебя не

    получал, он был?







    Не стало, сам занулил :)







    Я что-то не понял у них строго определенное место

    или нужен какой-то поиск?







    А что если отловить загрузку ntdll.dll

    и там попробовать отловить первую LDR строку



    Я тупо по приходу первого сообщения LOAD_DLL_DEBUG_EVENT

    обнулял Peb.NtGlobalFlag и прога сразу выходила,

    т.е. не грузилась