Перейти к содержанию
  • записей
    100
  • комментариев
    110
  • просмотров
    6 595

Поиск обработчика нажатий клавиш

Авторизация  
partoftheworlD

109 просмотров

Основными методами нахождения обработчика нажатий являются поиск(и заморозка потоков для проверки, просто потому, что всегда у обработчика свой поток) и поиск изменяющегося значения при нажатии на клавишу.
 

Так или иначе, оба этих способа приведут нас к тому, что игра использует DirectInput или XInput, выбор метода зависит от специфики игры и личного опыта.
Из инструментов для этого лучше всего подойдет x64dbg. Приступим к поиску с вкладки Threads и что мы видим, один из потоков был создан из dinput8.


1.png.775d02da1bf45a7b0a22021828e8ae2a.png


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

2.png.2a241f6bdbdf042e38108109ac9a7ee0.png

 

3.png.9a82f2644690b363bcd9f83af9d0568c.png

 

Пробежав быстро по стеку вызовов, находим интересную апишку MapVirtualKeyA выйдя из метода, которая переводит скан-код в код виртуальной клавиши.

 

4.thumb.png.58fa681bfab86eabedae249f19790785.png

 

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

На этом этапе уже будет удобней исследовать код в IDA/GHIDRA, поэтому перейдем к ним, оставив отладчик подключенным к процессу. Немного восстановлю код для наглядности:

 

Спойлер

void __fastcall KeyHandler(BSWin32KeyboardDevice *BSWin32KeyboardDevice, float a2)
{
  // [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]

  curState_1 = &BSWin32KeyboardDevice->curState;
  v3 = 2i64;
  max_index = 10;
  p_prevState = &BSWin32KeyboardDevice->prevState;
  p_curState = &BSWin32KeyboardDevice->curState;
  do
  {
    *p_prevState = *p_curState;
    p_prevState[1] = p_curState[1];
    p_prevState[2] = p_curState[2];
    p_prevState[3] = p_curState[3];
    p_prevState[4] = p_curState[4];
    p_prevState[5] = p_curState[5];
    p_prevState[6] = p_curState[6];
    p_prevState += 8;
    v8 = p_curState[7];
    p_curState += 8;
    *(p_prevState - 1) = v8;
    --v3;
  }
  while ( v3 );
  sub_7FF6C8FA66D0(
    qword_7FF6CB2B7158,
    BSWin32KeyboardDevice->IWrapKeyboardDevice8,
    &max_index,
    (__int64)BSWin32KeyboardDevice->array_of_keys);
  v9 = 0;
  idx = 0;
  if ( max_index )
  {
    do
    {
      wScanCode = *(unsigned int *)&BSWin32KeyboardDevice->array_of_keys[0x18 * idx];
      v12 = *(_DWORD *)&BSWin32KeyboardDevice->gap7C[0x18 * idx];
      wVirtKey = MapVirtualKeyA(*(_DWORD *)&BSWin32KeyboardDevice->array_of_keys[0x18 * idx], MAPVK_VSC_TO_VK);
      *((_BYTE *)&BSWin32KeyboardDevice->prevState + wScanCode) = *(&BSWin32KeyboardDevice->curState + wScanCode);
      *(&BSWin32KeyboardDevice->curState + wScanCode) = v12 & 0x80;
      if ( (_DWORD)wScanCode != 15
        || !BSWin32KeyboardDevice->byte2A0
        && !BSWin32KeyboardDevice->byte320
        && !BSWin32KeyboardDevice->byte292
        && !BSWin32KeyboardDevice->byte29E )
      {
        Settings(
          BSWin32KeyboardDevice,
          wScanCode,
          a2,
          *((_BYTE *)&BSWin32KeyboardDevice->prevState + wScanCode) != 0,
          (v12 & 0x80) != 0);
      }
      if ( v12 )
      {
        wScanCodeState = GetKeyInfoState((__int64)BSWin32KeyboardDevice, wScanCode);
        if ( wScanCodeState )
          goto LABEL_31;
        if ( wVirtKey )
        {
          v15 = BSWin32KeyboardDevice->byte292 >> 7;
          v16 = BSWin32KeyboardDevice->byte29E >> 7;
          pwszBuff = 0;
          if ( BSWin32KeyboardDevice->byte2A2 & 0x80 && !(BSWin32KeyboardDevice->byte1A2 & 0x80) )
            BSWin32KeyboardDevice->byte368 = BSWin32KeyboardDevice->byte368 == 0;
          if ( v16 || (v17 = v15 == 0, v18 = 1, !v17) )
            v18 = 0;
          v19 = 0;
          if ( v18 != (BSWin32KeyboardDevice->byte368 == 0) )
            v19 = 0x80u;
          byte_7FF6CB2FC700 = v19;
          if ( ToUnicode(wVirtKey, wScanCode, &KeyState, (LPWSTR)&pwszBuff, 2, 0) == 1 )
          {
            wScanCodeState = (unsigned __int16)pwszBuff;
            if ( (_WORD)pwszBuff )
LABEL_31:
              sub_7FF6C8FA69B0(qword_7FF6CB2E0B28, wScanCodeState);
          }
        }
      }
      ++idx;
    }
    while ( idx < max_index );
  }
  do
  {
    if ( *(curState_1 - 256) )
    {
      if ( *curState_1 )
        Settings(BSWin32KeyboardDevice, v9, a2, 1, 1);
    }
    ++v9;
    ++curState_1;
  }
  while ( v9 < 256 );
}

 

 

 

 

  • Плюс 2
Авторизация  


1 Комментарий


Рекомендуемые комментарии

Обновление:

BSWin32KeyboardDevice->gap80[wScanCode + 0xE8] = BSWin32KeyboardDevice->gap1A3[wScanCode + 0xC5];
BSWin32KeyboardDevice->gap1A3[wScanCode + 0xC5] = v12 & 0x80;

В коде были 2 строки, они отвечают за структуры, одна из которых обрабатывает состояние клавиш, а в другую пишется это состояние и после копируется в первую структуру для дальнейшей обработки. Для примера возьмем клавишу W её скан код это 11. Дальше пишем во вторую структуру состояние клавиши W (base + 11 + 268) = 0x80 и гг начинает двигаться.

 

 

  • Плюс 2

Поделиться этим комментарием


Ссылка на комментарий

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти
×

Важная информация

Находясь на нашем сайте, Вы автоматически соглашаетесь соблюдать наши Условия использования.