Borrowing from "shellcode" fundamentals, this technique abuses an RDTSC instruction found within the Windows DLL NTDLL.DLL function ReleaseBufferLocation(). By utilizing a pre-existing RDTSC instruction we can avoid detection from simple binary scans for the RDTSC (\x0F\x31) byte sequence. Here is the discovered RDTSC instruction from Windows XP SP2:
WINXPSP2.NTDLL.ReleaseBufferLocation():
.text:7C973215 mov ecx, [eax+4] // we *could* jump as high as this point
.text:7C973218 add ecx, eax
.text:7C97321A mov dword ptr [ecx], 0C0100001h
--->.text:7C973220 rdtsc // ecx should point to the caller stack
.text:7C973222 mov [ecx+8], eax // save the low dword
.text:7C973225 mov [ecx+0Ch], edx // save the high dword
.text:7C973228
.text:7C973228 loc_7C973228:
.text:7C973228 add esi, 0Ch
.text:7C97322B or eax, 0FFFFFFFFh
.text:7C97322E lock xadd [esi], eax // esi must point to writeable memory
.text:7C973232 mov eax, offset _WmipLoggerCount
.text:7C973237 or ecx, 0FFFFFFFFh
.text:7C97323A lock xadd [eax], ecx
.text:7C97323E pop esi // esi gets blows away, save/restore if needed
.text:7C97323F pop ebp // ebp gets blown away, save/restore in caller
.text:7C973240 retn 4 // need to pad two DWORDS for RET address
In my brief search through the system DLLs for a suitable RDTSC instruction followed by a retn, the above (legitimate, ie: a real instruction and not just a byte match) example was the only one I found. There may be others, it's been a while since I've looked at this, so I forget where I even scanned.
To abuse the above sequence, we craft and call the following function:
int obfuscated_rdtsc (void)
{
int stack_space[32];
__asm
{
jmp __end
__begin:
pop ebx
mov ecx, esp
add ecx, 4
mov esi, esp
add esi, 0x10
push ebp
push 1
push ebx
push 2
push 3
mov eax, 0x7c973220
jmp eax
__end:
call __begin
pop ebp
}
return stack_space[0];
}
A compiled example and source code is available in the obfuscated_rdtsc.zip archive. Note that the sample threshold values I use were just for experimentation and will need to modified to something sane (that won't false positive).
|