Сейчас на форуме: UniSoft, laslo, bartolomeo (+5 невидимых)

 eXeL@B —› Программирование —› Подскажите как организовать логику отладчика
Посл.ответ Сообщение


Ранг: 529.0 (!), 110thx
Активность: 0.290.04
Статус: Участник
5KRT

Создано: 30 июня 2011 17:22 · Поправил: daFix
· Личное сообщение · #1

Думаю что много кто тут писал отладчики, поэтому мож кто подскажет. Понимаю что за много лет я
уже запарил тут всех подобными вопросами
На данный момент хардварные бряки у меня устроены слегка коряво
Code:
  1.   int __fastcall DebugThread::SingleStepHandler(int Addr)
  2.   {
  3.          if (IsMyHWBreak((int)Addr))
  4.          {
  5.                  Log2("Handled Hardware Breakpoint at " + IntToHex(Addr,8));
  6.                  RemHwBpByAddr((int)Addr);
  7.                  dwContinueStatus = DBG_CONTINUE;
  8.                  DoSingleStep();
  9.                  SetHwBp((int)Addr ,EXECUTE, 1,1);
  10.                  return 1;
  11.          }
  12.          if (SSFLAG)
  13.          {   Log("SingleStep Breakpoint at " + IntToHex(Addr,8));
  14.                  SSFLAG = 0;
  15.                  dwContinueStatus = DBG_CONTINUE;
  16.                  return 1;
  17.          }
  18.          Log("Unhandled Hardware Breakpoint at " + IntToHex(Addr,8));
  19.          dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
  20.          return 0;
  21.   }


Тоесть в обработчике делается SingleStep и бряк ставится обратно. Тоесть EIP уже будет стоять на следующей команде после бряка. Это конечно был костыль, но сейчас мне надо как-то избавится от него. Можно конечно не восстанавливать его в обработчике, но очень хотелось бы чтобы они работали как в ольке. Оно вроде и легко на первый взгляд, но пока не нашёл
подходящего решения.
Буду рад любым свежим мыслям!

ADDED:
Ну и тогда уже до кучи - выполняются ли другие потоки, если один поток встал на EXCEPTION_BREAKPOINT?

-----
Research For Food





Ранг: 2014.5 (!!!!), 1278thx
Активность: 1.340.25
Статус: Модератор
retired

Создано: 30 июня 2011 21:38 · Поправил: Модератор
· Личное сообщение · #2

1. Флаг RF.
2. Если без Debug, точно выполняются. Если с ним, судя по всему, нет.




Ранг: 337.6 (мудрец), 224thx
Активность: 0.210.1
Статус: Участник
born to be evil

Создано: 01 июля 2011 00:32 · Поправил: ajax
· Личное сообщение · #3

daFix
в сырки UGdbg погляди, мож найдешь че интересное

-----
От многой мудрости много скорби, и умножающий знание умножает печаль





Ранг: 529.0 (!), 110thx
Активность: 0.290.04
Статус: Участник
5KRT

Создано: 01 июля 2011 14:47
· Личное сообщение · #4

Archer
rf вроде какраз то что надо! Но ни как... В обработчике надо возвести 16-й бит и сказать что мы обработали исключение? Очень трудно искать информацию. Я сейчас с телефона

ajax
Спасибо, буду с компа - гляну

-----
Research For Food





Ранг: 529.0 (!), 110thx
Активность: 0.290.04
Статус: Участник
5KRT

Создано: 03 июля 2011 01:17
· Личное сообщение · #5

RF — признак маскирования ошибок отладки, при установке значения
RF=1 возможные ошибки отладки игнорируются при выполнении следую-
щей команды; используется в процессе отладки программ;


Поймали исключение сингл степ, возвели RF флаг, DBG_CONTINUE и вперёд.
Вот что происходит при запуске

Code:
  1. Process Created. Id = 00000DC4
  2. Waiting for exeption...
  3. New Process Created. Process Handle - 00000730
  4. Process Start Address - 0052E230
  5. Waiting for exeption...
  6. Load library:
  7. ntdll.dll
  8. Waiting for exeption...
  9. Load library:
  10. F:\WINDOWS\system32\kernel32.dll
  11. ....
  12. Waiting for exeption...
  13. Load library:
  14. F:\WINDOWS\system32\VERSION.dll
  15. Waiting for exeption...
  16. Exepton code: 80000003
  17. System BreakPiont at 7C90120E
  18. Waiting for exeption...
  19. Load library:
  20. F:\WINDOWS\system32\IMM32.DLL
  21. Waiting for exeption...
  22. Exepton code: 80000004
  23. Handled Hardware Breakpoint at 0052E235
  24. 00000206
  25. 00020206
  26. Waiting for exeption...
  27. Exepton code: C0000005
  28. Access violation at address 0000E235
  29. Waiting for exeption...
  30. Exepton code: C0000005
  31. Access violation at address 0000E235
  32. Waiting for exeption...
  33. Process Whas Terminated. Exit Code - C0000005


