eXeLab
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС ВЗЛОМ
выпущен 2 августа!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

Русский / Russian English / Английский

Сейчас на форуме: (+1 невидимый пользователь)
 · Начало · Статистика · Регистрация · Поиск · ПРАВИЛА ФОРУМА · Язык · RSS · SVN ·

 eXeL@B —› Вопросы новичков —› Можно ли по средствам винды отключить подсчет тактов, или изменить значение на фиксированное?
Посл.ответ Сообщение

Ранг: 2.2 (гость)
Статус: Участник

Создано: 4 октября 2018 08:53 New!
Цитата · Личное сообщение · #1

собственно тема в названии, если можно, то как? не подскажите?

Ранг: 377.8 (мудрец)
Статус: Участник
"Тибериумный реверсинг"

Создано: 4 октября 2018 09:15 New!
Цитата · Личное сообщение · #2

WinAPI GetTickCount / QueryPerformanceCounter??
RDTSC?

Ранг: 2.2 (гость)
Статус: Участник

Создано: 4 октября 2018 12:37 New!
Цитата · Личное сообщение · #3

ELF_7719116 пишет:
WinAPI GetTickCount / QueryPerformanceCounter??
RDTSC?

а, точно, забыл сказать, RDTSC


Ранг: 206.6 (наставник)
Статус: Участник

Создано: 4 октября 2018 12:53 New!
Цитата · Личное сообщение · #4

Если верить мануалу, эту инструкцию можно только выключить, чтоб исключение вызывала.

Ранг: 2.2 (гость)
Статус: Участник

Создано: 4 октября 2018 12:56 New!
Цитата · Личное сообщение · #5

f13nd пишет:
Если верить мануалу, эту инструкцию можно только выключить, чтоб исключение вызывала.

как выключить? не догоняю


Ранг: 206.6 (наставник)
Статус: Участник

Создано: 4 октября 2018 13:03 · Поправил: f13nd New!
Цитата · Личное сообщение · #6

Ее логика такая
Code:
  1. IF (CR4.TSD=0) OR (CPL=0) OR (CR0.PE=0)
  2. THEN
  3. EDX:EAX ← TimeStampCounter;
  4. ELSE (* CR4.TSD is 1 and CPL is 1, 2, or 3 and CR0.PE is 1 *)
  5. #GP(0)
  6. FI;

When in protected or virtual 8086 mode, the time stamp disable (TSD) flag in register CR4
restricts the use of the RDTSC instruction as follows. When the TSD flag is clear, the RDTSC
instruction can be executed at any privilege level; when the flag is set, the instruction can only
be executed at privilege level 0.

CR4 устанавливается одним из форматов инструкции mov и только в 0 кольце:
Moves the contents of a control register (CR0, CR2, CR3, or CR4) to a general-purpose register
or vice versa. The operand size for these instructions is always 32 bits, regardless of the operandsize
attribute. (See “Control Registers” in Chapter 2 of the IA-32 Intel Architecture Software
Developer’s Manual, Volume 3, for a detailed description of the flags and fields in the control
registers.) This instruction can be executed only when the current privilege level is 0.

Ранг: 2.2 (гость)
Статус: Участник

Создано: 4 октября 2018 13:26 New!
Цитата · Личное сообщение · #7

f13nd пишет:
Ее логика такая

И как применить на практике?


Ранг: 206.6 (наставник)
Статус: Участник

Создано: 4 октября 2018 13:36 New!
Цитата · Личное сообщение · #8

Aqua_regia пишет:
И как применить на практике?

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


Ранг: 582.8 (!)
Статус: Модератор
Research & Development

Создано: 4 октября 2018 14:19 New!
Цитата · Личное сообщение · #9

Проще будет хукать код, который юзает RDTSC.
Другой вариант - драйвер типа того, что выкладывал Archer в теме про Quick Unpack.
Ну и, наверняка, у Indy есть свой вариант.

Ранг: 2.2 (гость)
Статус: Участник

Создано: 4 октября 2018 14:24 New!
Цитата · Личное сообщение · #10

Jupiter пишет:
Проще будет хукать код, который юзает RDTSC.
Другой вариант - драйвер типа того, что выкладывал Archer в теме про Quick Unpack.
Ну и, наверняка, у Indy есть свой вариант.

Хорошо, поищу, спасибо за совет, если не получится, отпишу здесь


Ранг: 331.3 (мудрец)
Статус: Участник
born to be evil

Создано: 4 октября 2018 16:39 New!
Цитата · Личное сообщение · #11

