Skip to content
Anti-Analysisintermediate

User Activity Sandbox Check

Malware monitors mouse movements, click counts, or browser history to determine whether it is running in a real user environment rather than an automated sandbox.

Automated sandbox environments replicate the Windows API surface but typically lack a human operator. They do not move the mouse, click on windows, or accumulate browser history. Malware exploits this by querying user-interaction metrics and staying dormant — or executing a benign code path — when the environment looks unattended.

Common signals checked:

  • Mouse cursor position: sampled at two points in time; a static cursor suggests no user.
  • Mouse click count: GetAsyncKeyState polled for VK_LBUTTON / VK_RBUTTON; fewer than N clicks in M seconds flags a sandbox.
  • Idle time: GetLastInputInfo returns the tick count of the last input event; a large idle delta is suspicious.
  • Browser artefacts: presence of Firefox/Chrome history databases, saved passwords, or installed extensions suggests genuine use.

How it works

c
#include <windows.h>

// Returns TRUE when environment looks like a sandbox (no user present)
BOOL IsSandbox_NoMouseMovement(void)
{
    POINT ptFirst, ptSecond;
    GetCursorPos(&ptFirst);
    Sleep(5000);                // Wait 5 seconds for natural movement
    GetCursorPos(&ptSecond);

    return (ptFirst.x == ptSecond.x && ptFirst.y == ptSecond.y);
}

BOOL IsSandbox_LowClickCount(UINT uMinClicks, DWORD dwWindowMs)
{
    UINT uClicks = 0;
    DWORD dwEnd = GetTickCount() + dwWindowMs;

    while (GetTickCount() < dwEnd) {
        if (GetAsyncKeyState(VK_LBUTTON) & 0x8000) uClicks++;
        if (GetAsyncKeyState(VK_RBUTTON) & 0x8000) uClicks++;
        Sleep(50);
    }
    return uClicks < uMinClicks;
}

At the instruction level the idle-time variant calls GetLastInputInfo, then subtracts the last-input tick from the current tick to measure inactivity:

asm
mov     dword ptr [rsp+lii], 8 ; LASTINPUTINFO.cbSize = sizeof(struct)
lea     rcx, [rsp+lii]         ; &LASTINPUTINFO
call    GetLastInputInfo       ; fills .dwTime with tick of last input
call    GetTickCount           ; now -> eax
sub     eax, [rsp+lii+4]       ; idleMs = now - lii.dwTime
cmp     eax, 60000             ; idle for more than 60s ?
ja      sandbox_detected       ; no recent user input -> unattended/sandbox

On Linux, malware may inspect ~/.mozilla/firefox/*/formhistory.sqlite and ~/.mozilla/firefox/*/extensions.json for evidence of real browsing activity.

Detection & analysis

During analysis:

  • Configure the sandbox to inject synthetic mouse and keyboard events at random intervals.
  • Use an interactive analysis VM rather than a fully automated sandbox for samples suspected of using this technique.
  • Patch the sleep/polling loop to exit immediately, then redirect the evasion branch.

Static / automated detection:

  • YARA / import heuristic: flag binaries importing GetCursorPos, GetAsyncKeyState, and GetLastInputInfo without a visible UI component.
  • MITRE ATT&CK: T1497.002 — Virtualization/Sandbox Evasion: User Activity Based Checks.
  • Emulation: stub GetCursorPos to return different coordinates on successive calls, and return a non-zero count from GetAsyncKeyState.
Votes

Comments(0)