Непонятные числа 00000206 и 00020206 - это EFlag до и после возведения флага

Глянул UGdbg, много интересного можно там подглядеть, но конкретно по сабжу не нашёл
Уже бьюсь в истерике

-----
Research For Food





Ранг: 337.6 (мудрец), 224thx
Активность: 0.210.1
Статус: Участник
born to be evil

Создано: 03 июля 2011 03:20 · Поправил: ajax
· Личное сообщение · #6

http://www.delphisources.ru/pages/faq/base/use_debug_api.html ?

-----
От многой мудрости много скорби, и умножающий знание умножает печаль





Ранг: 2014.5 (!!!!), 1278thx
Активность: 1.340.25
Статус: Модератор
retired

Создано: 03 июля 2011 09:38
· Личное сообщение · #7

А ты тот вообще бит то взвёл? Ты вообще Virtual-8086 mode flag воткнул, походу. Не удивительно тогда, что посыпались такие ошибки.
З.Ы. Надо не биться в истерике, а кодес проверять и отлаживать.



Ранг: 516.1 (!), 39thx
Активность: 0.280
Статус: Участник

Создано: 04 июля 2011 08:38
· Личное сообщение · #8

#define _set_rf(x) (x.EFlags |= 0x10000)
#define _clear_rf(x) (x.EFlags &= ~0x10000)

#define _set_trap(x) (x.EFlags |= 0x100)
#define _clear_trap(x) (x.EFlags &= ~0x100)




Ранг: 681.5 (! !), 405thx
Активность: 0.420.21
Статус: Участник
ALIEN Hack Team

Создано: 04 июля 2011 12:53
· Личное сообщение · #9

Ну и тогда уже до кучи - выполняются ли другие потоки, если один поток встал на EXCEPTION_BREAKPOINT?

Нет.

-----
Stuck to the plan, always think that we would stand up, never ran.




Ранг: 62.8 (постоянный), 11thx
Активность: 0.060
Статус: Участник

Создано: 15 июля 2011 00:31
· Личное сообщение · #10

на васме есть такой товарисч - крис касперски - так он утверждал что в принципе можно купить сорцы айса от нумеги и допиливать их в свой продукт - как это сделать он не уточнил, но имхо его можно потрясти




Ранг: 529.0 (!), 110thx
Активность: 0.290.04
Статус: Участник
5KRT

Создано: 15 июля 2011 16:21
· Личное сообщение · #11

Сейчас надо закончить несколько проектов, и вернусь к написанию отладчика.

Rockphorr
Звучит адски, т.к. стрелять по мухам из пушки не целесообразно в моём случае, да и цена там будет не с двумя нулями зелёных

ARCHANGEL
Верно ли я понял, во время исключения система тормозит все потоки, а при запуске, олька стартует все потоки кроме главного через ResumeThread?

-----
Research For Food





Ранг: 2014.5 (!!!!), 1278thx
Активность: 1.340.25
Статус: Модератор
retired

Создано: 15 июля 2011 18:25
· Личное сообщение · #12

Потоки сами разморозятся, когда отладчик скажет, что исключение обработано. Ленно проверить? Ей богу, минут 30 времени максимум.




Ранг: 681.5 (! !), 405thx
Активность: 0.420.21
Статус: Участник
ALIEN Hack Team

Создано: 16 июля 2011 00:35
· Личное сообщение · #13

daFix
Именно. Вызов ContinueDebugEvent снова запустит потоки на выполнение.

-----
Stuck to the plan, always think that we would stand up, never ran.





Ранг: 529.0 (!), 110thx
Активность: 0.290.04
Статус: Участник
5KRT

Создано: 23 сентября 2011 00:01
· Личное сообщение · #14

Опять понадобился горе-отладчик и решил добить его.
Думаю что ошибка кроется в том что я просто работаю с контекстом не того потока.

if (IsMyHWBreak((int)Addr))
{
Log("Handled Hardware Breakpoint at " + IntToHex(Addr,8));
cntxt.ContextFlags = CONTEXT_FULL;
GetThreadContext( pi.hThread, &cntxt);
cntxt.EFlags = cntxt.EFlags |= 1 << 16;// 0x8000;
SetThreadContext(pi.hThread, &cntxt);
dwContinueStatus = DBG_CONTINUE;
return 1;
}

