X86-assembly/Instructions/sidt
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