Ранг: 370.2 (мудрец)
Статус: Участник

Создано: 4 октября 2018 18:47 New!
Цитата · Личное сообщение · #12

Точно отбенчить код можно в ядре. Знаю такой трюк:

Code:
  1. #define IA32_PERF_CAPABILITIES        0x345 // read-only 
  2. #define IA32_FIXED_CTR_CTRL           0x38D // Fixed-Function Performance Counter Control (R/W)
  3. #define IA32_PERF_GLOBAL_STATUS       0x38E // Global Performance Counter Status (RO)
  4. #define IA32_PERF_GLOBAL_CTRL         0x38F // Global Performance Counter Control (R/W)
  5. #define IA32_PERF_GLOBAL_OVF_CTRL     0x390 // Global Performance Counter Overflow Control (R/W)
  6. #define IA32_PERF_GLOBAL_STATUS_RESET 0x390 // Global Performance Counter Overflow Reset Control (R/W)
  7. #define IA32_PERF_GLOBAL_STATUS_SET   0x391 // Global Performance Counter Overflow Set Control (R/W)
  8.  
  9. #define MSR_PERF_FIXED_CTR0 0x309 // INST_RETIRED.ANY
  10. #define MSR_PERF_FIXED_CTR1 0x30A // CPU_CLK_UNHALTED.THREAD / CPU_CLK_UNHALTED.CORE
  11. #define MSR_PERF_FIXED_CTR2 0x30B // CPU_CLK_UNHALTED.REF_TSC
  12.  
  13. static uint64_t g_perfGlobalCtrl;
  14. static uint64_t g_perfFixedCtrl;
  15.  
  16.  
  17. // IA32_PERF_GLOBAL_CTRL bits
  18. #define EN_FIXED_CTR0 (1ull << 32) // If CPUID.0AH: EDX[4:0] > 0
  19. #define EN_FIXED_CTR1 (1ull << 33) // If CPUID.0AH: EDX[4:0] > 1
  20. #define EN_FIXED_CTR2 (1ull << 34) // If CPUID.0AH: EDX[4:0] > 2
  21.  
  22. // IA32_FIXED_CTR_CTRL bits
  23. #define EN0_OS  (1ull <<  0) // Enable Fixed Counter 0 to count while CPL = 0
  24. #define EN0_USR (1ull <<  1) // Enable Fixed Counter 0 to count while CPL > 0
  25. #define EN0_PMI (1ull <<  3) // Enable PMI when fixed counter 0 overflows
  26. #define EN1_OS  (1ull <<  4) // Enable Fixed Counter 1to count while CPL = 0
  27. #define EN1_USR (1ull <<  5) // Enable Fixed Counter 1to count while CPL > 0
  28. #define EN1_PMI (1ull <<  7) // Enable PMI when fixed counter 1 overflows
  29. #define EN2_OS  (1ull <<  8) // Enable Fixed Counter 2 to count while CPL = 0
  30. #define EN2_USR (1ull <<  9) // Enable Fixed Counter 2 to count while CPL > 0
  31. #define EN2_PMI (1ull << 11) // Enable PMI when fixed counter 2 overflows
  32.  
  33. static void print_perfs()
  34. {
  35.          uint64_t ctr0 = __readmsr(MSR_PERF_FIXED_CTR0);
  36.          uint64_t ctr1 = __readmsr(MSR_PERF_FIXED_CTR1);
  37.          uint64_t ctr2 = __readmsr(MSR_PERF_FIXED_CTR2);
  38.  
  39.          DbgMsg("-------------------------------------\n");
  40.          DbgMsg("INST_RETIRED.ANY = %08X%08X\n", (uint32_t)(ctr0 >> 32), (uint32_t)ctr0);
  41.          DbgMsg("CPU_CLK_UNHALTED.THREAD = %08X%08X\n", (uint32_t)(ctr1 >> 32), (uint32_t)ctr1);
  42.          DbgMsg("CPU_CLK_UNHALTED.REF_TSC = %08X%08X\n", (uint32_t)(ctr2 >> 32), (uint32_t)ctr2);
  43.          DbgMsg("-------------------------------------\n");
  44. }
  45.  
  46. static void enable_perf()
  47. {
  48.          print_perfs();
  49.  
  50.          g_perfGlobalCtrl = __readmsr(IA32_PERF_GLOBAL_CTRL);
  51.          g_perfFixedCtrl = __readmsr(IA32_FIXED_CTR_CTRL);
  52.  
  53.          DbgMsg("IA32_PERF_GLOBAL_CTRL = %08X%08X\n", (uint32_t)(g_perfGlobalCtrl >> 32), (uint32_t)g_perfGlobalCtrl);
  54.          DbgMsg("IA32_PERF_GLOBAL_CTRL = %08X%08X\n", (uint32_t)(g_perfFixedCtrl >> 32), (uint32_t)g_perfFixedCtrl);
  55.  
  56.          __writemsr(IA32_PERF_GLOBAL_CTRL, g_perfGlobalCtrl | (EN_FIXED_CTR0 | EN_FIXED_CTR1 | EN_FIXED_CTR2));
  57.          __writemsr(IA32_FIXED_CTR_CTRL, (EN0_OS | EN1_OS | EN2_OS)); // | (EN0_USR | EN1_USR | EN2_USR)
  58.  
  59.  
  60.          __writemsr(MSR_PERF_FIXED_CTR0, 0);
  61.          __writemsr(MSR_PERF_FIXED_CTR1, 0);
  62.          __writemsr(MSR_PERF_FIXED_CTR2, 0);
  63.          print_perfs();
  64. }
  65.  
  66. static void disable_perf()
  67. {
  68.          __writemsr(IA32_PERF_GLOBAL_STATUS_RESET, (EN_FIXED_CTR0 | EN_FIXED_CTR1 | EN_FIXED_CTR2));
  69.          __writemsr(IA32_FIXED_CTR_CTRL, g_perfFixedCtrl);
  70.          __writemsr(IA32_PERF_GLOBAL_CTRL, g_perfGlobalCtrl);
  71. }


