原文由coolq发表,文章转载自他的博客 VMware的后门( 二 )


Vmware 4.0.0.4460 和 vmware 4.0.5.6030 。宿主机 Windows 2003 Standard 。
GuestOS RedHat 8 (Kernel 2.6.2, gcc 3.2) 。
IDApro 用于静态分析 , OllyDBG 用于动态调试 。
静态分析 vmware-checkvm 程序发现这个后门 。
静态分析动态调试得到各功能信息 。
How To Detect VMM Using (Almost) One CPU Instruction
Added by: A^C^E
Date: 18.11.04
Time: 08:52:13
Category: Article
Source: http://www.securiteam.com/securityreviews/6Z00H20BQS.html
Summary
The attached short (4 lines of code, that generate almost a single CPU instruction) exploit code can be used to detect whether the code is executed under a VMM or under a real environment. In addition to the exploit code, a detailed explanation of how this was found and why it works are also provided.
Details
Swallowing the Red Pill is more or less equivalent to the following code (returns non zero when in Matrix):
int swallow_redpill () {
unsigned char m[2 4], rpill[] = "/x0f/x01/x0d/x00/x00/x00/x00/xc3";
*((unsigned*)&rpill[3]) = (unsigned)m;
((void(*)())&rpill)();
return (m[5]>0xd0) ? 1 : 0;
}
The heart of this code is actually the SIDT instruction (encoded as 0F010D[addr]), which stores the contents of the interrupt descriptor table register (IDTR) in the destination operand, which is actually a memory location. What is special and interesting about SIDT instruction is that, it can be executed in non privileged mode (ring3) but it returns the contents of the sensitive register, used internally by operating system.
Because there is only one IDTR register, but there are at least two OS running concurrently (i.e. the host and the guest OS), VMM needs to relocate the guest"s IDTR in a safe place, so that it will not conflict with a host"s one. Unfortunately, VMM cannot know if (and when) the process running in guest OS executes SIDT instruction, since it is not privileged (and it doesn"t generate exception). Thus the process gets the relocated address of IDT table. It was observed that on VMWare, the relocated address of IDT is at address 0xffXXXXXX, whereas on Virtual PC it is 0xe8XXXXXX. This was tested on VMWare Workstation 4 and Virtual PC 2004, both running on Windows XP host OS.
Joanna Rutkowska came across this strange behavior of SIDT instruction a few years ago, when Joanna Rutkowska was testing Suckit rootkit on VMWare. Joanna Rutkowska noticed that it failed to load on VMWare whereas it seemed to work fine on the same distribution ran outside VM. After spending many hours Joanna Rutkowska figured out that the problematic instruction was actually SIDT, which was used by Suckit to get the address of the IDT table, and to hook its 0x80 entry through /dev/kmem device.
However, Joanna Rutkowska was not the first one who discovered this trick. Shortly after her adventure with Suckit Joanna Rutkowska found a very good USENIX paper about problems when implementing Virtual Machines on Intel processors, discussing of course SIDT problem, as well as many others.
So now, here is the simple code, written in C, which should compile on any all Intel based OS. Just in case you don"t have the C compiler for Windows, there is also a binary version attached.
NOTE: This program will fail on systems with PAX/X^W/grsecurity, protection (as it was pointed out by Brad Spengler) since the rpill variable is not marked as executable. To make it run in such systems, mprotect() should be used to mark rpill with PROT_EXEC attribute. Another solution would be to just use asm() keyword instead of shellcode-like buffer. However, this program should be rather considered as a skeleton to build into your own shellcode, rather then standalone production class tool. In addition, Joanna"s goal was to make it as simple and portable as possible. That"s why Joanna didn"t use asm() nor mprotect() since they are system or compiler dependent.
Joanna is also aware of another implementation of this technique, as well as some other tricks to fingerprint VMWare, which can be found at http://www.trapkit.de/.

推荐阅读