pi - это структура PROCESS_INFORMATION, полученная при создании процесса.
Если это так, тогда можно объяснить непонятные ошибки при отладке многопоточных приложений.
Значит делаем
GetThreadContext(OpenThread(DebugEvent.dwThreadId, ..., ...), &cntxt);
так?

-----
Research For Food





Ранг: 681.5 (! !), 405thx
Активность: 0.420.21
Статус: Участник
ALIEN Hack Team

Создано: 23 сентября 2011 00:05
· Личное сообщение · #15

daFix

GetThreadContext(OpenThread(DebugEvent.dwThreadId, ..., ...), &cntxt);

Такой подход жутко тормозит. OpenThread очень медленная, чтоб так её постоянно вызывать. Лучше хранить массив, по которому по известному идентификатору можно найти описатель потока.

-----
Stuck to the plan, always think that we would stand up, never ran.





Ранг: 529.0 (!), 110thx
Активность: 0.290.04
Статус: Участник
5KRT

Создано: 23 сентября 2011 00:21
· Личное сообщение · #16

ARCHANGEL
Глянул твой исходник, грамотно сделано! Переписываю свой код, возможно пропадут все глюки, которые так часто случаются при отладке, ибо странно что вообще работает

-----
Research For Food





Ранг: 529.0 (!), 110thx
Активность: 0.290.04
Статус: Участник
5KRT

Создано: 23 сентября 2011 02:48
· Личное сообщение · #17

Проблема не решилась

Сейчас нашёл одну странную странность! SetThreadContext не ставит контекст о_О

Code:
  1.      cntxt.ContextFlags = CONTEXT_ALL;
  2.      GetThreadContext(thr_hndl, &cntxt);
  3.      cntxt.EFlags = cntxt.EFlags |= 1 << 16; // 0x10000
  4.      SetThreadContext(thr_hndl, &cntxt);
  5.      GetThreadContext(thr_hndl, &cntxt);


Последний GetThreadContext показывает что EFlags ни что не изменился
Я опять в тупике

-----
Research For Food





Ранг: 990.2 (! ! !), 380thx
Активность: 0.680
Статус: Модератор
Author of DiE

Создано: 23 сентября 2011 07:51
· Личное сообщение · #18

какой еррор? юзай cntxt.ContextFlags = CONTEXT_CONTROL

-----
[nice coder and reverser]




Ранг: 47.7 (посетитель), 17thx
Активность: 0.090
Статус: Участник

Создано: 23 сентября 2011 08:21 · Поправил: bowrouco
· Личное сообщение · #19

Code:
  1. #define EFLAGS_CF_MASK        0x00000001L
  2. #define EFLAGS_PF_MASK        0x00000004L
  3. #define EFLAGS_AF_MASK        0x00000010L
  4. #define EFLAGS_ZF_MASK        0x00000040L
  5. #define EFLAGS_SF_MASK        0x00000080L
  6. #define EFLAGS_TF             0x00000100L
  7. #define EFLAGS_INTERRUPT_MASK 0x00000200L
  8. #define EFLAGS_DF_MASK        0x00000400L
  9. #define EFLAGS_OF_MASK        0x00000800L
  10. #define EFLAGS_IOPL_MASK      0x00003000L
  11. #define EFLAGS_NT             0x00004000L
  12. #define EFLAGS_RF             0x00010000L
  13. #define EFLAGS_V86_MASK       0x00020000L
  14. #define EFLAGS_ALIGN_CHECK    0x00040000L
  15. #define EFLAGS_VIF            0x00080000L
  16. #define EFLAGS_VIP            0x00100000L
  17. #define EFLAGS_ID_MASK        0x00200000L

EXIT_ALL macro:
Code:
  1.         test    dword ptr [esp+4], MODE_MASK
  2.  
  3. ; If the following branch is taken, we are returning to usermode.
  4. ; If this processor supports the SYSEXIT instruction, the branch
  5. ; will be adjusted at boot time to use the appropriate code sequence.
  6.  
  7. _KiSystemCallExitBranch:
  8.         jnz     short _KiSystemCallExit
  9.  
  10.         ; Exit to kernel mode from system call, faster than IRETD,
  11.         ; unwind the frame and branch to return address.
  12.  
  13.         pop     edx                 ; get eip
  14.         pop     ecx                 ; remove CS from stack
  15.         popfd                       ; restore eflags
  16.         jmp     edx
  17.  
  18.  
  19. _KiSystemCallExit:
  20.  
  21.         iretd                       ; return
  22.  
  23. _KiSystemCallExit2:
  24.  
  25.         test    dword ptr [esp+8], EFLAGS_TF
  26.         jne     short _KiSystemCallExit
  27.  
  28.         pop     edx                 ; pop EIP
  29.         add     esp, 4              ; Remove CS
  30.         and     dword ptr [esp], NOT EFLAGS_INTERRUPT_MASK ; Disable interrupts in the flags
  31.         popfd
  32.         pop     ecx                 ; pop ESP
  33.  
  34.         sti                         ; sysexit does not reload flags
  35.  
  36.         iSYSEXIT
  37.  
  38. _KiSystemCallExit3:
  39.  
  40.         ; AMD
  41.  
  42.         pop     ecx                 ; pop EIP
  43.         add     esp, 8
  44.         pop     esp
  45. ; mov esp, [esp+8] ; remove CS & Eflags, get ESP
  46.  
  47.         iSYSRET
  48.  
  49. endif  ;; <NoRestoreVolatiles>
  50.  
  51.         iretd                       ; return

