Исследование SendInput

Тема в разделе "WASM.RESEARCH", создана пользователем punxer, 20 сен 2010.

  1. punxer

    punxer Андрей

    Публикаций:
    0
    Регистрация:
    16 окт 2006
    Сообщения:
    1.327
    Адрес:
    Ржев
    Y_MurRel
    есть варианты вызова этого осервиса из 3 кольца?
    или из 0?
     
  2. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    Помогло волшебное слово extern :)
    так не падает:
    Код (Text):
    1.     #define sysenter __asm _emit 0x0f __asm _emit 0x34
    2.     #define NtUserSendInput     11F6h
    3.  
    4. void KiFastSystemCall(void)
    5. {
    6. __asm{
    7.     mov edx, esp
    8.     sysenter
    9.     }
    10. }
    11.  
    12. int extern __stdcall  NtUserSendInputServiceCall (UINT Count,LPINPUT Input,int Size)
    13. {
    14.     __asm
    15.     {
    16.         mov eax, NtUserSendInput
    17.         call KiFastSystemCall
    18.     }
    19. }
    20.  
    21. ...
    Так что сервис вызывается вроде-бы корректно (насколько можно судить по отфонарному тесту на "упадёт / не упадёт") Но xmm0 всё равно портится и если дело в этом то стабильноти это "понижение уровня" не добавит.
     
  3. punxer

    punxer Андрей

    Публикаций:
    0
    Регистрация:
    16 окт 2006
    Сообщения:
    1.327
    Адрес:
    Ржев
    пока всем огромное спасибо/ надеюсь сразу не вернусьь
     
  4. punxer

    punxer Андрей

    Публикаций:
    0
    Регистрация:
    16 окт 2006
    Сообщения:
    1.327
    Адрес:
    Ржев
    Y_Mur а эмулирует?
     
  5. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    кто что эмулирует?
    я лишь убедился что сервис отрабатывает на скормленных ему данных и возвращается куда нужно а правильно ли он их обработал можно выяснить только на реальной задаче.

    PS: порча xmm0 это фича не сервиса а с++ компилятора.
     
  6. punxer

    punxer Андрей

    Публикаций:
    0
    Регистрация:
    16 окт 2006
    Сообщения:
    1.327
    Адрес:
    Ржев
    не отрабатывает как надо/ то есть ввода нет((
     
  7. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    да действительно там компилятор ещё шаманство с push ebp и т.п. добавляет потому и данные в стеке смещены.
    В общем тут геморой не в вызове сервиса (который в api переходниках вызывается лаконично и без излишеств с которыми нужно было бы бороться) а в особенностях С компиляции.
    Попробуй лучше вариант:
    Код (Text):
    1. void GenerateKeyService ( WORD vk)
    2. {
    3.     DWORD64 tmpXMM0;
    4.     __asm movq [tmpXMM0], xmm0;
    5.     KEYBDINPUT  kinpt={0};
    6.     INPUT        inpt={0};
    7.     // generate down
    8.     inpt.type=INPUT_KEYBOARD;
    9.     kinpt.wVk=vk;
    10.     kinpt.time=NULL;
    11.     kinpt.dwExtraInfo=NULL;
    12.     kinpt.wScan=NULL;
    13.     kinpt.dwFlags=NULL;
    14.     inpt.ki=kinpt;
    15.  
    16.     SendInput(1,&inpt,sizeof(inpt));
    17.     kinpt.dwFlags=KEYEVENTF_KEYUP;
    18.     SendInput(1,&inpt,sizeof(inpt));
    19.     __asm movq xmm0, [tmpXMM0];
    20.     return;
    21. }
    может всё и стабилизируется.
     
  8. punxer

    punxer Андрей

    Публикаций:
    0
    Регистрация:
    16 окт 2006
    Сообщения:
    1.327
    Адрес:
    Ржев
    Y_Mur
    простой SendInput?
     
  9. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    Я не увидел в нём ничего что можно было бы посчитать источником глюков на пути к вызову сервиса, напротив всё лаконично и гладко. Чтобы добиться такой лаконичности от альтернативной версии с использованием С компилятора нужен изрядный танец с бубном. Так что единственное что могу заподозрить как причину нестабильности это изменение xmm0, который использует компилятор для копирования структуры в стек. Имхо проще всего его просто временно сохранить.
     
  10. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Там простая модель вызова. Удобнее использовать сервисный шлюз, чем сискал. Для вызова шерез шлюз(Int 0x2e) регистр Edx должен ссылаться на параметры сервиса, причём стек значения не имеет и не используется(тоесть можно обнулить Esp и вызвать сервис). При вызове сискала(Sysenter) в Edx должна быть ссылка на аргументы, уменьшенная на два слова(-8 байт). Стек восстанавливается при возврате в значение которое было в Edx. Сискал стек восстанавливает, шлюз не восстанавливает. При вызове шлюза возврат происходит на следующую инструкцию. При вызове сискала в Ip загружается ссылка на заглушку(Ret). Тоесть очевидно что сискал должен вызываться через процедурные ветвления.
     
  11. punxer

    punxer Андрей

    Публикаций:
    0
    Регистрация:
    16 окт 2006
    Сообщения:
    1.327
    Адрес:
    Ржев
    Clerk
    можно пример на си пожалуйста
    вызова NtUserSendInput

    ну или что бы можно было вставку организовать
    я пока попробую сам, но возможно не осилю
     
  12. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    punxer
    Разобрался (и попутно прочуствавал за что Clerk не любит С :)) так работает и даже возвращает eax = 1 как и сама SendInput.
    Рекомендованное выше сохранение xmm0 советую оставить, т.к. оно попрежнему портится компиляторм при заполнении структур.
    Код (Text):
    1. int SendInputServiceCall_int2e (UINT Count, LPINPUT Input, int SizeInput)
    2. {
    3.     __asm
    4.     {
    5.         mov eax, NtUserSendInput
    6.         push SizeInput
    7.         push Input
    8.         push Count
    9.         mov edx, esp
    10.         int 0x2E
    11.         add esp, 12 ; очистка стека от временных переменных
    12.     }
    13. }
    14.  
    15. int SendInputServiceCall_sysenter (UINT Count, LPINPUT Input, int SizeInput)
    16. {
    17.     __asm
    18.     {
    19.         mov eax, NtUserSendInput
    20.         push SizeInput
    21.         push Input
    22.         push Count
    23.         push eax    ; просто заполнитель до -8
    24.         push aa
    25.         mov edx, esp
    26.         sysenter
    27. aa:
    28.         add esp, 16 ; очистка стека от временных переменных
    29.     }
    30. }
    Clerk спасибо за подсказки, но к ним нужны некоторые уточнения:
    только удаляет адрес возврата, а параметры нужно чистить самому.
    нет на входе edx=esp после занесения адреса возврата, а на выходе адрес возврата в стеке отсутствует.

    Это да, но можно его и обмануть как я и сделал :) хотя конечно я наверно нарушил работу предсказателя ret-ов в камушке, но имхо здесь это мелочь.
     
  13. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Y_Mur
    Не спорьте, стек восстанавливается(это никак не значит что очищается, это выполняется в стабе). Смотрите тут для фасткала http://files.virustech.org/indy/wrk/trap.asm:
    Код (Text):
    1. _KiFastCallEntry        proc
    2.  
    3. ;
    4. ; Sanitize the segment registers
    5. ;
    6.         mov     ecx, KGDT_R3_DATA OR RPL_MASK
    7.         push    KGDT_R0_PCR
    8.         pop     fs
    9.         mov     ds, ecx
    10.         mov     es, ecx
    11.  
    12. ;
    13. ; When we trap into the kernel via fast system call we start on the DPC stack. We need
    14. ; shift to the threads stack before enabling interrupts.
    15. ;
    16.         mov     ecx, PCR[PcTss]        ;
    17.         mov     esp, [ecx]+TssEsp0
    18.  
    19.         push    KGDT_R3_DATA OR RPL_MASK   ; Push user SS
    20.         push    edx                         ; Push ESP
    21.         pushfd
    22. Kfsc10:
    23.         push    2                           ; Sanitize eflags, clear direction, NT etc
    24.         add     edx, 8                      ; (edx) -> arguments
    И тут для шлюза http://files.virustech.org/indy/wrk/kimacro.inc.
     
  14. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Y_Mur
    Зачем же вводить ссылки и фиксапы, если можно выполнить процедурное ветвление ?
    Он не отсутствует, возврат выполняется не на следующую инструкцию, я ведь написал. Менеджер загружает в трап-фрейм ссылку на ntdll!KiFastSystemCallRet(), а она выполняет Ret. Просто вы туда брейк не ставите, а RF устанавливается, тоесть трассировочный останов генерится после исполнения Ret. Не доверяйте на столько отладчику ;)
     
  15. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    punxer
    Это запредельная наглость. Уходите на соответствующие фурумы, где вам обьяснят как манипулировать регистрами средствами скриптов.
     
  16. punxer

    punxer Андрей

    Публикаций:
    0
    Регистрация:
    16 окт 2006
    Сообщения:
    1.327
    Адрес:
    Ржев
    Не один из вариантов почему то не отжимает кнопку, как и сама SendInput, может кто нить знает в чем может быть трабла


    Код (Text):
    1. void GenerateKeyService ( WORD vk)
    2. {
    3.     KEYBDINPUT  kinpt={0};
    4.     INPUT       inpt={0};
    5.     // generate down
    6.     inpt.type=INPUT_KEYBOARD;
    7.     kinpt.wVk=vk;
    8.     kinpt.time=NULL;
    9.     kinpt.dwExtraInfo=NULL;
    10.     kinpt.wScan=NULL;
    11.     kinpt.dwFlags=NULL;
    12.     inpt.ki=kinpt;
    13.  
    14.     SendInputServiceCall_int2e(1,&inpt,sizeof(inpt));
    15.     kinpt.dwFlags=KEYEVENTF_KEYUP;
    16.     SendInputServiceCall_int2e(1,&inpt,sizeof(inpt));
    17.     return;
    18. }
     
  17. punxer

    punxer Андрей

    Публикаций:
    0
    Регистрация:
    16 окт 2006
    Сообщения:
    1.327
    Адрес:
    Ржев
    может кто нибудь это прокомментировать
     
  18. punxer

    punxer Андрей

    Публикаций:
    0
    Регистрация:
    16 окт 2006
    Сообщения:
    1.327
    Адрес:
    Ржев
    Народ реально есть проблема. Ничего не помогает в 3 кольце, даже сервис ведет себя так же как и SendInput, как именно написано в предыдущем посте, отжатия не происходит, эмулируются VK_RETURN и NUMPAD_тралала.
     
  19. punxer

    punxer Андрей

    Публикаций:
    0
    Регистрация:
    16 окт 2006
    Сообщения:
    1.327
    Адрес:
    Ржев
    присутсвия клавиатуры физической на стенде и рабочем месте не предполагается вот
    может попробовать
    Код (Text):
    1. BOOL SetKeyboardState(
    2.     LPBYTE lpKeyState
    3. );
    для обнуления клавы, хотя нужноо же отжатие имитировать и это не покатит. И после очистки тоже отжатие вроде как не катит, не может же быть нажатия без отжатия%(
     
  20. punxer

    punxer Андрей

    Публикаций:
    0
    Регистрация:
    16 окт 2006
    Сообщения:
    1.327
    Адрес:
    Ржев
    сейчас функция выглядит так
    Код (Text):
    1. void GenerateKeyService ( WORD vk)
    2. {
    3.     KEYBDINPUT  kinpt={0};
    4.     INPUT       inpt={0};
    5.  
    6.     DWORD64 tmpXMM0;
    7.     __asm movq [tmpXMM0], xmm0;
    8.     inpt.type=INPUT_KEYBOARD;
    9.     kinpt.wVk=vk;
    10.     kinpt.time=NULL;
    11.     kinpt.dwExtraInfo=NULL;
    12.     kinpt.wScan=    MapVirtualKey(vk, 0);
    13.     kinpt.dwFlags=NULL;
    14.     inpt.ki=kinpt;
    15.  
    16.     SendInputServiceCall_int2e(1,&inpt,sizeof(inpt));
    17.    
    18.     WinErrDebugOut();
    19.  
    20.     inpt.ki.dwFlags=KEYEVENTF_KEYUP;
    21.    
    22.     Sleep(1000);
    23.  
    24.     SendInputServiceCall_int2e(1,&inpt,sizeof(inpt));
    25.  
    26.     WinErrDebugOut();
    27.  
    28.     __asm movq xmm0, [tmpXMM0];
    29.     return;
    30. }