mandiant / speakeasy

Windows kernel and user mode emulation.
MIT License
1.53k stars 232 forks source link

I detected some malware which are using IsProcessorFeaturePresent fun… #215

Closed sacx closed 2 years ago

sacx commented 2 years ago

…ction to detect if we are running in a emulated environment or not.

Right now IsProcessorFeaturePresent returns 1 for any feature, still it should not be the case for some of them. I just create a small applications to check for all features registered in processthreadsapi.h and I assigned those return values to each feature. Here is the table with those features and their return in a VirtualBox and on a real machine. Feature VirtualBox Return Physical Machine Return PF_FLOATING_POINT_PRECISION_ERRATA 0 0 PF_FLOATING_POINT_EMULATED 0 0 PF_COMPARE_EXCHANGE_DOUBLE 1 1 PF_MMX_INSTRUCTIONS_AVAILABLE 1 1 PF_PPC_MOVEMEM_64BIT_OK 0 0 PF_ALPHA_BYTE_INSTRUCTIONS 0 0 PF_XMMI_INSTRUCTIONS_AVAILABLE 1 1 PF_3DNOW_INSTRUCTIONS_AVAILABLE 0 0 PF_RDTSC_INSTRUCTION_AVAILABLE 1 1 PF_PAE_ENABLED 1 1 PF_XMMI64_INSTRUCTIONS_AVAILABLE 1 1 PF_SSE_DAZ_MODE_AVAILABLE 0 0 PF_NX_ENABLED 1 1 PF_SSE3_INSTRUCTIONS_AVAILABLE 1 1 PF_COMPARE_EXCHANGE128 1 1 PF_COMPARE64_EXCHANGE128 0 0 PF_CHANNELS_ENABLED 0 0 PF_XSAVE_ENABLED 1 1 PF_ARM_VFP_32_REGISTERS_AVAILABLE 0 0 PF_ARM_NEON_INSTRUCTIONS_AVAILABLE 0 0 PF_SECOND_LEVEL_ADDRESS_TRANSLATION 0 1 PF_VIRT_FIRMWARE_ENABLED 1 1 PF_RDWRFSGSBASE_AVAILABLE 1 1 PF_FASTFAIL_AVAILABLE 1 1 PF_ARM_DIVIDE_INSTRUCTION_AVAILABLE 0 0 PF_ARM_64BIT_LOADSTORE_ATOMIC 0 0 PF_ARM_EXTERNAL_CACHE_AVAILABLE 0 0 PF_ARM_FMAC_INSTRUCTIONS_AVAILABLE 0 0 PF_RDRAND_INSTRUCTION_AVAILABLE 1 1 PF_ARM_V8_INSTRUCTIONS_AVAILABLE 0 0 PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE 0 0 PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE 0 0 PF_RDTSCP_INSTRUCTION_AVAILABLE 1 1

sacx commented 2 years ago

To be more precise we have a malware which is using PF_FLOATING_POINT_PRECISION_ERRATA - The processor has the Pentium floating-point divide bug. Return from this feature must be 0 for all modern CPU's.

sacx commented 2 years ago

This is the code to get the values for IsProcessorFeaturePresent function.

#include <Windows.h>
#include <iostream>
#include <processthreadsapi.h>

