mirror of
https://github.com/CheckPointSW/InviZzzible
synced 2026-06-08 10:35:43 +00:00
626 lines
18 KiB
C++
626 lines
18 KiB
C++
#include "generic.h"
|
|
|
|
namespace SandboxEvasion {
|
|
|
|
VEDetection* Generic::create_instance(const json_tiny &j) {
|
|
return new Generic(j);
|
|
}
|
|
|
|
void Generic::CheckAllCustom() {
|
|
bool d;
|
|
std::pair<std::string, std::string> report;
|
|
std::string ce_name;
|
|
|
|
ce_name = Config::cgen2s[Config::ConfigGeneric::SLEEP_DUMMY];
|
|
if (IsEnabled(ce_name, conf.get<std::string>(ce_name + std::string(".") + Config::cg2s[Config::ConfigGlobal::ENABLED], ""))) {
|
|
d = CheckSleepDummyPatch();
|
|
report = GenerateReportEntry(ce_name, json_tiny(conf.get(ce_name, pt::ptree())), d);
|
|
log_message(LogMessageLevel::INFO, module_name, report.second, d ? RED : GREEN);
|
|
}
|
|
|
|
ce_name = Config::cgen2s[Config::ConfigGeneric::PERFORMANCE_COUNTER];
|
|
if (IsEnabled(ce_name, conf.get<std::string>(ce_name + std::string(".") + Config::cg2s[Config::ConfigGlobal::ENABLED], ""))) {
|
|
d = CheckPerformanceCounter();
|
|
report = GenerateReportEntry(ce_name, json_tiny(conf.get(ce_name, pt::ptree())), d);
|
|
log_message(LogMessageLevel::INFO, module_name, report.second, d ? RED : GREEN);
|
|
}
|
|
|
|
ce_name = Config::cgen2s[Config::ConfigGeneric::DISK_SIZE];
|
|
if (IsEnabled(ce_name, conf.get<std::string>(ce_name + std::string(".") + Config::cg2s[Config::ConfigGlobal::ENABLED], ""))) {
|
|
d = CheckDiskSize();
|
|
report = GenerateReportEntry(ce_name, json_tiny(conf.get(ce_name, pt::ptree())), d);
|
|
log_message(LogMessageLevel::INFO, module_name, report.second, d ? RED : GREEN);
|
|
}
|
|
|
|
ce_name = Config::cgen2s[Config::ConfigGeneric::DRIVE_SIZE];
|
|
if (IsEnabled(ce_name, conf.get<std::string>(ce_name + std::string(".") + Config::cg2s[Config::ConfigGlobal::ENABLED], ""))) {
|
|
d = CheckDriveSize();
|
|
report = GenerateReportEntry(ce_name, json_tiny(conf.get(ce_name, pt::ptree())), d);
|
|
log_message(LogMessageLevel::INFO, module_name, report.second, d ? RED : GREEN);
|
|
}
|
|
|
|
ce_name = Config::cgen2s[Config::ConfigGeneric::DEVICE_NPF_NDIS];
|
|
if (IsEnabled(ce_name, conf.get<std::string>(ce_name + std::string(".") + Config::cg2s[Config::ConfigGlobal::ENABLED], ""))) {
|
|
d = CheckNDISFile();
|
|
report = GenerateReportEntry(ce_name, json_tiny(conf.get(ce_name, pt::ptree())), d);
|
|
log_message(LogMessageLevel::INFO, module_name, report.second, d ? RED : GREEN);
|
|
}
|
|
|
|
ce_name = Config::cgen2s[Config::ConfigGeneric::MOUSE_ACTIVE];
|
|
if (IsEnabled(ce_name, conf.get<std::string>(ce_name + std::string(".") + Config::cg2s[Config::ConfigGlobal::ENABLED], ""))) {
|
|
d = CheckMouseActive();
|
|
report = GenerateReportEntry(ce_name, json_tiny(conf.get(ce_name, pt::ptree())), d);
|
|
log_message(LogMessageLevel::INFO, module_name, report.second, d ? RED : GREEN);
|
|
}
|
|
|
|
ce_name = Config::cgen2s[Config::ConfigGeneric::RAM];
|
|
if (IsEnabled(ce_name, conf.get<std::string>(ce_name + std::string(".") + Config::cg2s[Config::ConfigGlobal::ENABLED], ""))) {
|
|
d = CheckRAM();
|
|
report = GenerateReportEntry(ce_name, json_tiny(conf.get(ce_name, pt::ptree())), d);
|
|
log_message(LogMessageLevel::INFO, module_name, report.second, d ? RED : GREEN);
|
|
}
|
|
|
|
ce_name = Config::cgen2s[Config::ConfigGeneric::BIG_RAM_ALLOC];
|
|
if (IsEnabled(ce_name, conf.get<std::string>(ce_name + "." + Config::cg2s[Config::ConfigGlobal::ENABLED], ""))) {
|
|
d = CheckBigRAMAllocate();
|
|
report = GenerateReportEntry(ce_name, json_tiny(conf.get(ce_name, pt::ptree())), d);
|
|
log_message(LogMessageLevel::INFO, module_name, report.second, d ? RED : GREEN);
|
|
}
|
|
|
|
ce_name = Config::cgen2s[Config::ConfigGeneric::SYSTEM_UPTIME];
|
|
if (IsEnabled(ce_name, conf.get<std::string>(ce_name + std::string(".") + Config::cg2s[Config::ConfigGlobal::ENABLED], ""))) {
|
|
d = CheckSystemUptime();
|
|
report = GenerateReportEntry(ce_name, json_tiny(conf.get(ce_name, pt::ptree())), d);
|
|
log_message(LogMessageLevel::INFO, module_name, report.second, d ? RED : GREEN);
|
|
}
|
|
|
|
ce_name = Config::cgen2s[Config::ConfigGeneric::PROCESSORS_COUNT];
|
|
if (IsEnabled(ce_name, conf.get<std::string>(ce_name + std::string(".") + Config::cg2s[Config::ConfigGlobal::ENABLED], ""))) {
|
|
d = CheckNumberOfProcessors();
|
|
report = GenerateReportEntry(ce_name, json_tiny(conf.get(ce_name, pt::ptree())), d);
|
|
log_message(LogMessageLevel::INFO, module_name, report.second, d ? RED : GREEN);
|
|
}
|
|
|
|
ce_name = Config::cgen2s[Config::ConfigGeneric::DNS_RESPONSE];
|
|
if (IsEnabled(ce_name, conf.get<std::string>(ce_name + std::string(".") + Config::cg2s[Config::ConfigGlobal::ENABLED], ""))) {
|
|
d = CheckDNSResponse();
|
|
report = GenerateReportEntry(ce_name, json_tiny(conf.get(ce_name, pt::ptree())), d);
|
|
log_message(LogMessageLevel::INFO, module_name, report.second, d ? RED : GREEN);
|
|
}
|
|
|
|
ce_name = Config::cgen2s[Config::ConfigGeneric::TIME_TAMPERING];
|
|
if (IsEnabled(ce_name, conf.get<std::string>(ce_name + std::string(".") + Config::cg2s[Config::ConfigGlobal::ENABLED], ""))) {
|
|
d = CheckTimeTampering(ProcessWorkingMode::MASTER);
|
|
report = GenerateReportEntry(ce_name, json_tiny(conf.get(ce_name, pt::ptree())), d);
|
|
log_message(LogMessageLevel::INFO, module_name, report.second, d ? RED : GREEN);
|
|
}
|
|
|
|
ce_name = Config::cgen2s[Config::ConfigGeneric::MOUSE_RAW_ACTIVE];
|
|
if (IsEnabled(ce_name, conf.get<std::string>(ce_name + std::string(".") + Config::cg2s[Config::ConfigGlobal::ENABLED], ""))) {
|
|
d = CheckMouseRawActive(ProcessWorkingMode::MASTER);
|
|
report = GenerateReportEntry(ce_name, json_tiny(conf.get(ce_name, pt::ptree())), d);
|
|
log_message(LogMessageLevel::INFO, module_name, report.second, d ? RED : GREEN);
|
|
}
|
|
|
|
ce_name = Config::cgen2s[Config::ConfigGeneric::USER_INPUT_ACTIVITY];
|
|
if (IsEnabled(ce_name, conf.get<std::string>(ce_name + "." + Config::cg2s[Config::ConfigGlobal::ENABLED], ""))) {
|
|
d = CheckUserInputActivity(ProcessWorkingMode::MASTER);
|
|
report = GenerateReportEntry(ce_name, json_tiny(conf.get(ce_name, pt::ptree())), d);
|
|
log_message(LogMessageLevel::INFO, module_name, report.second, d ? RED : GREEN);
|
|
}
|
|
|
|
ce_name = Config::cgen2s[Config::ConfigGeneric::AUDIO_DEVICE_ABSENCE];
|
|
if (IsEnabled(ce_name, conf.get<std::string>(ce_name + "." + Config::cg2s[Config::ConfigGlobal::ENABLED], ""))) {
|
|
d = CheckAudioDeviceAbsence();
|
|
report = GenerateReportEntry(ce_name, json_tiny(conf.get(ce_name, pt::ptree())), d);
|
|
log_message(LogMessageLevel::INFO, module_name, report.second, d ? RED : GREEN);
|
|
}
|
|
}
|
|
|
|
bool Generic::CheckSystemUptime() const {
|
|
// FIXME: make it configurable ?
|
|
const DWORD uptime = 1000 * 60 * 12; // 12 minutes
|
|
|
|
return GetTickCount() < uptime;
|
|
}
|
|
|
|
bool Generic::CheckRAM() const {
|
|
MEMORYSTATUSEX ms = {};
|
|
ms.dwLength = sizeof(ms);
|
|
|
|
// FIXME: make it configurable ?
|
|
const DWORDLONG min_ram = 1024 * 1024 * 1024; // 1GB
|
|
|
|
if (!GlobalMemoryStatusEx(&ms))
|
|
return false;
|
|
|
|
return ms.ullTotalPhys < min_ram;
|
|
}
|
|
|
|
bool Generic::CheckBigRAMAllocate() const
|
|
{
|
|
void* mem = VirtualAllocEx(GetCurrentProcess(), nullptr, 0x279C6A13, MEM_COMMIT, PAGE_READWRITE);
|
|
const bool rv = !mem;
|
|
if (mem)
|
|
{
|
|
memset(mem, 0xBD, 0x279C6A13);
|
|
VirtualFreeEx(GetCurrentProcess(), mem, 0, MEM_RELEASE);
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
bool Generic::CheckDiskSize() const {
|
|
HANDLE hDrive;
|
|
GET_LENGTH_INFORMATION gli = {};
|
|
DWORD dwReturned;
|
|
uint32_t min_disk_size_gb = 60; // FIXME: make it configurable ?
|
|
|
|
hDrive = CreateFileA("\\\\.\\PhysicalDrive0", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
|
if (hDrive == INVALID_HANDLE_VALUE)
|
|
return false;
|
|
|
|
if (!DeviceIoControl(hDrive, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &gli, sizeof(gli), &dwReturned, NULL)) {
|
|
CloseHandle(hDrive);
|
|
return false;
|
|
}
|
|
|
|
CloseHandle(hDrive);
|
|
return (gli.Length.QuadPart / (1024 * 1024 * 1024)) < min_disk_size_gb;
|
|
}
|
|
|
|
bool Generic::CheckDriveSize() const {
|
|
ULARGE_INTEGER drive_size = {};
|
|
uint32_t min_disk_size_gb = 60; // FIXME: make it configurable ?
|
|
|
|
if (GetDiskFreeSpaceExA("C:\\", NULL, &drive_size, NULL))
|
|
return (drive_size.QuadPart / (1024 * 1024 * 1024)) < min_disk_size_gb;
|
|
|
|
return false;
|
|
}
|
|
|
|
bool Generic::CheckNDISFile() const {
|
|
HANDLE hFile;
|
|
const wchar_t ndis_wan_ip_fname[] = L"\\\\.\\NPF_NdisWanIp";
|
|
DWORD err;
|
|
|
|
hFile = CreateFileW(ndis_wan_ip_fname, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
|
|
if (hFile == INVALID_HANDLE_VALUE) {
|
|
err = GetLastError();
|
|
return err != ERROR_PATH_NOT_FOUND && err != ERROR_FILE_NOT_FOUND;
|
|
}
|
|
CloseHandle(hFile);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Generic::CheckMouseActive() const {
|
|
POINT pos_f, pos_s;
|
|
const uint32_t timeout = 1000; // timeout in milliseconds
|
|
const uint8_t tries = 5;
|
|
|
|
for (uint8_t i = 0; i < tries; ++i) {
|
|
GetCursorPos(&pos_f);
|
|
Sleep(timeout);
|
|
GetCursorPos(&pos_s);
|
|
|
|
if ((pos_s.x - pos_f.x) || (pos_s.y - pos_f.y))
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool Generic::CheckSleepDummyPatch() const {
|
|
DWORD tick_count_f, tick_count_s;
|
|
const DWORD delay_ms = 900; // timeout in milliseconds
|
|
|
|
tick_count_f = GetTickCount();
|
|
SleepEx(delay_ms, FALSE);
|
|
tick_count_s = GetTickCount();
|
|
|
|
return (tick_count_s - tick_count_f) < (delay_ms - 50);
|
|
}
|
|
|
|
bool Generic::CheckPerformanceCounter() const {
|
|
LARGE_INTEGER Frequency = { 0 };
|
|
LARGE_INTEGER StartingTime = { 0 };
|
|
LARGE_INTEGER EndingTime = { 0 };
|
|
LARGE_INTEGER ElapsedTimeMs = { 0 };
|
|
|
|
const DWORD delay_ms = 10000; // timeout in milliseconds
|
|
const DWORD max_delta = 50; // delay in milliseconds
|
|
|
|
QueryPerformanceFrequency(&Frequency);
|
|
QueryPerformanceCounter(&StartingTime);
|
|
|
|
// Activity to be timed
|
|
Sleep(delay_ms);
|
|
|
|
QueryPerformanceCounter(&EndingTime);
|
|
|
|
ElapsedTimeMs.QuadPart = 1000ll * (EndingTime.QuadPart - StartingTime.QuadPart) / Frequency.QuadPart;
|
|
|
|
// printf("Elapsed: %u. Waited: %u\n", ElapsedTimeMs.LowPart, delay_ms);
|
|
|
|
return abs(static_cast<long>(ElapsedTimeMs.LowPart) - static_cast<long>(delay_ms)) > max_delta;
|
|
}
|
|
|
|
bool Generic::CheckNumberOfProcessors() const {
|
|
const DWORD min_proc_count = 2;
|
|
SYSTEM_INFO si = {};
|
|
|
|
if (get_number_of_processors() < min_proc_count)
|
|
return true;
|
|
|
|
GetSystemInfo(&si);
|
|
|
|
return si.dwNumberOfProcessors < min_proc_count;
|
|
}
|
|
|
|
bool Generic::CheckDNSResponse() const {
|
|
// Calling function DnsQuery to query Host or PTR records
|
|
std::list<IP4_ADDRESS> ips;
|
|
// FIXME: should it be configurable?
|
|
std::map<std::string, size_t> dns_r = {
|
|
{ "microsoft.com", 3 },
|
|
{ "bbc.com", 3 },
|
|
{ "amazon.com", 3 }
|
|
};
|
|
bool sandbox_detected = false;
|
|
unsigned char ip_addr[4];
|
|
|
|
for (auto &dns : dns_r) {
|
|
ips = {};
|
|
if (!perform_dns_request(dns.first, ips))
|
|
continue;
|
|
|
|
// perform check on number of received domains
|
|
if (ips.size() < dns.second) {
|
|
sandbox_detected = true;
|
|
break;
|
|
}
|
|
|
|
// perform check on received IP-addresses
|
|
for (auto &ip : ips) {
|
|
memcpy(ip_addr, reinterpret_cast<void *>(&ip), sizeof(ip_addr));
|
|
if (!(((ip_addr[0] != 10) && (((ip_addr[0] != 0xac) || (ip_addr[1] <= 15)) || (ip_addr[1] >= 0x20))) && ((ip_addr[0] != 0xc0) || (ip_addr[1] != 0xa8)))) {
|
|
sandbox_detected = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return sandbox_detected;
|
|
}
|
|
|
|
bool Generic::CheckTimeTampering(ProcessWorkingMode wm) const {
|
|
switch (wm) {
|
|
case ProcessWorkingMode::MASTER:
|
|
return CheckTimeTamperingMaster();
|
|
case ProcessWorkingMode::SLAVE:
|
|
return CheckTimeTamperingSlave();
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
bool Generic::CheckTimeTamperingMaster() const {
|
|
wchar_t app_params[] = L"--action --dtt";
|
|
PROCESS_INFORMATION pi = {};
|
|
|
|
if (!run_self_susp(app_params, &pi))
|
|
return false;
|
|
|
|
ResumeThread(pi.hThread);
|
|
|
|
// wait process for finish
|
|
DWORD ec;
|
|
do {
|
|
if (!GetExitCodeProcess(pi.hProcess, &ec)) {
|
|
TerminateProcess(pi.hProcess, 0xFF);
|
|
CloseHandle(pi.hThread);
|
|
CloseHandle(pi.hProcess);
|
|
return false;
|
|
}
|
|
Sleep(100);
|
|
} while (ec == STILL_ACTIVE);
|
|
|
|
CloseHandle(pi.hThread);
|
|
CloseHandle(pi.hProcess);
|
|
|
|
return ec == 1;
|
|
}
|
|
|
|
|
|
bool Generic::CheckTimeTamperingSlave() const {
|
|
const int delta = 5 * 1000; // 5 sec
|
|
const int64_t k100NStoMSecs = 10000ll;
|
|
bool sandboxDetected = false;
|
|
const std::string host("google.com"); // FIXME: should be configurable?
|
|
|
|
FILETIME ftLocalStart, ftLocalEnd, ftWebStart, ftWebEnd;
|
|
|
|
GetSystemTimeAsFileTime(&ftLocalStart);
|
|
if (!get_web_time(host, ftWebStart))
|
|
return false;
|
|
|
|
int64_t totalMSec = 0;
|
|
for (int i = 0; i < 10; ++i) {
|
|
const int sleepSec = 1 + (rand() % 10);
|
|
totalMSec += sleepSec * 1000;
|
|
SleepEx(sleepSec * 1000, FALSE);
|
|
}
|
|
|
|
GetSystemTimeAsFileTime(&ftLocalEnd);
|
|
if (!get_web_time(host, ftWebEnd))
|
|
return false;
|
|
|
|
// PC's clock validation
|
|
const int64_t localTimeDiff = std::abs(ftLocalEnd - ftLocalStart) / k100NStoMSecs;
|
|
const int64_t webTimeDiff = std::abs(ftWebEnd - ftWebStart) / k100NStoMSecs;
|
|
|
|
if (std::abs(localTimeDiff - webTimeDiff) > delta)
|
|
sandboxDetected = true;
|
|
|
|
// second check for proper sleep delay
|
|
if (!sandboxDetected) {
|
|
if (localTimeDiff < totalMSec)
|
|
sandboxDetected = true;
|
|
if (webTimeDiff < totalMSec)
|
|
sandboxDetected = true;
|
|
}
|
|
return sandboxDetected;
|
|
}
|
|
|
|
|
|
bool Generic::CheckMouseRawActive(ProcessWorkingMode wm) {
|
|
switch (wm) {
|
|
case ProcessWorkingMode::MASTER:
|
|
return CheckMouseRawActiveMaster();
|
|
case ProcessWorkingMode::SLAVE:
|
|
return CheckMouseRawActiveSlave();
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
bool Generic::CheckMouseRawActiveMaster() {
|
|
wchar_t app_params[] = L"--action --mra";
|
|
PROCESS_INFORMATION pi = {};
|
|
const uint32_t timeout = 1000; // timeout in milliseconds
|
|
const uint8_t tries = 10;
|
|
|
|
if (!run_self_susp(app_params, &pi))
|
|
return false;
|
|
|
|
ResumeThread(pi.hThread);
|
|
|
|
// wait process for finish
|
|
DWORD ec;
|
|
for (uint8_t i = 0; i < tries; ++i) {
|
|
GetExitCodeProcess(pi.hProcess, &ec);
|
|
if (ec != STILL_ACTIVE)
|
|
break;
|
|
Sleep(timeout);
|
|
}
|
|
|
|
TerminateProcess(pi.hProcess, 0xFF);
|
|
CloseHandle(pi.hThread);
|
|
CloseHandle(pi.hProcess);
|
|
|
|
return ec != 0;
|
|
}
|
|
|
|
|
|
bool Generic::CheckMouseRawActiveSlave() {
|
|
MSG msg;
|
|
HINSTANCE hInstance = GetModuleHandleA(NULL);
|
|
|
|
if (MouseRawActiveRegisterClass(hInstance) == NULL)
|
|
return false;
|
|
|
|
if (MouseRawActiveInitInstance(hInstance) == FALSE)
|
|
return false;
|
|
|
|
while (GetMessage(&msg, NULL, 0, 0)) {
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
bool Generic::CheckUserInputActivity(ProcessWorkingMode wm)
|
|
{
|
|
switch (wm) {
|
|
case ProcessWorkingMode::MASTER:
|
|
return CheckUserInputActivityMaster();
|
|
case ProcessWorkingMode::SLAVE:
|
|
return CheckUserInputActivitySlave();
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
bool Generic::CheckUserInputActivityMaster() {
|
|
wchar_t app_params[] = L"--action --user-input";
|
|
PROCESS_INFORMATION pi = {};
|
|
const uint32_t timeout = 1000; // timeout in milliseconds
|
|
const uint8_t tries = 10;
|
|
|
|
if (!run_self_susp(app_params, &pi))
|
|
return false;
|
|
|
|
ResumeThread(pi.hThread);
|
|
|
|
// wait process for finish
|
|
DWORD ec;
|
|
for (uint8_t i = 0; i < tries; ++i) {
|
|
GetExitCodeProcess(pi.hProcess, &ec);
|
|
if (ec != STILL_ACTIVE)
|
|
break;
|
|
Sleep(timeout);
|
|
}
|
|
|
|
TerminateProcess(pi.hProcess, 0xFF);
|
|
CloseHandle(pi.hThread);
|
|
CloseHandle(pi.hProcess);
|
|
|
|
return ec != 0;
|
|
}
|
|
|
|
|
|
bool Generic::CheckUserInputActivitySlave() {
|
|
int tries = 0xFFFAF99;
|
|
LASTINPUTINFO lii = {};
|
|
int okTries = 0;
|
|
DWORD lastTime = 0;
|
|
while (1)
|
|
{
|
|
lii.cbSize = 8;
|
|
lii.dwTime = 0;
|
|
if (!GetLastInputInfo(&lii))
|
|
return true;
|
|
if (lii.dwTime - lastTime >= 0x1F2)
|
|
{
|
|
++okTries;
|
|
lastTime = lii.dwTime;
|
|
}
|
|
SleepEx(0x11Bu, 0);
|
|
if (okTries > 5)
|
|
return false;
|
|
if (!--tries)
|
|
return true;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
bool Generic::CheckAudioDeviceAbsence() const {
|
|
return is_audio_device_absent();
|
|
}
|
|
|
|
|
|
ATOM Generic::MouseRawActiveRegisterClass(HINSTANCE hInstance) {
|
|
WNDCLASSEXA wcex;
|
|
|
|
wcex.cbSize = sizeof(WNDCLASSEXA);
|
|
|
|
wcex.style = CS_HREDRAW | CS_VREDRAW;
|
|
wcex.lpfnWndProc = Generic::MouseRawWndProc;
|
|
wcex.cbClsExtra = 0;
|
|
wcex.cbWndExtra = 0;
|
|
wcex.hInstance = hInstance;
|
|
wcex.hIcon = NULL;
|
|
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
|
|
wcex.lpszMenuName = NULL;
|
|
wcex.lpszClassName = mouse_raw_wnd_class.c_str();
|
|
wcex.hIconSm = NULL;
|
|
|
|
return RegisterClassExA(&wcex);
|
|
}
|
|
|
|
|
|
BOOL Generic::MouseRawActiveInitInstance(HINSTANCE hInstance) {
|
|
HWND hWnd;
|
|
|
|
// hWnd = CreateWindowExA(WS_EX_TOOLWINDOW, mouse_raw_wnd_class.c_str(), "ABCD", 0, 0, 0, 680, 480, NULL, NULL, hInstance, NULL);
|
|
hWnd = CreateWindowExA(WS_EX_TOOLWINDOW | WS_EX_TOPMOST, mouse_raw_wnd_class.c_str(), "ABCD", 0, 0, 0, 640, 480, NULL, NULL, hInstance, NULL);
|
|
|
|
if (!hWnd)
|
|
return FALSE;
|
|
|
|
ShowWindow(hWnd, SW_SHOW);
|
|
UpdateWindow(hWnd);
|
|
|
|
// register raw input device
|
|
RAWINPUTDEVICE Rid[1];
|
|
|
|
Rid[0].usUsagePage = 0x01;
|
|
Rid[0].usUsage = 0x02;
|
|
Rid[0].dwFlags = RIDEV_NOLEGACY; // adds HID mouse and also ignores legacy mouse messages
|
|
Rid[0].hwndTarget = hWnd;
|
|
|
|
return RegisterRawInputDevices(Rid, 1, sizeof(Rid[0]));
|
|
}
|
|
|
|
|
|
LRESULT CALLBACK Generic::MouseRawWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
|
|
PAINTSTRUCT ps;
|
|
HDC hdc;
|
|
const uint8_t total_tries = 20;
|
|
const uint8_t real_after = 5;
|
|
|
|
switch (message) {
|
|
case WM_INPUT: {
|
|
|
|
UINT dwSize;
|
|
|
|
// puts("WM_INPUT");
|
|
|
|
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER));
|
|
LPBYTE lpb = new BYTE[dwSize];
|
|
|
|
if (lpb == NULL)
|
|
return 0;
|
|
|
|
if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)) != dwSize) {
|
|
delete[] lpb;
|
|
lpb = NULL;
|
|
|
|
return 0;
|
|
}
|
|
|
|
RAWINPUT *raw = (RAWINPUT*)lpb;
|
|
|
|
if (raw->header.dwType == RIM_TYPEMOUSE) {
|
|
static LONG lastX = 0;
|
|
static LONG lastY = 0;
|
|
static uint8_t count = 0;
|
|
static uint8_t tries = 0;
|
|
|
|
++tries;
|
|
|
|
if (lastX != raw->data.mouse.lLastX && lastY != raw->data.mouse.lLastY)
|
|
++count;
|
|
|
|
lastX = raw->data.mouse.lLastX;
|
|
lastY = raw->data.mouse.lLastY;
|
|
|
|
// not detected
|
|
if (count >= real_after) {
|
|
ExitProcess(0);
|
|
}
|
|
|
|
// detected
|
|
if (tries >= total_tries) {
|
|
ExitProcess(1);
|
|
}
|
|
}
|
|
|
|
delete[] lpb;
|
|
lpb = NULL;
|
|
|
|
break;
|
|
}
|
|
case WM_PAINT:
|
|
hdc = BeginPaint(hWnd, &ps);
|
|
EndPaint(hWnd, &ps);
|
|
break;
|
|
case WM_DESTROY:
|
|
PostQuitMessage(0);
|
|
break;
|
|
default:
|
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
} // SandboxEvasion
|