Code:
  1. EFLAGS (CF, PF, AF, ZF, SF, TF, DF, OF, NT) <- tempEFLAGS;
  2. IF OperandSize = 32
  3.    THEN EFLAGS(RF, AC, ID) <- tempEFLAGS; FI;

Intel® 64 and IA-32 Architectures Software Developer’s Manual V.2A, 3-490



Ранг: 47.7 (посетитель), 17thx
Активность: 0.090
Статус: Участник

Создано: 23 сентября 2011 08:24
· Личное сообщение · #20

Hellspawn
> какой еррор?
STATUS_SUCCESS, очевидно ведь

| Сообщение посчитали полезным: daFix


Ранг: 793.4 (! !), 568thx
Активность: 0.740
Статус: Участник
Шаман

Создано: 23 сентября 2011 14:04
· Личное сообщение · #21

daFix если винда x64 то нужно выровнять контекст, то ли на 4 то ли на 8 байт не помню, я просто VirtualAlloc использовал, без этого на x64 работа с контекстом была невозможна, ну за исключением, когда он случайно на стеке выровненный получался.

-----
Yann Tiersen best and do not fuck





Ранг: 529.0 (!), 110thx
Активность: 0.290.04
Статус: Участник
5KRT

Создано: 23 сентября 2011 14:28 · Поправил: daFix
· Личное сообщение · #22

PE_Kill
Объявил эту структуру как локальную и использую в нескольких функциях, вызываемых в разное ремя. Так вот так косяцит только в этом месте, тоесть выравнивание тут точно не поможет. Винда XP 32 бита.

bowrouco прав, все функции возвращают TRUE.
Я уже на всякий случай и суспендил поток, потом возобновлял его. Хотя он и так вроде в суспенде лежит

bowrouco пишет:
#define EFLAGS_RF             0x00010000L

Угу, у меня так и есть

Hellspawn
Делал CONTEXT_CONTROL, разницы нету

-----
Research For Food




Ранг: 47.7 (посетитель), 17thx
Активность: 0.090
Статус: Участник

Создано: 23 сентября 2011 20:26 · Поправил: bowrouco
· Личное сообщение · #23

daFix
Если не понятно в коде, скажу напрямую. Нет смысла использовать RF. Вы не в ядре, у вас нет привилегий для управления этим флагом(приведу пример, серия из Int 0x2A(CD 2A CD 2A CD 2A CD 2A CD 2A CD 2A CD 2A CD 2A CD 2A CD 2A CD 2A CD 2A CD 2A...) не трейсится). Этот флаг вообще вам и не нужен.

Для достижения профита смотрите KeContextToKframes() и обратную её апи, либо спросите там, где вам подробно обьеснят




Ранг: 681.5 (! !), 405thx
Активность: 0.420.21
Статус: Участник
ALIEN Hack Team

Создано: 23 сентября 2011 20:44
· Личное сообщение · #24

bowrouco пишет:
Вы не в ядре, у вас нет привилегий для управления этим флагом

daFix, вспомните нашу вчерашнюю беседу в аське. И делайте как я предлагал. Всё выйдет.

серия из Int 0x2A(CD 2A CD 2A CD 2A CD 2A CD 2A CD 2A CD 2A CD 2A CD 2A CD 2A CD 2A CD 2A CD 2A...) не трейсится)

Она не не трейсится, она проскакивает, т.е. трейс идёт, но останов сработает на второй инструкции за этой конструкцией, что позволяет использовать способ с TF.

-----
Stuck to the plan, always think that we would stand up, never ran.




Ранг: 47.7 (посетитель), 17thx
Активность: 0.090
Статус: Участник

Создано: 23 сентября 2011 21:02 · Поправил: bowrouco
· Личное сообщение · #25