int main()
{
    int var_PF_FLOATING_POINT_PRECISION_ERRATA = IsProcessorFeaturePresent(PF_FLOATING_POINT_PRECISION_ERRATA);
    std::cout << " PF_FLOATING_POINT_PRECISION_ERRATA " << var_PF_FLOATING_POINT_PRECISION_ERRATA<<"\n " ;
    int var_PF_FLOATING_POINT_EMULATED = IsProcessorFeaturePresent(PF_FLOATING_POINT_EMULATED);
    std::cout << " PF_FLOATING_POINT_EMULATED " << var_PF_FLOATING_POINT_EMULATED<<"\n " ;
    int var_PF_COMPARE_EXCHANGE_DOUBLE = IsProcessorFeaturePresent(PF_COMPARE_EXCHANGE_DOUBLE);
    std::cout << " PF_COMPARE_EXCHANGE_DOUBLE " << var_PF_COMPARE_EXCHANGE_DOUBLE<<"\n " ;
    int var_PF_MMX_INSTRUCTIONS_AVAILABLE = IsProcessorFeaturePresent(PF_MMX_INSTRUCTIONS_AVAILABLE);
    std::cout << " PF_MMX_INSTRUCTIONS_AVAILABLE " << var_PF_MMX_INSTRUCTIONS_AVAILABLE<<"\n " ;
    int var_PF_PPC_MOVEMEM_64BIT_OK = IsProcessorFeaturePresent(PF_PPC_MOVEMEM_64BIT_OK);
    std::cout << " PF_PPC_MOVEMEM_64BIT_OK " << var_PF_PPC_MOVEMEM_64BIT_OK<<"\n " ;
    int var_PF_ALPHA_BYTE_INSTRUCTIONS = IsProcessorFeaturePresent(PF_ALPHA_BYTE_INSTRUCTIONS);
    std::cout << " PF_ALPHA_BYTE_INSTRUCTIONS " << var_PF_ALPHA_BYTE_INSTRUCTIONS<<"\n " ;
    int var_PF_XMMI_INSTRUCTIONS_AVAILABLE = IsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE);
    std::cout << " PF_XMMI_INSTRUCTIONS_AVAILABLE " << var_PF_XMMI_INSTRUCTIONS_AVAILABLE<<"\n " ;
    int var_PF_3DNOW_INSTRUCTIONS_AVAILABLE = IsProcessorFeaturePresent(PF_3DNOW_INSTRUCTIONS_AVAILABLE);
    std::cout << " PF_3DNOW_INSTRUCTIONS_AVAILABLE " << var_PF_3DNOW_INSTRUCTIONS_AVAILABLE<<"\n " ;
    int var_PF_RDTSC_INSTRUCTION_AVAILABLE = IsProcessorFeaturePresent(PF_RDTSC_INSTRUCTION_AVAILABLE);
    std::cout << " PF_RDTSC_INSTRUCTION_AVAILABLE " << var_PF_RDTSC_INSTRUCTION_AVAILABLE<<"\n " ;
    int var_PF_PAE_ENABLED = IsProcessorFeaturePresent(PF_PAE_ENABLED);
    std::cout << " PF_PAE_ENABLED " << var_PF_PAE_ENABLED<<"\n " ;
    int var_PF_XMMI64_INSTRUCTIONS_AVAILABLE = IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE);
    std::cout << " PF_XMMI64_INSTRUCTIONS_AVAILABLE " << var_PF_XMMI64_INSTRUCTIONS_AVAILABLE<<"\n " ;
    int var_PF_SSE_DAZ_MODE_AVAILABLE = IsProcessorFeaturePresent(PF_SSE_DAZ_MODE_AVAILABLE);
    std::cout << " PF_SSE_DAZ_MODE_AVAILABLE " << var_PF_SSE_DAZ_MODE_AVAILABLE<<"\n " ;
    int var_PF_NX_ENABLED = IsProcessorFeaturePresent(PF_NX_ENABLED);
    std::cout << " PF_NX_ENABLED " << var_PF_NX_ENABLED<<"\n " ;
    int var_PF_SSE3_INSTRUCTIONS_AVAILABLE = IsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE);
    std::cout << " PF_SSE3_INSTRUCTIONS_AVAILABLE " << var_PF_SSE3_INSTRUCTIONS_AVAILABLE<<"\n " ;
    int var_PF_COMPARE_EXCHANGE128 = IsProcessorFeaturePresent(PF_COMPARE_EXCHANGE128);
    std::cout << " PF_COMPARE_EXCHANGE128 " << var_PF_COMPARE_EXCHANGE128<<"\n " ;
    int var_PF_COMPARE64_EXCHANGE128 = IsProcessorFeaturePresent(PF_COMPARE64_EXCHANGE128);
    std::cout << " PF_COMPARE64_EXCHANGE128 " << var_PF_COMPARE64_EXCHANGE128<<"\n " ;
    int var_PF_CHANNELS_ENABLED = IsProcessorFeaturePresent(PF_CHANNELS_ENABLED);
    std::cout << " PF_CHANNELS_ENABLED " << var_PF_CHANNELS_ENABLED<<"\n " ;
    int var_PF_XSAVE_ENABLED = IsProcessorFeaturePresent(PF_XSAVE_ENABLED);
    std::cout << " PF_XSAVE_ENABLED " << var_PF_XSAVE_ENABLED<<"\n " ;
    int var_PF_ARM_VFP_32_REGISTERS_AVAILABLE = IsProcessorFeaturePresent(PF_ARM_VFP_32_REGISTERS_AVAILABLE);
    std::cout << " PF_ARM_VFP_32_REGISTERS_AVAILABLE " << var_PF_ARM_VFP_32_REGISTERS_AVAILABLE<<"\n " ;
    int var_PF_ARM_NEON_INSTRUCTIONS_AVAILABLE = IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE);
    std::cout << " PF_ARM_NEON_INSTRUCTIONS_AVAILABLE " << var_PF_ARM_NEON_INSTRUCTIONS_AVAILABLE<<"\n " ;
    int var_PF_SECOND_LEVEL_ADDRESS_TRANSLATION = IsProcessorFeaturePresent(PF_SECOND_LEVEL_ADDRESS_TRANSLATION);
    std::cout << " PF_SECOND_LEVEL_ADDRESS_TRANSLATION " << var_PF_SECOND_LEVEL_ADDRESS_TRANSLATION<<"\n " ;
    int var_PF_VIRT_FIRMWARE_ENABLED = IsProcessorFeaturePresent(PF_VIRT_FIRMWARE_ENABLED);
    std::cout << " PF_VIRT_FIRMWARE_ENABLED " << var_PF_VIRT_FIRMWARE_ENABLED<<"\n " ;
    int var_PF_RDWRFSGSBASE_AVAILABLE = IsProcessorFeaturePresent(PF_RDWRFSGSBASE_AVAILABLE);
    std::cout << " PF_RDWRFSGSBASE_AVAILABLE " << var_PF_RDWRFSGSBASE_AVAILABLE<<"\n " ;
    int var_PF_FASTFAIL_AVAILABLE = IsProcessorFeaturePresent(PF_FASTFAIL_AVAILABLE);
    std::cout << " PF_FASTFAIL_AVAILABLE " << var_PF_FASTFAIL_AVAILABLE<<"\n " ;
    int var_PF_ARM_DIVIDE_INSTRUCTION_AVAILABLE = IsProcessorFeaturePresent(PF_ARM_DIVIDE_INSTRUCTION_AVAILABLE);
    std::cout << " PF_ARM_DIVIDE_INSTRUCTION_AVAILABLE " << var_PF_ARM_DIVIDE_INSTRUCTION_AVAILABLE<<"\n " ;
    int var_PF_ARM_64BIT_LOADSTORE_ATOMIC = IsProcessorFeaturePresent(PF_ARM_64BIT_LOADSTORE_ATOMIC);
    std::cout << " PF_ARM_64BIT_LOADSTORE_ATOMIC " << var_PF_ARM_64BIT_LOADSTORE_ATOMIC<<"\n " ;
    int var_PF_ARM_EXTERNAL_CACHE_AVAILABLE = IsProcessorFeaturePresent(PF_ARM_EXTERNAL_CACHE_AVAILABLE);
    std::cout << " PF_ARM_EXTERNAL_CACHE_AVAILABLE " << var_PF_ARM_EXTERNAL_CACHE_AVAILABLE<<"\n " ;
    int var_PF_ARM_FMAC_INSTRUCTIONS_AVAILABLE = IsProcessorFeaturePresent(PF_ARM_FMAC_INSTRUCTIONS_AVAILABLE);
    std::cout << " PF_ARM_FMAC_INSTRUCTIONS_AVAILABLE " << var_PF_ARM_FMAC_INSTRUCTIONS_AVAILABLE<<"\n " ;
    int var_PF_RDRAND_INSTRUCTION_AVAILABLE = IsProcessorFeaturePresent(PF_RDRAND_INSTRUCTION_AVAILABLE);
    std::cout << " PF_RDRAND_INSTRUCTION_AVAILABLE " << var_PF_RDRAND_INSTRUCTION_AVAILABLE<<"\n " ;
    int var_PF_ARM_V8_INSTRUCTIONS_AVAILABLE = IsProcessorFeaturePresent(PF_ARM_V8_INSTRUCTIONS_AVAILABLE);
    std::cout << " PF_ARM_V8_INSTRUCTIONS_AVAILABLE " << var_PF_ARM_V8_INSTRUCTIONS_AVAILABLE<<"\n " ;
    int var_PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE = IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE);
    std::cout << " PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE " << var_PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE<<"\n " ;
    int var_PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE = IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE);
    std::cout << " PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE " << var_PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE<<"\n " ;
    int var_PF_RDTSCP_INSTRUCTION_AVAILABLE = IsProcessorFeaturePresent(PF_RDTSCP_INSTRUCTION_AVAILABLE);
    std::cout << " PF_RDTSCP_INSTRUCTION_AVAILABLE " << var_PF_RDTSCP_INSTRUCTION_AVAILABLE<<"\n " ;
    int var_PF_RDPID_INSTRUCTION_AVAILABLE = IsProcessorFeaturePresent(PF_RDPID_INSTRUCTION_AVAILABLE);
    std::cout << " PF_RDPID_INSTRUCTION_AVAILABLE " << var_PF_RDPID_INSTRUCTION_AVAILABLE<<"\n " ;
    int var_PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE = IsProcessorFeaturePresent(PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE);
    std::cout << " PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE " << var_PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE<<"\n " ;
    int var_PF_MONITORX_INSTRUCTION_AVAILABLE = IsProcessorFeaturePresent(PF_MONITORX_INSTRUCTION_AVAILABLE);
    std::cout << " PF_MONITORX_INSTRUCTION_AVAILABLE " << var_PF_MONITORX_INSTRUCTION_AVAILABLE<<"\n " ;
    int var_PF_SSSE3_INSTRUCTIONS_AVAILABLE = IsProcessorFeaturePresent(PF_SSSE3_INSTRUCTIONS_AVAILABLE);
    std::cout << " PF_SSSE3_INSTRUCTIONS_AVAILABLE " << var_PF_SSSE3_INSTRUCTIONS_AVAILABLE<<"\n " ;
    int var_PF_SSE4_1_INSTRUCTIONS_AVAILABLE = IsProcessorFeaturePresent(PF_SSE4_1_INSTRUCTIONS_AVAILABLE);
    std::cout << " PF_SSE4_1_INSTRUCTIONS_AVAILABLE " << var_PF_SSE4_1_INSTRUCTIONS_AVAILABLE<<"\n " ;
    int var_PF_SSE4_2_INSTRUCTIONS_AVAILABLE = IsProcessorFeaturePresent(PF_SSE4_2_INSTRUCTIONS_AVAILABLE);
    std::cout << " PF_SSE4_2_INSTRUCTIONS_AVAILABLE " << var_PF_SSE4_2_INSTRUCTIONS_AVAILABLE<<"\n " ;
    int var_PF_AVX_INSTRUCTIONS_AVAILABLE = IsProcessorFeaturePresent(PF_AVX_INSTRUCTIONS_AVAILABLE);
    std::cout << " PF_AVX_INSTRUCTIONS_AVAILABLE " << var_PF_AVX_INSTRUCTIONS_AVAILABLE<<"\n " ;
    int var_PF_AVX2_INSTRUCTIONS_AVAILABLE = IsProcessorFeaturePresent(PF_AVX2_INSTRUCTIONS_AVAILABLE);
    std::cout << " PF_AVX2_INSTRUCTIONS_AVAILABLE " << var_PF_AVX2_INSTRUCTIONS_AVAILABLE<<"\n " ;
    int var_PF_AVX512F_INSTRUCTIONS_AVAILABLE = IsProcessorFeaturePresent(PF_AVX512F_INSTRUCTIONS_AVAILABLE);
    std::cout << " PF_AVX512F_INSTRUCTIONS_AVAILABLE " << var_PF_AVX512F_INSTRUCTIONS_AVAILABLE<<"\n " ;
}
williballenthin commented 2 years ago

im happy to merge at any time - let me know if you'll tweak the code or leave it as is.

sacx commented 2 years ago

I added the explanatory comment.

sacx commented 2 years ago

You can merge it now. Thanks!