X86-assembly/Instructions/sidt

From aldeid
Jump to navigation Jump to search
You are here:
sidt

Description

sidt instruction

The sidt instruction writes the 6-byte Interrupt Descriptor Table (IDT) register to a specified memory region

Syntax

sidt   mem48

Example

sidt  fword ptr [ebp-8]     ; write the 6-byte IDT to memory location pointed to by [ebp-8]
mov   eax, [ebp-6]          ; save IDT base address to eax
cmp   eax, 8003F400h        ; \
jbe   short loc_12345678    ; | check if IDT base address is in range [0x8003F400-0x80047400]
cmp   eax, 80047400h        ; | 0x8003F400 = IDT base address on Windows XP x86
jnb   short loc_12345678    ; /

Red-Pill

"There is only one Interrupt Descriptor Table Register (IDTR), one Global Descriptor Table Register (GDTR) and one Local Descriptor Table Register (LDTR) per processor. Since there are two operating systems running at the same time (the host and the guest), the virtual machine needs to relocate the IDTR, GDTR and LDTR for the guest OS to different locations in order to avoid conflicts. This will cause inconsistencies between the values of these registers in a virtual machine and in the native machine. The instructions SIDT, SGDT and SLDT are assembly instructions that can respectively be used to retreive the values of IDTR, GDTR and LDTR." (Source: http://vrt-blog.snort.org/2009/10/how-does-malware-know-difference.html)

The IDT is stored in the IDTR (Interrupt Descriptor Table Register) and its base adress starts at offset 0x5 in the IDTR:

                                              IDTR Register
                ┌───────────────────────────────────────────┬─────────────────────┐
                │             IDT Base Address              │      IDT Limit      │      
                ├──────────┬──────────┬──────────┬──────────┼──────────┬──────────┤
VMware (hex)    │    FF    │    ??    │    ??    │    ??    │    ??    │    ??    │
VMware (bin)    │ 11111111 │ ???????? │ ???????? │ ???????? │ ???????? │ ???????? │
                └──────────┴──────────┴──────────┴──────────┴──────────┴──────────┘
                ¦          ¦          ¦          ¦          ¦          ¦          ¦
Byte Offset     ¦    0x5   ¦    0x4   ¦    0x3   ¦    0x2   ¦    0x1   ¦    0x0   ¦

The IDT is at:

  • 0x80ffffff in Windows
  • 0xe8XXXXXX in Virtual PC
  • 0xffXXXXXX in VMware

Malware can check the VMware signature (0xFF at offset 0x5) by different ways:

  • check the value at offset 0x5 directly from the IDTR. See {{#switchtablink:Example 1|example #1}}.
  • position at offset 0x2 and shift right 24 bits See {{#switchtablink:Example 2|example #2}}.
  • perform an AND of the value from offset 0x2 to 0x5 with 0xFF000000 See {{#switchtablink:Example 3|example #3}}.

Example 1

push    ebp
mov     ebp, esp
sub     esp, 454h
push    ebx
push    esi
push    ebp
push    8
push    0
lea     eax, [ebp+Dst]
push    eax
call    _memset
add     esp, 0Ch
lea     eax, [ebp+Dst]
sidt    fword ptr [eax]     ; Contents of IDTR saved to memory location pointed to by EAX
mov     al, [eax+5]         ; Start of base memory address (5th byte offset) saved to AL
cmp     al, 0FFh            ; Check whether it is 0xFF (VMware signature)
jnz     short loc_401E19

Example 2

C source

//... SNIP ...

unsigned long
get_idt_base (void)
{
	unsigned char	idtr[6];
	unsigned long	idt	= 0;
 
	_asm sidt idtr
	idt = *((unsigned long *)&idtr[2]);
 
	return (idt);
}

//... SNIP ...

void
test1 (void)
{
	unsigned int 	idt_base	= 0;
 
	idt_base = get_idt_base ();
 
	printf ("[+] Test 1: IDT\n");	
	printf ("IDT base: 0x%x\n", idt_base);
 
	if ((idt_base >> 24) == 0xff) {
		printf ("Result  : VMware detected\n\n");
		return;
	}
 
	else {
		printf ("Result  : Native OS\n\n");
		return;
	}
}

Assembly

.text:00401000 get_idt_base    proc near
.text:00401000
.text:00401000 var_10          = byte ptr -10h
.text:00401000 var_8           = dword ptr -8
.text:00401000 var_4           = dword ptr -4
.text:00401000
.text:00401000                 push    ebp
.text:00401001                 mov     ebp, esp
.text:00401003                 sub     esp, 10h
.text:00401006                 mov     eax, ___security_cookie
.text:0040100B                 xor     eax, ebp
.text:0040100D                 mov     [ebp+var_8], eax
.text:00401010                 mov     [ebp+var_4], 0
.text:00401017                 sidt    fword ptr [ebp+var_10]
.text:0040101B                 mov     eax, dword ptr [ebp+var_10+2]
.text:0040101E                 mov     [ebp+var_4], eax
.text:00401021                 mov     eax, [ebp+var_4]
.text:00401024                 mov     ecx, [ebp+var_8]
.text:00401027                 xor     ecx, ebp
.text:00401029                 call    @__security_check_cookie@4 ; __security_check_cookie(x)
.text:0040102E                 mov     esp, ebp
.text:00401030                 pop     ebp
.text:00401031                 retn
.text:00401031 get_idt_base    endp

;[SNIP]

.text:004010D0 sub_4010D0      proc near
.text:004010D0
.text:004010D0 var_4           = dword ptr -4
.text:004010D0
.text:004010D0                 push    ebp
.text:004010D1                 mov     ebp, esp
.text:004010D3                 push    ecx
.text:004010D4                 mov     [ebp+var_4], 0
.text:004010DB                 call    get_idt_base
.text:004010E0                 mov     [ebp+var_4], eax
.text:004010E3                 push    offset aTest1Idt ; "[+] Test 1: IDT\n"
.text:004010E8                 call    _printf
.text:004010ED                 add     esp, 4
.text:004010F0                 mov     eax, [ebp+var_4]
.text:004010F3                 push    eax
.text:004010F4                 push    offset aIdtBase0xX ; "IDT base: 0x%x\n"
.text:004010F9                 call    _printf
.text:004010FE                 add     esp, 8
.text:00401101                 mov     ecx, [ebp+var_4]
.text:00401104                 shr     ecx, 18h
.text:00401107                 cmp     ecx, 0FFh
.text:0040110D                 jnz     short loc_401120
.text:0040110F                 push    offset aResultVmwareDe ; "Result  : VMware detected\n\n"
.text:00401114                 call    _printf
.text:00401119                 add     esp, 4
.text:0040111C                 jmp     short loc_40112D
.text:0040111E ; ---------------------------------------------------------------------------
.text:0040111E                 jmp     short loc_40112D
.text:00401120 ; ---------------------------------------------------------------------------
.text:00401120
.text:00401120 loc_401120:
.text:00401120                 push    offset aResultNativeOs ; "Result  : Native OS\n\n"
.text:00401125                 call    _printf
.text:0040112A                 add     esp, 4
.text:0040112D
.text:0040112D loc_40112D:
.text:0040112D                 mov     esp, ebp
.text:0040112F                 pop     ebp
.text:00401130                 retn
.text:00401130 sub_4010D0      endp

Example 3

Thwart SIDT

To thwart this technique, use one of the following techniques:

  • run on a multicore processor machine
  • NOP-out the sidt instruction
  • Modify the jump following the test


Comments

Keywords: sidt red-pill