RDTSC is an instruction used to read a processor’s time stamp counter. Reading it twice allows to calculate a delta between the values of the time stamp counter and if the obtained delta is significantly large, use it as a detection of a debugger, emulator, or a virtual environment.
rdtsc mov ebx,eax rdtsc sub eax,ebx cmp eax,DELTA jb ok ... suspicious environment detected ... ok:
It’s a really old anti-reversing trick (and it has many variants) which can be recognized/instrumented/bypassed by making RDTSC a privileged instruction (e.g. using a Phantom plugin for OllyDbg), or simply by patching the code.
Newer processors support a new instruction called RDTSCP that does exactly the same thing as RDTSC, except it is doing it in a serializing way (which means it waits for all instructions to execute before reading the counter and the possible re-ordering of instruction execution won’t happen). It can be used to calculate the time stamp counter delta the same way as RDTSC and as a result detect the fact of program being debugged, emulated, or ran inside a virtual environment.
This is nothing groundbreaking (read: it’s kinda lame), but since it could be used as a ‘yet another anti-‘ trick it is still worth documenting.
rdtscp mov ebx,eax rdtscp sub eax,ebx cmp eax,DELTA jb ok ... suspicious environment detected ... ok:
The opcode for RDTSCP is 0F 01 F9 so you can embed it inline if your assembler doesn’t support it.
OllyDbg 1.x recognizes RDTSCP as:
-
0F01F9 INVLPG CL
The OllyDbg 2.x recognizes it correctly as
-
0F01F9 rdtscp
RDTSCP is not recognized by Virtual PC 2007 and older hardware. One can use a cpuid to determine support for this instruction, or simply attempt running it and catch the STATUS_ILLEGAL_INSTRUCTION exception if the instruction is invalid.
One thing to note: RDTSC(P) delta trick doesn’t detect virtual environments very well – running samples ‘live’ inside VMWare easily fools malware that they run on the ‘real’ computer (unless they use other vm detection tricks, or the delta is really small – kinda silly idea since it would prevent running the malware on slower systems). As mentioned above, if used in debugging/tracing context RDTSC(P) can be quite successful. It would be interesting to find out how it performs under various emulators, but I don’t use them so I could not test it.
Results of running under VM are below:
- Host (Windows 7SP1 x64):
- rdtscp delta=27, rdtsc delta=21
- rdtscp delta=56, rdtsc delta=18
- rdtscp delta=27, rdtsc delta=140
- rdtscp delta=56, rdtsc delta=18
- rdtscp delta=76, rdtsc delta=60
- rdtscp delta=27, rdtsc delta=29
- rdtscp delta=38, rdtsc delta=21
- VMWare Workstation 10.0.2, guest OS: Windows XP SP3 32:
- rdtscp delta=241, rdtsc delta=325
- rdtscp delta=241, rdtsc delta=399
- rdtscp delta=236, rdtsc delta=331
- rdtscp delta=236, rdtsc delta=405
- rdtscp delta=265, rdtsc delta=304
- rdtscp delta=265, rdtsc delta=349
- rdtscp delta=265, rdtsc delta=340
- VMWare Workstation 10.0.2, guest OS: Windows 7 SP1 32:
- rdtscp delta=56, rdtsc delta=18
- rdtscp delta=27, rdtsc delta=21
- rdtscp delta=56, rdtsc delta=18
- rdtscp delta=27, rdtsc delta=21
- rdtscp delta=56, rdtsc delta=18
- rdtscp delta=27, rdtsc delta=18
- rdtscp delta=56, rdtsc delta=21
- VMWare Workstation 10.0.2, guest OS: Windows 7 SP1 64:
- rdtscp delta=27, rdtsc delta=21
- rdtscp delta=56, rdtsc delta=18
- rdtscp delta=27, rdtsc delta=47
- rdtscp delta=27, rdtsc delta=18
- rdtscp delta=56, rdtsc delta=18
- rdtscp delta=56, rdtsc delta=18
- rdtscp delta=27, rdtsc delta=21
- Virtual Box 4.3.10, guest OS: Windows XP SP3 32:
- rdtscp delta=64, rdtsc delta=64
- rdtscp delta=27, rdtsc delta=47
- rdtscp delta=27, rdtsc delta=18
- rdtscp delta=27, rdtsc delta=18
- rdtscp delta=56, rdtsc delta=21
- rdtscp delta=27, rdtsc delta=21
- rdtscp delta=27, rdtsc delta=50
- rdtscp delta=27, rdtsc delta=47
You can download the test program here.