目前网上千篇一律都是这个代码 public static string Get_CPUID() { try {
而现在64位Windows系统已经很流行了,在32/64位模式下如何使用CPUID呢?于是本文介绍了如何在各个版本的VC及64位下使用CPUID指令。 一、推荐使用__cpuid、__cpuidex等Intrinsics函数 在32位模式下,我们可以使用内嵌汇编来调用cpuid指令。但在64位模式下,VC编译器不支持内嵌汇编。 例如CPUID指令的对应Intrinsics函数是—— // http://msdn.microsoft.com/en-us/library/hskdteyh.aspx void __cpuid( 早期的CPUID功能只需要一个功能ID参数(eax),这时可以使用__cpuid函数。 cpuid; // save.
: 1436.898 cpu cores : 6 cpuid level : 20 cpu family : 6 cpu MHz : 1438.027 cpu cores : 6 cpuid level cpu cores : 6 cpuid level : 20 cpu family : 6 cpu MHz : 1317.898 cpu cores : 6 cpuid level : 20 cpu cores : 6 cpuid level : 20 cpu family : 6 cpu MHz : 1375.671 cpu cores : 6 cpuid level : 20 cpu family cores : 18 cpuid level : 20 cpu family : 6 cpu MHz : 1200.199 cpu cores : 18 cpuid level : 20 cpu : 18 cpuid level : 20 cpu family : 6 cpu MHz : 1200.199 cpu cores : 18 cpuid level : 20 cpu family
macos版本为bigsur 11系列; 宿主机cpu:AMD r5 5600h 虚拟机修改代码 smc.version = "0" cpuid.0.eax = "0000:0000:0000:0000 :0000:0000:0000:1011" cpuid.0.ebx = "0111:0101:0110:1110:0110:0101:0100:0111" cpuid.0.ecx = "0110:1100 :0110:0101:0111:0100:0110:1110" cpuid.0.edx = "0100:1001:0110:0101:0110:1110:0110:1001" cpuid.1.eax = "0000:0000:0000:0001:0000:0110:0111:0001" cpuid.1.ebx = "0000:0010:0000:0001:0000:1000:0000:0000" cpuid .1.ecx = "1000:0010:1001:1000:0010:0010:0000:0011" cpuid.1.edx = "0000:0111:1000:1011:1111:1011:1111:
分析 Host上拓扑关系 我们一般会用lscpu命令看到基本的CPU拓扑信息,也可以通过cat /proc/cpuinfo的方式看到“physical id”,“core id” cpuid 再进一步探讨 Linux有命令cpuid,代码在https://github.com/tycho/cpuid cpuid命令的结果截取如下: ? 可见,通过cpuid命令可以获取到cpu的确切的socket/core/thread信息。 进一步分析源代码可以发现,上图的打印信息是通过CPUID leaf 0x0b获取到的。 QEMU 既然是通过CPUID指令可以获取cpu的硬件拓扑,而且Guest在运行CPUID指令的时候,会从none-root模式退出来,hypervisor可以构造出来特定的reg参数告诉给Guest, Cache passthrough 同理,cache的拓扑关系也是通过CPUID leaf 0x02和leaf 0x04指令获取的,通过配置qemu的启动参数“host-cache-info=on”达到
5,cpuid命令 目前cpuid的upstream(https://github.com/tycho/cpuid)支持了v5的avx指令。 编译upstream的cpuid,执行 ? 在linux-4.4上执行cpuid,也可以看到,那么原因是什么呢? avx512指令集是CPU指令,不同的cpu以及cpu版本支持情况不同。 cpu提供了cpuid这条指令,根据返回值的flag判断,当前cpu是否支持。 lscpu(或者cat /proc/cpuinfo),是kernel实现的对指令支持的检查,然后输出字符串。 cpuid命令,在用户态直接执行cpuid指令,获取cpu的flag。并不依赖内核实现。 所以,在v5的cpu上,4.4的内核上,会看到lscpu和cpuid的不同结果。
(int level, byte* buffer) // { // eax = level // cpuid // buffer[0] = eax , // mov eax, dword ptr [ebp+8] (move level into eax) 0x0F, 0xA2, // cpuid byte[] x64CodeBytes = { 0x53, // push rbx this gets clobbered by cpuid // rcx is level // rdx is buffer. // Need to save buffer elsewhere, cpuid overwrites rdx , call cpuid 0x89, 0xc8, // mov eax, ecx 0x0F, 0xA2, // cpuid
这些关系是通过AffinityStrategy中的matches方法来实现的: boolean matches(int cpuId, int cpuId2); matches传入两个参数,分别是传入的两个 cpuId。 (cpuId) == cpuLayout.socketId(cpuId2) && cpuLayout.coreId(cpuId) == cpuLayout.coreId 并且提供了三个方法根据给定的cpuId返回对应的socket、core和thread信息: int socketId(int cpuId); int coreId(int cpuId) ; int threadId(int cpuId); matches方法就是根据传入的cpuId找到对应的socket,core信息进行比较,从而生成了5中不同的策略。
(int level, byte* buffer) // { // eax = level // cpuid // buffer[0] = eax , // mov eax, dword ptr [ebp+8] (move level into eax) 0x0F, 0xA2, // cpuid byte[] x64CodeBytes = { 0x53, // push rbx this gets clobbered by cpuid // rcx is level // rdx is buffer. // Need to save buffer elsewhere, cpuid overwrites rdx , call cpuid 0x89, 0xc8, // mov eax, ecx 0x0F, 0xA2, // cpuid
高32位是CPUID,用来识别CPU类型。低64位每个处理器都不同,唯一地代表了该处理器。 CPU号可以用来识别 https://blog.csdn.net/fudong071234/article/details/49612083__cpuid, __cpuidex | Microsoft DocsLearn more about: __cpuid, __cpuidex https://docs.microsoft.com/en-us/cpp/intrinsics/cpuid-cpuidex = 7) { f_7_EBX_ = data_[7].interArray[1]; f_7_ECX_ = data_[7].interArray[2]; } // Calling __cpuid __cpuid(cpui.interArray, 0x80000000); nExIds_ = cpui.interArray[0]; char brand[0x40]; memset(brand
与rdtsc;cpuid;rdtsc组合类似,IET散度测试使用计数器来分析两条指令,计算平均执行时间,然后比较两条指令的结果。 捕获指令的开始时钟计数(cpuid)。 每次都用相同的叶子执行,并捕获结束时钟计数。 计算该循环的时钟计数之差。 将结果存储在CPUID_IET数组中。 重复第二条候选指令。 理想的候选者是cpuid,但必须谨慎选择第二条指令。平均IET必须比cpuid实际硬件上的IET长,否则检查毫无意义。 我们还限制了VMX / SVM指令的执行,并追溯了RDTSC和CPUID的所有执行。结果有些令人失望。 BattlEye程序 RDTSC / CPUID / RDTSC BattlEye采用的方法是使用rdtsc;cpuid;rdtsc组合的标准定时攻击。
原理其实很简单,通过读取对应UUID寄存器,就可以获取过去到芯片的UUID QString RJLinkView::jlinkGetCpuIdHandle(void) { unsigned char cpuId [12]={0}; char cpuIdTemp[128]={0}; jlinkReadMemFunc(0x1FFF7A10, 12, cpuId); sprintf(cpuIdTemp , "%02X%02X%02X%02X-%02X%02X%02X%02X-%02X%02X%02X%02X", cpuId[3], cpuId[2], cpuId[1], cpuId [0], cpuId[7], cpuId[6], cpuId[5], cpuId[4], cpuId[11], cpuId[10], cpuId[9], jlinkConnectHandle()) { infoShowHandle(tr("获取CPU ID中,请稍后...")); infoShowHandle(tr("获取CPUID
添加引用:using System.Management;
实现代码:
class HardWareInfo
{
///
pwd=iegc 提取码:iegc 在.vmx文件尾部加上这段配置才可以启动机器 bios.bootDelay="5000" smc.version = "0" cpuid.0.eax = "0000: 0000:0000:0000:0000:0000:0000:1011" cpuid.0.ebx = "0111:0101:0110:1110:0110:0101:0100:0111" cpuid.0.ecx = "0110:1100:0110:0101:0111:0100:0110:1110" cpuid.0.edx = "0100:1001:0110:0101:0110:1110:0110:1001" cpuid.1.eax = "0000:0000:0000:0001:0000:0110:0111:0001" cpuid.1.ebx = "0000:0010:0000:0001:0000:1000: 0000:0000" cpuid.1.ecx = "1000:0010:1001:1000:0010:0010:0000:0011" cpuid.1.edx = "0000:0111:1000:1011
0x1FFFF7AC; #else void* p = (void*)0x1FFFF7E8; #endif memcpy(ID, p, ArrayLength(ID)); CPUID = SCB->CPUID; uint MCUID = DBGMCU->IDCODE; // MCU编码。 endif 各常见芯片信息如下: STM32F030C8T6 SmartOS STM32F030C8 48MHz Flash:64k RAM:8k DevID:0x0440 RevID:0x2000 CPUID 0x20002000) = 0xe60 GD32F130C8T6 SmartOS GD32F130C8 48MHz Flash:64k RAM:8k DevID:0x0410 RevID:0x1303 CPUID = 0x1188 (4k) STM32F103VET6 SmartOS STM32F103VE 72MHz Flash:512k RAM:64k DevID:0x0414 RevID:0x1001 CPUID
(); int sockets(); int coresPerSocket(); int threadsPerCore(); int socketId(int cpuId ); int coreId(int cpuId); int threadId(int cpuId); } 根据CPU layout的信息, AffinityStrategies提供了一些基本的 (cpuId) == cpuLayout.socketId(cpuId2) && cpuLayout.coreId(cpuId) == cpuLayout.coreId (cpuId2); } } Affinity策略可以有顺序,在前面的策略会首先匹配,如果匹配不上则会选择第二策略,依此类推。 public static AffinityLock acquireLock(int cpuId) { return acquireLock(true, cpuId, AffinityStrategies.ANY
String Dim mo As New ManagementObjectSearcher("SELECT * FROM Win32_Processor") Dim CpuId As String = "" For Each wb As ManagementObject In mo.Get CpuId = wb("ProcessorId ") Next Return CpuId End Function
CPUID Leaf比较 与保留的MSR地址范围类似的一种快速方法是CPUID对照其通常的值检查保留的响应。 第一个示例显示使用无效的CPUID叶来确定系统是否已虚拟化。 UINT64 UmpIsSystemVirtualized2(void) { cpuid_buffer_t regs; __cpuid((int32_t*)®s, 0x40000000 ); cpuid_buffer_t reserved_regs; __cpuid((int32_t*)&reserved_regs, 0); __cpuid((int32_t* RDTSC / CPUID / RDTSC 如果您已经进行了性能分析,或者为防恶意软件而进行了沙箱检测(或更可疑的目的),则可能已经使用或遇到了这种计时检查。
该宏使用了SGX环境禁止的CPUID指令,导致程序崩溃。 一方面SGX环境出于安全考虑禁止了CPUID指令,另一方面,应用程序使用CPUID检测CPU对SIMD的支持情况是很常见的“正当行为”。 虽然CPUID触发崩溃虽然没有泄露信息,没有越权访问,没有触发Unsound等安全问题,是一种运行时安全守卫措施。 Teaclave的sgx_tstd中重新实现了is_x86_feature_detected宏来避免触及CPUID。 另外,单解决一个is_x86_feature_detected显然也不能避免代码直接内嵌CPUID汇编指令的情况。因此,我们暂且选择让代码不触及CPUID。 具体方法为,我们增加一个编译后处理步骤,通过反汇编输出的enclave.so来检查其中是否含有CPUID指令。
这里我在吾爱破解论坛上找到份18年的比赛作品,从8个方面检测虚拟机环境: 查询I/O通信端口 通过MAC地址检测 CPUID检测 通过主板序列号、型号、系统盘所在磁盘名称等其他硬件信息 搜索特定进程检测 通过注册表检测 通过服务检测 文件路径检测 通过时间差检测 检测工具 0x01 去虚拟化思路 其中较为难解决的是CPUID和进程、服务的隐藏,其他可以通过修改设备信息做到。 CPUID CPUID检测是大多数检测程序都会用到的,这里我们可想.vmx配置文件中添加 cpuid.1.eax = "00001111001010111111101111110011" 在绕VMP3.5 的虚拟机检测时也需要在cpuid上断点置eax为0,这里CPUID就算完成了,接下来我们需要对关键进程和服务进行隐藏。 00-0c-29" || strMac == "00-50-56") { return TRUE; } else { return FALSE; } } //3.CPUID