From 324f115476ea9f75cb846c7acf9627e403ece035 Mon Sep 17 00:00:00 2001 From: Robert Fisk Date: Fri, 5 Jan 2018 15:19:57 +1300 Subject: [PATCH] Implement mouse acceleration pulse timing. Doesn't work on realistic inputs. --- Downstream/.settings/language.settings.xml | 4 +- Upstream/.settings/language.settings.xml | 4 +- Upstream/Inc/build_config.h | 8 +- Upstream/Inc/upstream_hid_botdetect.h | 6 - Upstream/Src/upstream_hid_botdetect.c | 159 +++++++++++++++------ 5 files changed, 126 insertions(+), 55 deletions(-) diff --git a/Downstream/.settings/language.settings.xml b/Downstream/.settings/language.settings.xml index 0cebdf1..0b0ced0 100644 --- a/Downstream/.settings/language.settings.xml +++ b/Downstream/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + @@ -16,7 +16,7 @@ - + diff --git a/Upstream/.settings/language.settings.xml b/Upstream/.settings/language.settings.xml index 063351b..9b2b3ac 100755 --- a/Upstream/.settings/language.settings.xml +++ b/Upstream/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + @@ -16,7 +16,7 @@ - + diff --git a/Upstream/Inc/build_config.h b/Upstream/Inc/build_config.h index 471c778..b1a575b 100644 --- a/Upstream/Inc/build_config.h +++ b/Upstream/Inc/build_config.h @@ -27,7 +27,7 @@ #ifdef CONFIG_KEYBOARD_BOT_DETECT_ENABLED //----------------------------------------------------------- //Adjust this threshold first to tune keyboard bot detection. Lower values = more sensitive - #define KEYBOARD_BOTDETECT_TEMPORARY_LOCKOUT_BIN_THRESHOLD 4 + #define KEYBOARD_BOTDETECT_LOCKOUT_BIN_THRESHOLD 4 //----------------------------------------------------------- #define KEYBOARD_BOTDETECT_FAST_BIN_WIDTH_MS 10 //10ms per bin @@ -43,14 +43,18 @@ #ifdef CONFIG_MOUSE_BOT_DETECT_ENABLED //----------------------------------------------------------- //Adjust this threshold first to tune mouse bot detection. Lower values = more sensitive - #define MOUSE_BOTDETECT_TEMPORARY_LOCKOUT_VELOCITY_THRESHOLD 4 + #define MOUSE_BOTDETECT_LOCKOUT_CONSTANT_ACCEL_THRESHOLD 20 + #define MOUSE_BOTDETECT_LOCKOUT_MINIMUM_ACCEL_TIME_MS 200 //----------------------------------------------------------- + #define MOUSE_BOTDETECT_VELOCITY_MULTIPLIER 10 #define MOUSE_BOTDETECT_VELOCITY_HISTORY_SIZE 12 #define MOUSE_BOTDETECT_VELOCITY_MATCH_BASE 256 #define MOUSE_BOTDETECT_VELOCITY_MATCH_ERROR 6 #define MOUSE_BOTDETECT_MOVE_DELAY_LIMIT 5 + #define MOUSE_BOTDETECT_ACCEL_EVENT_THRESHOLD (4 * MOUSE_BOTDETECT_VELOCITY_MULTIPLIER) + #endif //Configuration common to all bot detectors diff --git a/Upstream/Inc/upstream_hid_botdetect.h b/Upstream/Inc/upstream_hid_botdetect.h index a37feb2..a5cd20f 100644 --- a/Upstream/Inc/upstream_hid_botdetect.h +++ b/Upstream/Inc/upstream_hid_botdetect.h @@ -38,12 +38,6 @@ typedef struct } KeyTimerLogTypeDef; -typedef struct -{ - uint8_t moveDelay; - uint16_t velocity; -} -MouseVelocityHistoryTypeDef; void Upstream_HID_BotDetect_Systick(void); diff --git a/Upstream/Src/upstream_hid_botdetect.c b/Upstream/Src/upstream_hid_botdetect.c index b523e63..173085c 100644 --- a/Upstream/Src/upstream_hid_botdetect.c +++ b/Upstream/Src/upstream_hid_botdetect.c @@ -55,14 +55,25 @@ volatile LockoutStateTypeDef LockoutState = LOCKOUT_STATE_INACTIVE; //Variables specific to mouse bot detection: #if defined (CONFIG_MOUSE_ENABLED) && defined (CONFIG_MOUSE_BOT_DETECT_ENABLED) - uint32_t LastMouseMoveTime = 0; - MouseVelocityHistoryTypeDef MouseVelocityHistory[MOUSE_BOTDETECT_VELOCITY_HISTORY_SIZE] = {0}; + uint32_t LastMouseMoveTime = 0; + + //Acceleration event timing stuff + uint32_t AccelerationEventStartTime; + uint32_t PreviousRawVelocity = 0; + int8_t AccelerationEventPolarityActive = 0; + + //Constant acceleration detection stuff + uint16_t MouseVelocityHistory[MOUSE_BOTDETECT_VELOCITY_HISTORY_SIZE] = {0}; + int32_t PreviousSmoothedAcceleration = 0; + uint8_t ConstantAccelerationCounter = 0; + - uint8_t SameVelocityCounter = 0; //Debug: -// uint8_t SameVelocityCounterMax = 0; + uint8_t ConstantAccelerationCounterMax = 0; - static void Upstream_HID_BotDetectMouse_DoLockout(void); + static void Upstream_HID_BotDetectMouse_AccelEventStart(int32_t rawAcceleration); + static void Upstream_HID_BotDetectMouse_AccelEventStop(uint32_t accelStopTime); + static void Upstream_HID_BotDetectMouse_DoLockout(void); #endif @@ -132,8 +143,8 @@ void Upstream_HID_BotDetectKeyboard(uint8_t* keyboardInData) //Check for evidence of bot typing for (i = 0; i < KEYBOARD_BOTDETECT_FAST_BIN_COUNT; i++) { - if ((KeyDelayFastBinArray[i] > KEYBOARD_BOTDETECT_TEMPORARY_LOCKOUT_BIN_THRESHOLD) || - (KeyDowntimeFastBinArray[i] > KEYBOARD_BOTDETECT_TEMPORARY_LOCKOUT_BIN_THRESHOLD)) + if ((KeyDelayFastBinArray[i] > KEYBOARD_BOTDETECT_LOCKOUT_BIN_THRESHOLD) || + (KeyDowntimeFastBinArray[i] > KEYBOARD_BOTDETECT_LOCKOUT_BIN_THRESHOLD)) { Upstream_HID_BotDetectKeyboard_DoLockout(); break; @@ -144,8 +155,8 @@ void Upstream_HID_BotDetectKeyboard(uint8_t* keyboardInData) } for (i = 0; i < KEYBOARD_BOTDETECT_SLOW_BIN_COUNT; i++) { - if ((KeyDelaySlowBinArray[i] > KEYBOARD_BOTDETECT_TEMPORARY_LOCKOUT_BIN_THRESHOLD) || - (KeyDowntimeSlowBinArray[i] > KEYBOARD_BOTDETECT_TEMPORARY_LOCKOUT_BIN_THRESHOLD)) + if ((KeyDelaySlowBinArray[i] > KEYBOARD_BOTDETECT_LOCKOUT_BIN_THRESHOLD) || + (KeyDowntimeSlowBinArray[i] > KEYBOARD_BOTDETECT_LOCKOUT_BIN_THRESHOLD)) { Upstream_HID_BotDetectKeyboard_DoLockout(); break; @@ -294,7 +305,6 @@ static void Upstream_HID_BotDetectKeyboard_KeyDown(uint8_t keyCode) - static void Upstream_HID_BotDetectKeyboard_KeyUp(uint8_t keyCode) { uint32_t i; @@ -383,67 +393,104 @@ void Upstream_HID_BotDetectMouse(uint8_t* mouseInData) uint32_t now = HAL_GetTick(); uint32_t moveDelay; uint32_t velocity; - uint32_t newAverageVelocity; - uint32_t newAverageVelocityMatchError; - uint32_t oldAverageVelocity; - int8_t mouseX; - int8_t mouseY; + int8_t mouseX; + int8_t mouseY; + + //Acceleration event timing stuff + int32_t rawAcceleration; + + //Constant acceleration detection stuff + uint32_t newSmoothedVelocity; + uint32_t oldSmoothedVelocity; + int32_t newSmoothedAcceleration; + int32_t smoothedAccelerationMatchError; + mouseX = mouseInData[1]; mouseY = mouseInData[2]; velocity = (sqrtf(((int32_t)mouseX * mouseX) + - ((int32_t)mouseY * mouseY))) * 10; //Multiply floating-point sqrt result to avoid integer rounding errors + ((int32_t)mouseY * mouseY))) * MOUSE_BOTDETECT_VELOCITY_MULTIPLIER; //Multiply floating-point sqrt result to avoid integer rounding errors + moveDelay = ((int32_t)(now - LastMouseMoveTime) + (HID_FS_BINTERVAL / 2)) / HID_FS_BINTERVAL; //Number of poll intervals since last movement - moveDelay = ((now - LastMouseMoveTime) + (HID_FS_BINTERVAL / 2)) / HID_FS_BINTERVAL; //Number of poll intervals since last movement - if (moveDelay > MOUSE_BOTDETECT_MOVE_DELAY_LIMIT) moveDelay = MOUSE_BOTDETECT_MOVE_DELAY_LIMIT; - if ((velocity != 0) && (moveDelay != 0)) + //Look for unrealistically short acceleration events + if (moveDelay > MOUSE_BOTDETECT_MOVE_DELAY_LIMIT) //Did the mouse stop moving? + { + moveDelay = MOUSE_BOTDETECT_MOVE_DELAY_LIMIT; + PreviousRawVelocity = 0; + if (AccelerationEventPolarityActive != 0) + { + Upstream_HID_BotDetectMouse_AccelEventStop(LastMouseMoveTime); + } + } + + rawAcceleration = velocity - PreviousRawVelocity; + PreviousRawVelocity = velocity; + velocity = velocity / moveDelay; + if (AccelerationEventPolarityActive == 0) + { + if (abs(rawAcceleration) > MOUSE_BOTDETECT_ACCEL_EVENT_THRESHOLD) + { + Upstream_HID_BotDetectMouse_AccelEventStart(rawAcceleration); + } + } + else + { + //Acceleration event in progress + if (((AccelerationEventPolarityActive == 1) && (rawAcceleration < -MOUSE_BOTDETECT_ACCEL_EVENT_THRESHOLD)) || + ((AccelerationEventPolarityActive == -1) && (rawAcceleration > MOUSE_BOTDETECT_ACCEL_EVENT_THRESHOLD))) + { + Upstream_HID_BotDetectMouse_AccelEventStop(now); //Polarity has changed, so stop and re-start a new event + Upstream_HID_BotDetectMouse_AccelEventStart(rawAcceleration); + } + } + + + //Look for periods of constant acceleration + if (velocity != 0) { LastMouseMoveTime = now; for (i = (MOUSE_BOTDETECT_VELOCITY_HISTORY_SIZE - 1); i > 0; i--) //Shuffle down history data { MouseVelocityHistory[i] = MouseVelocityHistory[i - 1]; } - MouseVelocityHistory[0].moveDelay = moveDelay; //Store latest data at head - MouseVelocityHistory[0].velocity = velocity; + MouseVelocityHistory[0] = velocity; //Store latest data at head - if (MouseVelocityHistory[(MOUSE_BOTDETECT_VELOCITY_HISTORY_SIZE - 1)].velocity > 0) + if (MouseVelocityHistory[(MOUSE_BOTDETECT_VELOCITY_HISTORY_SIZE - 1)] > 0) { - moveDelay = 0; //Calculate new and old average velocities - velocity = 0; + velocity = 0; //Calculate new and old average velocities for (i = 0; i < (MOUSE_BOTDETECT_VELOCITY_HISTORY_SIZE / 2); i++) { - moveDelay += MouseVelocityHistory[i].moveDelay; - velocity += MouseVelocityHistory[i].velocity; + velocity += MouseVelocityHistory[i]; } - newAverageVelocity = (velocity * 8) / moveDelay; //Multiply velocity up to avoid rounding errors on divide + newSmoothedVelocity = (velocity * 8) / (MOUSE_BOTDETECT_VELOCITY_HISTORY_SIZE / 2); //Multiply velocity up to avoid rounding errors on divide - moveDelay = 0; velocity = 0; for (i = (MOUSE_BOTDETECT_VELOCITY_HISTORY_SIZE / 2); i < MOUSE_BOTDETECT_VELOCITY_HISTORY_SIZE; i++) { - moveDelay += MouseVelocityHistory[i].moveDelay; - velocity += MouseVelocityHistory[i].velocity; + velocity += MouseVelocityHistory[i]; } - oldAverageVelocity = (velocity * 8) / moveDelay; //Multiply velocity up to avoid rounding errors on divide + oldSmoothedVelocity = (velocity * 8) / (MOUSE_BOTDETECT_VELOCITY_HISTORY_SIZE / 2); //Multiply velocity up to avoid rounding errors on divide - newAverageVelocityMatchError = (newAverageVelocity * MOUSE_BOTDETECT_VELOCITY_MATCH_ERROR) / MOUSE_BOTDETECT_VELOCITY_MATCH_BASE; - if (((newAverageVelocity + newAverageVelocityMatchError) >= oldAverageVelocity) && - ((newAverageVelocity - newAverageVelocityMatchError) <= oldAverageVelocity)) + newSmoothedAcceleration = newSmoothedVelocity - oldSmoothedVelocity; + smoothedAccelerationMatchError = (oldSmoothedVelocity * MOUSE_BOTDETECT_VELOCITY_MATCH_ERROR) / MOUSE_BOTDETECT_VELOCITY_MATCH_BASE; + if (((PreviousSmoothedAcceleration + smoothedAccelerationMatchError) >= newSmoothedAcceleration) && + ((PreviousSmoothedAcceleration - smoothedAccelerationMatchError) <= newSmoothedAcceleration)) { - SameVelocityCounter++; - if (SameVelocityCounter > MOUSE_BOTDETECT_TEMPORARY_LOCKOUT_VELOCITY_THRESHOLD) - { - Upstream_HID_BotDetectMouse_DoLockout(); - } + ConstantAccelerationCounter++; +// if (ConstantAccelerationCounter > MOUSE_BOTDETECT_TEMPORARY_LOCKOUT_VELOCITY_THRESHOLD) +// { +// Upstream_HID_BotDetectMouse_DoLockout(); +// } //Debug: -// if (SameVelocityCounter > SameVelocityCounterMax) SameVelocityCounterMax = SameVelocityCounter; + if (ConstantAccelerationCounter > ConstantAccelerationCounterMax) ConstantAccelerationCounterMax = ConstantAccelerationCounter; } else { - SameVelocityCounter = 0; + ConstantAccelerationCounter = 0; } + PreviousSmoothedAcceleration = newSmoothedAcceleration; } } else @@ -464,6 +511,32 @@ void Upstream_HID_BotDetectMouse(uint8_t* mouseInData) } +static void Upstream_HID_BotDetectMouse_AccelEventStart(int32_t rawAcceleration) +{ + AccelerationEventStartTime = HAL_GetTick(); + if (rawAcceleration > 0) + { + AccelerationEventPolarityActive = 1; + } + else + { + AccelerationEventPolarityActive = -1; + } +} + + + +static void Upstream_HID_BotDetectMouse_AccelEventStop(uint32_t accelStopTime) +{ + if ((accelStopTime - AccelerationEventStartTime) < MOUSE_BOTDETECT_LOCKOUT_MINIMUM_ACCEL_TIME_MS) + { + Upstream_HID_BotDetectMouse_DoLockout(); + } + AccelerationEventPolarityActive = 0; +} + + + static void Upstream_HID_BotDetectMouse_DoLockout(void) { uint32_t i; @@ -481,9 +554,9 @@ static void Upstream_HID_BotDetectMouse_DoLockout(void) //Otherwise, reset counters and give warning for (i = 0; i < MOUSE_BOTDETECT_VELOCITY_HISTORY_SIZE; i++) { - MouseVelocityHistory[i].velocity = 0; + MouseVelocityHistory[i] = 0; } - SameVelocityCounter = 0; + ConstantAccelerationCounter = 0; TemporaryLockoutTimeMs = 0; LockoutState = LOCKOUT_STATE_TEMPORARY_ACTIVE;