mwizard Этот флажёк может юзать обычная программа в целях защиты, пакеры это используют. Подмена обработчика в MSR это потенциальный бсодогенератор. Вот как это нужно делать http://frmn.org.ua/index.php?page=show&id=18
Это понятно, просто юзеры сами системных вызовов не делают Мне это показалось забавным. Вопросов нет. Но это драйвер. А речь о user mode.
<irony>Тогда уже для int 2e хукаем KiIntSystemCall.</irony> Это всё немного не то, KiFastSystemCall внутри выглядит просто: mov edx, esp и sysenter. Следовательно, хук будет не на sysenter, на лишь на том, что его вызывает. Никто не мешает приложениям аля Skype вызывать sysenter напрямую, не прибегая к вызову KiFastSystemCall. В общем, рабочим вариантом остается загрузка образа в память средствами ОСи, дизассемблирование кода до ближайшего call, jmp, jnz и прочего и установка на них hardware breakpoints, если есть права, либо int 3, если прав нет (только сохранить где-то заменяемую инструкцию, естественно). И так пока дизассемблер не найдет syscall.
Приложения не используют быстрый вызов, ибо в отличае от вызова сервиса через 0x2e прерывание, возврат из сервиса, вызванного инструкцией Sysenter происходит не на инструкцию следующую за ней, а на адрес определённый в разделяемой памяти(это не касается XPSP1). Это KiFastSystemCallRet. Недостаток один - не известен номер сервиса по возврату. Поэтому никто кроме MsRem'а это не юзает наверно.
Вы абсолютно правы, нужно лишь учитывать, что KiFastSystemCallRet на самом деле представляет из себя только одну инструкцию - retn, и нужен он в первую очередь для того, чтобы "вернуться" из call dword ptr [edx], из которых состоят большинство Nt* функций в ntdll. Поэтому sysenter легко вызывается минуя KiFastSystemCall кодом вида Код (Text): mySysCall proc sysenter ; мы попадаем в KiFastSystemCallRet, но стек не изменяется mySysCall endp KiFastSystemCallRet proc ret ; из стека выдавливается адрес, по которому находится "jmp somewhere" и происходит прыжок туда KiFastSystemCallRet endp push 1234h ; передаем какие-то параметры обработчику syscall-ов. push 0ABCDh call mySysCall ; в стек заносится eip следующего за этой инструкцией jmp. jmp somewhere Вот, чем не вызов syscall из кода приложения? Можно обойтись даже без mySysCall, просто добавляя в стек адрес, куда мы хотим вернуться после выхода. Я допускаю, что что-то понимаю неверно. А кто/что такое MsRem?
mwizard Во первых какой есчо сискалл, у меня процессор эту инструкцию не поддерживает. Её атлоны юзают. Во вторых код какойто бред. Обработчик инструкции Sysenter требует в регистре Edx указатель на параметры находящиеся в стеке уменьшенный на 2*4. Сам регистр Esp при вызове сервиса не используется и не имеет значения. По возврату ядро загружает в регистр Esp значение, которое было в регистре Edx перед вызовом сервиса. Соответственно этой модели и должен быть оформлен вызов.
бред - понял, исправлюсь Но тем не менее это не отрицает возможности использования sysenter вне KiFastSystemCall, верно?
Прав. Вот именно поэтому бесполезно пытаться отловить из юзермода вызов сервиса гдето внутри приложения. Это нужно в ядре делать.
Вот код кстати для перехвата KiFastSystemCall в текущем процессе: Код (Text): UsSharedData equ 7FFE0000h UsSystemCall equ 7FFE0300h UsNtMajorVersion equ 0026Ch UsNtMinorVersion equ 00270h OS_VERSION_ID_2000 equ 0 OS_VERSION_ID_XP equ 1 OS_VERSION_ID_2003 equ 2 OS_VERSION_ID_VISTA equ 3 OS_VERSION_ID_7 equ 4 $NtProtectVirtualMemory macro mov eax,ServiceId mov edx,esp Int 2Eh lea esp,[esp + 5*4] endm ;В случае успеха EFlags.ZF = 1. GET_VERSION_ID macro mov ecx,dword ptr ds:[UsSharedData + UsNtMajorVersion] mov edx,dword ptr ds:[UsSharedData + UsNtMinorVersion] cmp ecx,5 je v_5_x_ cmp ecx,6 jne err_ver_ ;6.X test edx,edx mov eax,OS_VERSION_ID_VISTA jz end_ver_ ;6.0 dec edx inc eax ;OS_VERSION_ID_7 jz end_ver_ ;6.1 jmp err_ver_ v_5_x_: xor eax,eax ;OS_VERSION_ID_2000 test edx,edx jz end_ver_ ;5.0 inc eax ;OS_VERSION_ID_XP dec edx jz end_ver_ ;5.1 inc eax ;OS_VERSION_ID_2003 dec edx jz end_ver_ err_ver_: mov eax,STATUS_NOT_IMPLEMENTED end_ver_: endm .code comment ' KiFastSystemCall: mov edx,esp ;-> jmp short ptr call_ref_ sysenter [x nop] KiFastSystemCallRet: ret ;-> nop [jmp KiFastSystemCallRetHandler] ;x5 call_ref_: jmp KiFastSystemCallHandler ;x5 (KiFastSystemCallRet + 6) ' IcpRedirectionUsSystemCall proc uses ebx esi edi Dispatcher:PVOID Local OldProtect:ULONG Local ProtectAddress:PVOID Local ProtectSize:ULONG Local ServiceId:ULONG GET_VERSION_ID jnz exit_ Call dt_ dt_: pop edx movzx edx,byte ptr [edx + eax + (offset ServiceTable - offset dt_)] assume fs:nothing mov eax,fs:[TEB.Peb] mov ServiceId,edx mov eax,PEB.Ldr[eax] mov eax,PEB_LDR_DATA.InLoadOrderModuleList.Flink[eax] mov eax,LDR_DATA_TABLE_ENTRY.InLoadOrderModuleList.Flink[eax] ;ntdll.dll mov esi,ds:[UsSystemCall] ;KiFastSystemCall mov edi,ds:[UsSystemCall + 4] ;KiFastSystemCallRet mov ecx,LDR_DATA_TABLE_ENTRY.DllBase[eax] mov edx,LDR_DATA_TABLE_ENTRY.SizeOfImage[eax] cmp esi,ecx jb not_imp_ cmp edi,ecx jb not_imp_ add ecx,edx cmp esi,ecx ja not_imp_ cmp edi,ecx ja not_imp_ cmp byte ptr [edi],0C3h ;ret jne err_stub_ cmp dword ptr [esi],340FD48Bh ;mov edx,esp/sysenter mov ebx,edi jne err_stub_ sub ebx,esi jbe err_stub_ cmp ebx,4 jb err_stub_ cmp ebx,32 ja err_stub_ add ebx,4 add edi,6 mov ProtectSize,ebx mov ProtectAddress,esi lea eax,OldProtect lea ecx,ProtectSize lea edx,ProtectAddress push eax push PAGE_EXECUTE_READWRITE push ecx push edx push NtCurrentProcess $NtProtectVirtualMemory test eax,eax mov edx,Dispatcher jnz exit_ sub edx,edi sub edx,5 mov dword ptr [edi + 1],edx mov byte ptr [edi],0E9h ;Jmp Handler mov bh,0EBh xchg bl,bh lock xchg word ptr [esi],bx lea eax,OldProtect lea ecx,ProtectSize lea edx,ProtectAddress push eax push PAGE_EXECUTE_READWRITE push ecx push edx push NtCurrentProcess $NtProtectVirtualMemory exit_: ret not_imp_: mov eax,STATUS_NOT_IMPLEMENTED jmp exit_ err_stub_: mov eax,STATUS_UNSUCCESSFUL jmp exit_ ServiceTable: BYTE 077h BYTE 089h BYTE 08Fh BYTE 0D2h BYTE 0D8h IcpRedirectionUsSystemCall endp И бинарник: Код (Text): PiEntry: db 055h, 08Bh, 0ECh, 083h, 0C4h, 0F0h, 053h, 056h, 057h, 08Bh db 00Dh, 06Ch, 002h, 0FEh, 07Fh, 08Bh, 015h, 070h, 002h, 0FEh db 07Fh, 083h, 0F9h, 005h, 074h, 014h, 083h, 0F9h, 006h, 075h db 01Dh, 085h, 0D2h, 0B8h, 003h, 000h, 000h, 000h, 074h, 019h db 04Ah, 040h, 074h, 015h, 0EBh, 00Eh, 033h, 0C0h, 085h, 0D2h db 074h, 00Dh, 040h, 04Ah, 074h, 009h, 040h, 04Ah, 074h, 005h db 0B8h, 002h, 000h, 000h, 0C0h, 00Fh, 085h, 0D0h, 000h, 000h db 000h, 0E8h, 000h, 000h, 000h, 000h, 05Ah, 00Fh, 0B6h, 094h db 010h, 0E0h, 000h, 000h, 000h, 064h, 0A1h, 030h, 000h, 000h db 000h, 089h, 055h, 0F0h, 08Bh, 040h, 00Ch, 08Bh, 040h, 00Ch db 08Bh, 000h, 08Bh, 035h, 000h, 003h, 0FEh, 07Fh, 08Bh, 03Dh db 004h, 003h, 0FEh, 07Fh, 08Bh, 048h, 018h, 08Bh, 050h, 020h db 03Bh, 0F1h, 00Fh, 082h, 09Eh, 000h, 000h, 000h, 03Bh, 0F9h db 00Fh, 082h, 096h, 000h, 000h, 000h, 003h, 0CAh, 03Bh, 0F1h db 00Fh, 087h, 08Ch, 000h, 000h, 000h, 03Bh, 0F9h, 00Fh, 087h db 084h, 000h, 000h, 000h, 080h, 03Fh, 0C3h, 00Fh, 085h, 082h db 000h, 000h, 000h, 081h, 03Eh, 08Bh, 0D4h, 00Fh, 034h, 08Bh db 0DFh, 075h, 078h, 02Bh, 0DEh, 076h, 074h, 083h, 0FBh, 004h db 072h, 06Fh, 083h, 0FBh, 020h, 077h, 06Ah, 083h, 0C3h, 004h db 083h, 0C7h, 006h, 089h, 05Dh, 0F4h, 089h, 075h, 0F8h, 08Dh db 045h, 0FCh, 08Dh, 04Dh, 0F4h, 08Dh, 055h, 0F8h, 050h, 06Ah db 040h, 051h, 052h, 06Ah, 0FFh, 08Bh, 045h, 0F0h, 08Bh, 0D4h db 0CDh, 02Eh, 08Dh, 064h, 024h, 014h, 085h, 0C0h, 08Bh, 055h db 008h, 075h, 02Eh, 02Bh, 0D7h, 083h, 0EAh, 005h, 089h, 057h db 001h, 0C6h, 007h, 0E9h, 0B7h, 0EBh, 086h, 0DFh, 0F0h, 066h db 087h, 01Eh, 08Dh, 045h, 0FCh, 08Dh, 04Dh, 0F4h, 08Dh, 055h db 0F8h, 050h, 06Ah, 040h, 051h, 052h, 06Ah, 0FFh, 08Bh, 045h db 0F0h, 08Bh, 0D4h, 0CDh, 02Eh, 08Dh, 064h, 024h, 014h, 05Fh db 05Eh, 05Bh, 0C9h, 0C2h, 004h, 000h, 0B8h, 002h, 000h, 000h db 0C0h, 0EBh, 0F2h, 0B8h, 001h, 000h, 000h, 0C0h, 0EBh, 0EBh db 077h, 089h, 08Fh, 0D2h, 0D8h
Код (Text): KiFastSystemCallRetHandler proc C test eax,eax jnz _return mov edx,dword ptr [esp] mov edx,dword ptr [edx-0Bh] ;в edx номер сервиса _return: ret KiFastSystemCallRetHandler endp Clerk, Ты же сам когда-то помогал высчитывать смешение по номеру сервиса..
Flasher Это ведь для системного стуба. В произвольном коде не известно откуда и что было загружено в Eax.