ARCHANGEL
Из за хардварной установки RF на iret при т-процессинге взводится RF, это отлаживает трап до следующей инструкции, а там снова вызов шлюза. Таким образом на данной последовательности трап не генерится. Выше я привёл код, который возвращает управление в юзермод.

| Сообщение посчитали полезным: ARCHANGEL


Ранг: 529.0 (!), 110thx
Активность: 0.290.04
Статус: Участник
5KRT

Создано: 23 сентября 2011 23:39
· Личное сообщение · #26

Другими словами, из Ring3 это не возможно?

-----
Research For Food




Ранг: 47.7 (посетитель), 17thx
Активность: 0.090
Статус: Участник

Создано: 24 сентября 2011 10:45 · Поправил: bowrouco
· Личное сообщение · #27

daFix
Да. Флажки корректируются при конвертациях т-фрейма в контекст и обратно. Те, на которые налаживается корректирующая маска нельзя изменить. Есчо и не нужно.

add:
Посмотрел константу для XP, в начале KeContextToKframes() есть следующая конструкция:
Code:
  1. and eax,0x3E0DD7
  2. or eax,0x200

Тоесть в символическом виде:
Code:
  1. rEFlags & (EFLAGS_MASK | EFLAGS_CF | EFLAGS_PF | EFLAGS_AF | EFLAGS_ZF | EFLAGS_SF | EFLAGS_TF | EFLAGS_DF | EFLAGS_OF | EFLAGS_VM | EFLAGS_AC | EFLAGS_VIF | EFLAGS_VIP | EFLAGS_ID)
  2.  
  3. rEFlags | EFLAGS_IF

В сурсах это макро SANITIZE_FLAGS:
Code:
  1. #define SANITIZE_FLAGS(eFlags, mode) (\
  2.     ((mode) == KernelMode ? \
  3.         ((0x00000000L) | ((eFlags) & 0x003f0fd7)) : \
  4.         ((EFLAGS_INTERRUPT_MASK) | ((eFlags) & EFLAGS_USER_SANITIZE))))


Из за RF кстате вы можите думать что из Sysenter управление возвращается на следующую за ней инструкцию. На самом деле это не так.

| Сообщение посчитали полезным: daFix


Ранг: 529.0 (!), 110thx
Активность: 0.290.04
Статус: Участник
5KRT

Создано: 24 сентября 2011 13:59 · Поправил: daFix
· Личное сообщение · #28

Беру свои слова про то что bowrouco "особо ни кому не помогает", обратно
Что-же, верну тогда всё на место, пусть будет через SingleStep сделано. От одного глюка с потоками
избавился, и этого уже достаточно пока. Спасибо всем кто откликнулся.
Тему не закрываю, может потом ещё подниму её. Всёравно ни кто тут не флудит

-----
Research For Food





Ранг: 793.4 (! !), 568thx
Активность: 0.740
Статус: Участник
Шаман

Создано: 24 сентября 2011 14:06
· Личное сообщение · #29

daFix пишет:
Беру свои слова про то что bowrouco "особо ни кому не помогает", обратно

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

-----
Yann Tiersen best and do not fuck




Ранг: 47.7 (посетитель), 17thx
Активность: 0.090
Статус: Участник

Создано: 24 сентября 2011 21:26
· Личное сообщение · #30