Используем perfomance counter'ы в MSR регистрах. Их три штуки: один считает все такты, другой только такты затраченные на исполнение кода, третий - выполненные инструкции. Если брать третий счетчик и тестируемый код оборачивать в cli / sti, то результат всегда сходится цифра в цифру. Если брать значимые такты - немного плавает. Если брать все такты - скачет как мартовский заяц из-за смены режимов энергопотребления процессора.

| Сообщение посчитали полезным: mak, plutos, Aqua_regia, Katana



Ранг: 292.3 (наставник)
Статус: Участник

Создано: 1 ноября 2018 20:50 New!
Цитата · Личное сообщение · #13

Jupiter

> Ну и, наверняка, у Indy есть свой вариант.

Конечно же. Есть калибровочный источник данных, который расположен в разделяемой ядром памяти и ядро там значение апдейтит. Есть пользовательский поток выборок(DF) к данной области. Для решения задачи могут быть использованы два пути:

1. Установка ловушки на область. Дикий способ, учитывая что ловушек всего четыре.
2. Трек выборки. Адресный декодер обнаруживает выборку из целевой области и тогда в зависимости от импл. выполняется подмена данных. Могу пример показать если интересно.


Ранг: 582.8 (!)
Статус: Модератор
Research & Development

Создано: 2 ноября 2018 00:53 New!
Цитата · Личное сообщение · #14

difexacaw
А с точки зрения производительности второй вариант насколько хорош?


Ранг: 292.3 (наставник)
Статус: Участник

Создано: 3 ноября 2018 12:10 · Поправил: difexacaw New!
Цитата · Личное сообщение · #15

Jupiter

У юзер кода как таковой производительности нет. Общий профайл определяется ядром, там потоки большую часть времени спят в ожидании синхрособытий. Драйвера не панацея, нет никаких проблем отключить таймеры(tsc или сервисные) и в драйвере нужные значения возвращать. Вот только есть один нюанс, что ту же тск можно заменить на любые асм примитивы. Тоесть счётчики возвращают абсолютное время, можно сравнить два цикла на число итераций и так получится относительное время, без использования таймеров. Это просто обычно не используется.

А счётчики в USD никак по простому не изменить. У ядра нет интерфейсов, что бы там значение калибровать, так же и манипуляции с этой областью из юм невозможны. В простейшем случае нужно анмапить из км эту область и замапить туда свою, где реализовать свой таймер. Это из области извратов. Делается просто - отслеживаем выборку и подменяем значение. Не трогая ядро. Профайл зависит от имплементации.
 eXeL@B —› Вопросы новичков —› Можно ли по средствам винды отключить подсчет тактов, или изменить значение на фиксированное?

Оригинальный DVD-ROM: eXeL@B DVD !

Вы находитесь на форуме сайта EXELAB.RU
Проект ReactOS