On the day of moving bricks, I suddenly remembered that there seemed to be some anti virtual machine method for a virus analyzed before. At that time, I didn't understand much or even understand the operation of detecting virtual machines. Now I think of going back and forth to study the detection technology of virtual machine. In this process, I have learned from many classic articles of other gods (of course, most of them are other people's things, I just pick up people's teeth and wisdom)
In contrast, we generally encounter some anti virtual machine anti debugging operations when analyzing viruses. The common means of anti virtual machine is to traverse the system process, detect special processes, detect special services, detect registry entries and so on. Researchers from foreign SANS security organizations have concluded that there are no more than the following four types of virtual machine detection methods:
● search the process, file system and registry in the virtual environment;
● search memory in virtual environment
● search for specific virtual hardware in the virtual environment
● search for specific processor instructions and functions in the virtual environment
I learned the early articles shared by several great gods, and based on the examples inside. I did a test and added some understanding in the test process.
This time, we mainly detect the virtual machine environment based on the memory of the virtual environment and the technical means of processor instructions.
The first is to use privileged instructions to detect the virtual environment:
VMware provides a communication mechanism for mutual communication between physical machines and virtual machines. It uses the "IN" instruction to read the data of a specific port for two machine communication. However, because the IN instruction is a privileged instruction, when executing this instruction on the real machine IN protected mode, unless permission allows, an exception of type "EXCEPTION_PRIV_INSTRUCTION" will be triggered, and no exception will occur IN the virtual machine, When specifying the function number 0A (get VMware version), it will return its version number "VMXH" IN EBX; When the function number is 0x14, it can be used to obtain the VMware memory size. When it is greater than 0, it indicates that it is IN the virtual machine.
Detection routine:
#include <stdio.h> #include <Windows.h> int main() { bool rc = true; __try { __asm { push edx push ecx push ebx mov eax, 'VMXh' mov ebx, 0 // Set ebx to other values of non magic number 'VMXH' mov ecx, 10 // Specifies the function number, which is used to obtain the VMware version. When it is 0x14, it is used to obtain the VMware memory size mov edx, 'VX' // Port number in eax, dx // Read VMware version from port dx to eax //If the function number specified above is 0x14, you can judge whether the value in eax is greater than 0. If so, it indicates that it is in the virtual machine cmp ebx, 'VMXh' // Judge whether the VMware version 'VMXh' is included in ebx. If yes, it is in the virtual machine setz[rc] // Set return value pop ebx pop ecx pop edx } } __except (EXCEPTION_EXECUTE_HANDLER) //If not in VMware, this exception is triggered { rc = false; } if (rc) printf("In virtual machine environment"); else printf("Not in virtual machine"); getchar(); return rc; }
#include <stdio.h> #include <Windows.h> int main() { bool rc = true; __asm { push edx push ecx push ebx mov eax, 'VMXh' mov ebx, 0 // Set ebx to other values of non magic number 'VMXH' mov ecx, 14h // Specifies the function number, which is used to obtain the VMware version. When it is 0x14, it is used to obtain the VMware memory size mov edx, 'VX' // Port number in eax, dx // Read VMware version from port dx to eax //If the function number specified above is 0x14, you can judge whether the value in eax is greater than 0. If so, it indicates that it is in the virtual machine cmp eax, 0 // Judge whether the VMware version 'VMXh' is included in ebx. If yes, it is in the virtual machine JBE Table setz [rc] // Set return value Table: pop ebx pop ecx pop edx } if(!rc) printf("In virtual machine environment"); else printf("Not in virtual machine"); getchar(); return rc; }
Test results:
Method 2: use sensitive instructions to monitor the virtual environment:
VMM (Virtual Machine Monitor) is a kind of software that can create separate multiple (virtual) machines on the same physical hardware. As mentioned above, VMM of VMWare seems to run in our operating system as an application. In fact, it can run at the bottom of the operating system, that is, the system layer, which we often call, and fully control the hardware. In other words, during this period of time, the virtual memory and linear memory of the physical machine will be temporarily removed.
As shown in the figure above, there are several points to note:
1: Virtual machine memory and physical machine memory can be switched to each other
2: The operating system fully controls the physical machine OS context
3: VMM fully controls the context of the virtual machine
4: Each context has its own address space, interrupt descriptor table, stack and execution context (that is, physical machine and virtual machine have their own set of data structures). From here, we can start to detect the existence of virtual machine
Next is the second method to detect virtual machines: sensitive instruction detection virtual machines
The method of using IDT base address to detect virtual machine is a general method, which is applicable to VMware and Virtual PC. Interrupt Descriptor Table IDT (Interrupt Descriptor Table) is used to find the software function used to process interrupts. It is a data composed of 256 items, in which each interrupt corresponds to a function. The Interrupt Descriptor Table IDT associates each exception or interrupt vector with their processing process respectively. IDT is an array composed of 8-byte long descriptors. The IDT table can reside anywhere in the linear address space, and the processor uses the IDTR register to locate the location of the IDT table. We can use sensitive instructions to obtain the required data. The following sensitive instructions can obtain the values of the corresponding registers respectively.
- SGDT: store GDT register
- SIDT: store IDT register
- SLDT: store LDT register
- SMSW: store machine status
LIDT and SIDT instructions are used to load and save the contents of the IDTR register (interrupt descriptor table register, which is used for the base address of IDT in memory), and LIDT instructions are used to load the length limit and base address operands in memory into the IDTR register. This instruction can only be executed by the code whose current privilege level CPL is 0. It is usually used in the operating system initialization code when creating IDT. The SIDT instruction is used to copy the base address and length limit content in the IDTR into memory. The instruction can be executed at any privilege level.
The SIDT instruction stores the contents of the IDTR in the following format
typedef struct { WORD IDTLimit; // Size of IDT WORD LowIDTbase; // Low order address of IDT WORD HiIDTbase; // High order address of IDT } IDTINFO;
Since IDTR is the only one in use, it is impossible for two IDTR tables to work at the same time. However, there are two operating systems, that is, our physical machine operating system and virtual machine operating system. In order to prevent the conflict between the two, VMM will modify the IDT address in the virtual machine, which leads to the difference between the IDT address of the physical machine and the virtual machine. We can detect the virtual machine through this difference.
Use one sentence code to read the base address of IDT table:
A compilation reads the position of IDT
_asm sidt idtr;
(during the actual test, I found that when the IDT base address is less than 0xd00xxxxxx, it means that the program is in the VMware virtual environment, but the specific practicability needs to be tested. I found that it is not very accurate during Win10 64 bit physical and testing)
Test routine:
#include <stdio.h> int main () { unsigned char m[2+4], rpill[] = "\x0f\x01\x0d\x00\x00\x00\x00\xc3"; //Equivalent to SIDT[adrr], where addr is used to save the IDT address *((unsigned*)&rpill[3]) = (unsigned)m; //Set addr in sidt[addr] as the address of m ((void(*)())&rpill)(); //Execute the SIDT instruction and save the read IDT address in the array m printf ("idt base: %#X \ n ", * ((unsigned * &m[2])); / / since the first two bytes are IDT size, it is the IDT address from m[2] if (m[5]>0xd0) printf("Not in Matrix!%#x\n", m[5]; / / when the IDT base address is greater than 0x80xxxxx, the program is in VMware else printf ("in Matrix.%#x\n",m[5]);getchar(); return 0; }
Test results:
The above is the way of using IDT base address to detect virtual machines. Similarly, LDT and GDT can be used to detect virtual machines.
(in the operating system, there is only one global descriptor table GDT, and one processor corresponds to one GDT. Similarly, in order to prevent conflict, there must be a difference between the GDT of virtual machine and that of physical machine. We can judge according to the difference of this value.)
Use the LGDT instruction to load the entry address of GDT into the GDTR register, which is convenient for the CPU to use when dying. We can obtain the data of GDTR register through the SGDT instruction; Similarly, the LLDT instruction is used to install the selector into the LDTR register, and SLDT is used to obtain the value of the LDTR register.
Test routine:
#include <stdio.h> void GDTDetect(void) { unsigned int gdt_addr = 0; unsigned char gdtr[4]; _asm sgdt gdtr gdt_addr = *((unsigned int *)&gdtr[2]); printf("GDT BaseAddr:0x%x\n", gdt_addr); if ((gdt_addr >> 24) == 0x80) { printf("Inside VMware\n"); } else printf("Native OS\n"); } int main(void) { GDTDetect(); getchar(); return 0; }
Test results:
Detection method based on STR mechanism
When all programs running in protected mode switch tasks, the segment selector pointing to TSS in the current task will be stored in the task register. TSS contains the executable environment state of the current task, including general register state, segment register state, flag register state, EIP register state, etc. when this task is executed again, the processor will its original saved task state. Each task has its own TSS, and we can obtain the segment selector pointing to the TSS in the current task through the str instruction. The task register has the segment selector and segment descriptor of the TSS of the current task. The TSS descriptor can only be stored in GDT, not LDT or IDT. The instructions LTR (load task register) and str (save task register) load and save the visible part of the task register. LTR instruction allows the task register to load the segment selector of TSS descriptor. This instruction can only run at privilege level 0. This instruction is usually used to initialize the task register during system initialization. The instruction STR can save the visible part of the task register to a general-purpose register or memory. The instruction can run at any privilege level.
Here, the str (Store task register) instruction is used to store the segment selector in the task register (TR) to the target operand. The target operand can be a general-purpose register or memory location. The segment selector stored by this instruction points to the task status segment (TSS) of the currently running task. In the virtual machine and the real host, the address read through STR is different. When the address is equal to 0x0040xxxx, it indicates that it is in the virtual machine, otherwise it is a physical machine. (during the actual test, it is found that, on the contrary, when the str address is equal to 0x40, it indicates that it is in the physical machine state, otherwise it is in the virtual machine)
Test code:
}*/ #include <stdio.h> int main(void) { unsigned char mem[4] = { 0 }; int i; __asm str mem; printf(" STR base: 0x"); for (i = 0; i < 4; i++) { printf("%02x", mem[i]); } if (mem[0] == 0x40) printf("\n Native OS!!\n"); else printf("\n INSIDE MATRIX!!\n"); getchar(); return 0; }
The third method: detection method based on time difference
As the name suggests, it is to detect the relative running time of virtual machine and real machine through specific instructions. It can be realized through RDTSC instruction. RDTSC instruction is used to save the number of CPU running cycles since the computer is started into EDX: EAX, where EDX is high and EAX is low.
The main test codes are as follows:
.data szTitle db "VMDetect With RDTSC", 0h szInsideVM db "Inside VMware!", 0h szOutsideVM db "Native OS!", 0h .code start: RDTSC xchg ecx, eax RDTSC sub eax, ecx cmp eax, 0FFh jg Detected invoke MessageBox, 0, offset szOutsideVM, offset szTitle, 0 ret Detected: invoke MessageBox, 0, offset szInsideVM, offset szTitle, 0 ret end start
Countermeasures:
There are corresponding countermeasures for several methods of detecting virtual machines listed above, including detecting registry keys not listed, detecting specific processes, detecting hardware fingerprints and detecting specific services.
When virtualization is enabled, most of the above detection methods will fail. As for the hardware fingerprint, VN has many hardware features. The more common detection methods will detect the MAC address of VMware. The default network card MAC address prefix of VMware is "00-05-69, 00-0C-29 or 00-50-56"
. Corresponding tools can be used to modify features to avoid detection.
Summary:
Nowadays, with the increasingly fierce security confrontation, the problem of network security has become a major issue that can not be ignored. As an indispensable auxiliary tool for network security practitioners, the contribution of virtual machine to network security can not be underestimated. In the future, it will certainly be a battleground for strategists, and the detection and confrontation of virtual machine will inevitably become the top priority of attacking cities and regions, With the continuous updating and upgrading of VMWare and the continuous upgrading of Hacker's technical means, I believe there will be more and more technical means to detect virtual machines. At the same time, soldiers will block water and earth, and there will also be more technical means to combat virtual machines, which will be endless and safe.