PE_Kill
А есчо у меня есть матчасть, написанная инде под воздействием веществ:
Code:
  1. Трап-фрейм.
  2. Это структура описывающая контекст задачи(состояние процессора). Механизмы вызова шлюзов
  3. досконально рассмотрены в манах на процессор Intel® 64 and IA-32 Architectures Software
  4. Developer’s Manual v. 2, 3. Далее описаны механимы переключения уникальные для NT.
  5. Трап-фрейм содержит регистры и дополнительную информацию необходимую для изоляции
  6. задач – предыдущий режим, указатель на голову цепочки SEH и специальный маркер. Когда
  7. вызывается вектор в IDT(хардварные прерывания и исключения) или сискал(Sysenter/Syscall)
  8. состояние задачи сохраняется в ядерном стеке в виде трап-фрейма и окружение меняется на
  9. ядерное. Рассмотрим механизм подробно.
  10. Если вектор в IDT вызывается из юзермода, то процессор переключает стек на ядерный, при этом
  11. на дне ядерного стека сохраняется пользовательский стек(предыдущие Ss:Esp). Ядерный стек
  12. описан в сегменте состояния задачи(ядерные Ss:Esp). Отсюда он и загружаются в процессор.
  13. Сегмент кода(Cs:Eip) на который передаётся управление при вызове вектора описан в
  14. дескрипторе прерывания. Так как сегмент кода меняется, то процессор сохраняет его, также и
  15. регистр флагов. Это позволяет продолжить исполнение с прерванного места. Часть стека на его
  16. дне в которой сохраняются эти регистры называется IRET-фреймом, так как инструкций IRET
  17. загружает регистры из этой структуры в процессор:
  18. ErrCode DWORD ? ; Код ошибки(селектор, флажки и пр.), передаётся как
  19. информация про исключение. Не является частью IRET-фрейма(удаляется при формировании
  20. трап-фрейма).
  21. rEip PVOID ? ; Адрес инструкции следующей за Int, адрес инструкции на
  22. которой возник фолт или адрес возврата из ловушки), это смещение в сегменте кода куда
  23. будет передано управление при исполнении Iretd.
  24. rCs DWORD ? ; +4, Селектор сегмента кода в котором вызван вектор и куда
  25. будет выполнен возврат.
  26. rEFlags DWORD ? ; +2*4, Регистр флагов на момент вызова вектора.
  27. rEsp PVOID ? ; +3*4, Транзитный стек, эти два поля определяют стек на
  28. момент вызова вектора.
  29. rSs DWORD ? ; +4*4
  30. ; Следующие 4 поля сохраняются, если вектор вызван из V8086-mode(VDM).
  31. rEs ULONG ? ; +5*4
  32. rDs ULONG ? ; +6*4
  33. rFs ULONG ? ; +7*4
  34. rGs ULONG ? ; +8*4
  35. Если вектор вызван из ядра, то стек не переключается и IRET-фрейм не будет содержать
  36. пользовательский стек. ISR выполняется на текущем стеке. Из этого следует важный вывод – при
  37. вызове векторов в ядре стек не выравнивается. Из-за этого механизм SEH не будет работать, так
  38. как диспетчер проверяет валидность цепочки фреймов, в частности она должна быть выровнена
  39. на 4 байта. Таким образом ядерный стек всегда должен быть выравнен на 4 байта, тоесть размер
  40. стековых фреймов должен быть выравнен на 4 байта(например нельзя использовать байтовые
  41. переменные).
  42. Если вектор вызван через сискал(инструкция Sysenter), то IRET-фрейм формируется программно.
  43. При этом источником ядерного стека является регистр MSR IA32_SYSENTER_ESP(DPC-стек). Это
  44. общий стек для всех потоков(транзитный), исполняемых на данном процессоре. Иначе ушло бы
  45. много времени на перезагрузку MSR при планировании. Хэндлер сискалов в начале своей работы
  46. переключает DPC-стек на потоковый, беря указатель на него из TSS. Туда адрес дна стека
  47. загружается планировщиком из описателя потока(ETHREAD.InitialStack).
  48. IRET-фрейм находится в конце трап-фрейма, так как он формируется аппаратно. Далее
  49. сохраняются RGP и сегментные регистры. Голова цепочки SEH-фреймов сохраняетсяа начало цепи
  50. завершается загрузкой маркера EXCEPTION_CHAIN_END(для исключений цепь не завершается,
  51. таким образом при рекурсивных вызовах исключений будет развёрнута SEH-цепь предыдущего
  52. хэндлера). Это позволяет изолировать цепочки SEH разных ISR(манипуляция опциональна,
  53. изоляция происходит не всегда). Формирование трап-фрейма завершается загрузкой в
  54. отладочные регистры ядерного контекста(если активен ядерный отладчик).
  55. Трап-фрейм изменяется в версиях, для NT 5.1 структура имеет следующий вид:
  56. typedef struct _KTRAP_FRAME {
  57. // Следующий два поля образуют стековый фрейм.
  58. ULONG DbgEbp; // Ebp – ссылка на следующий стековый фрейм или трап-фрейм.
  59. ULONG DbgEip; // +4, Eip – адрес возврата из ISR.
  60. ULONG DbgArgMark; // +0x8, Маркер трап-фрейма 0xBADB0D00.
  61. ULONG DbgArgPointer; // +0xC, Указатель на параметры сервиса, это ссылка на стек с
  62. параметрами при входе в сервис(в регистре Edx).
  63. // Резервные поля, используются при изменениях фрейма для восстановления стека.
  64. ULONG TempSegCs; // +0x10
  65. ULONG TempEsp; // +0x14
  66. // Отладочные регистры.
  67. ULONG Dr0; // +0x18
  68. ULONG Dr1; // +0x1C
  69. ULONG Dr2; // +0x20
  70. ULONG Dr3; // +0x24
  71. ULONG Dr6; // +0x28
  72. ULONG Dr7; // +0x2C
  73. ULONG SegGs; // +0x30
  74. ULONG SegEs; // +0x34
  75. ULONG SegDs; // +0x38
  76. ULONG Edx; // +0x3C
  77. ULONG Ecx; // +0x40
  78. ULONG Eax; // +0x44
  79. ULONG PreviousPreviousMode; // +0x48, Предыдущий режим, вычисляется на основе CPL.
  80. PEXCEPTION_REGISTRATION_RECORD ExceptionList; // +0x4C, Голова цепочки SEH-фреймов.
  81. ULONG SegFs; // +0x50
  82. ULONG Edi; // +0x54
  83. ULONG Esi; // +0x58
  84. ULONG Ebx; // 0x5C
  85. ULONG Ebp;// +0x60
  86. ULONG ErrCode; // +0x64, Информация об исключении.
  87. Пользовательский сегмент кода.
  88. // IRET-фрейм.
  89. ULONG Eip; // +0x68
  90. ULONG SegCs; // +0x6C
  91. ULONG EFlags; // +0x70, Флажки.
  92. // Пользовательский стек.
  93. ULONG HardwareEsp; // +0x74
  94. ULONG HardwareSegSs; // +0x78
  95. // Поля заполняются при переключении из V86-режима. Валидность полей определяет флажок
  96. EFLAGS_V86_MASK.
  97. ULONG V86Es; // +0x7C
  98. ULONG V86Ds; // +0x80
  99. ULONG V86Fs; // +0x84
  100. ULONG V86Gs; // +0x88
  101. } KTRAP_FRAME;
  102. Поле DbgArgMark позволяет находить и идентифицировать трап-фреймы по маркеру
  103. 0xBADB0D00. В начале трап-фрейма находится стековый фрейм, определить что он является
  104. частью трап-фрейма можно проверив маркер. При бактрейсе этот маркер позволяет определить
  105. конец SFC.
  106. Рассмотрим подробно как формируется трап-фрейм.
  107. KiTrap01:
  108. ; ISR #DB.
  109. ; Очищается TF, IF(прерывания маскируются).
  110. ; IRET-фрейм формируется аппаратно, текущий стек(Ss:Esp) загружается из TSS.
  111. ; [Esp] rEip
  112. ; [Esp + 4] rCs
  113. ; [Esp + 2*4] rEFlags
  114. ; [Esp + 3*4] rEsp
  115. ; [Esp + 4*4] rSs
  116. push 0 ; Error code.
  117. mov word ptr ss:[esp + 2],0
  118. push ebp
  119. push ebx
  120. push esi
  121. push edi
  122. push fs
  123. ; До обращения к ядерной памяти за пределами стека должны быть перезагружены
  124. селекторы.
  125. mov ebx,0x30 ; KGDT_R0_PCR
  126. mov fs,bx ; Теперь Fs адресует PCR, прямая адресация недопустима, так как адрес
  127. блока уникален для каждого процессора.
  128. mov ebx,dword ptr fs:[0] ; PCR.ExceptionList - голова цепи SEH.
  129. push ebx ; Сохраняем её в фрейме.
  130. sub esp,4 ; Предыдущий режим определим далее при необходимости.
  131. push eax
  132. push ecx
  133. push edx
  134. push ds
  135. push es
  136. push gs
  137. mov ax,0x23 ; KGDT_R3_DATA | RPL_MASK
  138. sub esp,0x30 ; Остальные поля заполним далее.
  139. ; Перезагружаем Ds и Es.
  140. mov ds,ax
  141. mov es,ax
  142. mov ebp,esp ; Теперь Ebp адресует стековый фрейм, который лежит в начале трап-
  143. фрейма(маркер позволяет идентифицировать фрейм).
  144. test dword ptr ss:[esp + 0x70],0x20000 ; EFlags & EFLAGS_V86_MASK - проверяем мод, если
  145. вызов в V86 режиме, то корректируем сегментные регистры.
  146. jnz V86_kit1_a
  147. TargetLabel:
  148. cld ; DF аппаратно не очищается.
  149. mov ebx,dword ptr ss:[ebp + 0x60] ; Ebp
  150. mov edi,dword ptr ss:[ebp + 0x68] ; Eip
  151. mov dword ptr ss:[ebp + 0xC],edx
  152. mov dword ptr ss:[ebp+8],0xBADB0D00 ; Маркер T-фрейма.
  153. mov dword ptr ss:[ebp],ebx ; DbgEbp
  154. mov dword ptr ss:[ebp + 4],edi ; DbgEip
  155. test byte ptr fs:[0x50],0xFF ; PCR.DebugActive
  156. jnz Dr_kit1_a ; Отладчик активен, загружаем ядерный Dr-контекст.
  157. ; Регистр управления Dr7 не обнуляем, это излишне так как поставить брейк на системное ап
  158. нельзя(в сервисах проверки диапазона).
  159. ExitLabel:
  160. .. ; T-фрейм сформирован, теперь прерывания могут быть размаскированы.
  161. V86_kit1_a:
  162. ; Копируем хардварно сохранённые регистры в пользовательскую часть фрейма.
  163. mov eax,dword ptr ss:[ebp + 0x84] ; V86Fs
  164. mov ebx,dword ptr ss:[ebp + 0x88] ; V86Gs
  165. mov ecx,dword ptr ss:[ebp + 0x7C] ; V86Es
  166. mov edx,dword ptr ss:[ebp + 0x80] ; V86Ds
  167. mov word ptr ss:[ebp + 0x50],ax ; Fs
  168. mov word ptr ss:[ebp + 0x30],bx ; Gs
  169. mov word ptr ss:[ebp + 0x34],cx ; Es
  170. mov word ptr ss:[ebp + 0x38],dx ; Ds
  171. jmp TargetLabel
  172. Dr_kit1_a:
  173. test dword ptr ss:[ebp + 0x70],0x20000 ; V86 ?
  174. jnz v86mode
  175. test dword ptr ss:[ebp + 0x6C],1 ; Cs & MODE_MASK
  176. je ExitLabel ; K-mode; вызов из ядра, отладочный контекст уже загружен.
  177. v86mode:
  178. ; Вызов из юзермода. Сохраняем Dr-контекст и загружаем ядерный.
  179. mov ebx,dr0
  180. mov ecx,dr1
  181. mov edi,dr2
  182. mov dword ptr ss:[ebp + 0x18],ebx ; Dr0
  183. mov dword ptr ss:[ebp + 0x1C],ecx ; Dr1
  184. mov dword ptr ss:[ebp + 0x20],edi ; Dr2
  185. mov ebx,dr3
  186. mov ecx,dr6
  187. mov edi,dr7
  188. mov dword ptr ss:[ebp + 0x24],ebx ; Dr3
  189. mov dword ptr ss:[ebp + 0x28],ecx ; Dr6
  190. xor ebx,ebx
  191. mov dword ptr ss:[ebp + 0x2C],edi ; Dr7
  192. mov dr7,ebx ; На время инициализации Dr-контекста регистр управления Dr7
  193. обнуляем.
  194. Загружаем ядерный Dr-контекст.
  195. mov edi,dword ptr fs:[0x20] ; PKPRCB
  196. mov ebx,dword ptr ds:[edi + 0x2F8] ; PRCB.ProcessorState.SpecialRegisters.SrKernelDr0
  197. mov ecx,dword ptr ds:[edi + 0x2FC] ; etc.
  198. mov dr0,ebx
  199. mov dr1,ecx
  200. mov ebx,dword ptr ds:[edi + 0x300]
  201. mov ecx,dword ptr ds:[edi + 0x304]
  202. mov dr2,ebx
  203. mov dr3,ecx
  204. mov ebx,dword ptr ds:[edi + 0x308]
  205. mov ecx,dword ptr ds:[edi + 0x30C]
  206. mov dr6,ebx
  207. mov dr7,ecx ; Загружаем регистр управления, теперь хардварные брейки работают.
  208. jmp ExitLabel
  209. Всякий вход в ядро, будь то исключения, прерывания или сискалы приводит к формированию T-
  210. фрейма. При возврате из ядра(точнее предыдущей ISR) T-фрейм загружается обратно в
  211. процессор. Восстанавливаются голова SEH-цепи, RGP, селекторы и IRET-фрейм загружается в
  212. процессор. При этом может доставляться APC. В WRK манипуляции трап-фреймами можно
  213. посмотреть в файлах kimacro.inc и trap.asm. Для формирования T-фрейма используются макросы
  214. ENTER_*, для загрузки его в процессор используется макрос EXIT_ALL.

Это не делает рихтера мной, и не попрёт вам. Но даёт ответы на вопросы тс. Вы же идёте лесом


 eXeL@B —› Программирование —› Подскажите как организовать логику отладчика
:: Ваш ответ
Жирный  Курсив  Подчеркнутый  Перечеркнутый  {mpf5}  Код  Вставить ссылку 
:s1: :s2: :s3: :s4: :s5: :s6: :s7: :s8: :s9: :s10: :s11: :s12: :s13: :s14: :s15: :s16:


Максимальный размер аттача: 500KB.
Ваш логин: german1505 » Выход » ЛС
   Для печати Для печати