#define WIN32_LEAN_AND_MEAN #define STRICT #include #include #include #include #include #include #include #include static unsigned int nRandBytes; static int initrand(void) { unsigned int nRandMax; unsigned int nRandMaxBits; time_t tLoc; nRandMax = RAND_MAX; for(nRandMaxBits = 0; nRandMax != 0; nRandMax >>= 1, ++ nRandMaxBits); nRandBytes = nRandMaxBits / CHAR_BIT; assert(nRandBytes != 0); srand((unsigned)(time(&tLoc) & UINT_MAX)); return 1; } static void randbytes(void * p, size_t n) { unsigned char * b; size_t i; int r = rand(); b = (unsigned char *)p; for(i = 0; i < n; ++ i) { if(i % nRandBytes == 0) r = rand(); b[i] = (unsigned char)(r & UCHAR_MAX); r >>= CHAR_BIT; } } static ULONG randULONG(void) { ULONG n; randbytes(&n, sizeof(n)); return n; } #ifdef _M_IX86 #define ZWC_SEGMENT_BITS (0xFFFF) #define ZWC_EFLAGS_BITS (0x3C0CD5) #endif static jmp_buf jmpbuf; static CONTEXT continueContext; extern void continuePoint(void); extern void check(CONTEXT *); extern LONG NTAPI ZwContinue(IN CONTEXT *, IN BOOLEAN); void check(CONTEXT * actualContext) { #ifdef _M_IX86 assert(actualContext->ContextFlags == CONTEXT_FULL); /* Random data segments */ assert ( (actualContext->SegGs & ZWC_SEGMENT_BITS) == (continueContext.SegGs & ZWC_SEGMENT_BITS) ); assert ( (actualContext->SegFs & ZWC_SEGMENT_BITS) == (continueContext.SegFs & ZWC_SEGMENT_BITS) ); assert ( (actualContext->SegEs & ZWC_SEGMENT_BITS) == (continueContext.SegEs & ZWC_SEGMENT_BITS) ); assert ( (actualContext->SegDs & ZWC_SEGMENT_BITS) == (continueContext.SegDs & ZWC_SEGMENT_BITS) ); /* Integer registers */ assert(actualContext->Edi == continueContext.Edi); assert(actualContext->Esi == continueContext.Esi); assert(actualContext->Ebx == continueContext.Ebx); printf("%s %lX : %lX\n", "Edx", actualContext->Edx, continueContext.Edx); //assert(actualContext->Edx == continueContext.Edx); assert(actualContext->Ecx == continueContext.Ecx); assert(actualContext->Eax == continueContext.Eax); /* Control registers and segments */ assert(actualContext->Ebp == continueContext.Ebp); assert(actualContext->Eip == continueContext.Eip); assert ( (actualContext->SegCs & ZWC_SEGMENT_BITS) == (continueContext.SegCs & ZWC_SEGMENT_BITS) ); assert ( (actualContext->EFlags & ZWC_EFLAGS_BITS) == (continueContext.EFlags & ZWC_EFLAGS_BITS) ); assert(actualContext->Esp == continueContext.Esp); assert ( (actualContext->SegSs & ZWC_SEGMENT_BITS) == (continueContext.SegSs & ZWC_SEGMENT_BITS) ); #endif longjmp(jmpbuf, 1); } int main(void) { initrand(); /* First time */ if(setjmp(jmpbuf) == 0) { CONTEXT bogus; continueContext.ContextFlags = CONTEXT_FULL; GetThreadContext(GetCurrentThread(), &continueContext); #ifdef _M_IX86 continueContext.ContextFlags = CONTEXT_FULL; /* Fill the integer registers with random values */ continueContext.Edi = randULONG(); continueContext.Esi = randULONG(); continueContext.Ebx = randULONG(); continueContext.Edx = randULONG(); continueContext.Ecx = randULONG(); continueContext.Eax = randULONG(); continueContext.Ebp = randULONG(); /* Randomize all the allowed flags (determined experimentally with WinDbg) */ continueContext.EFlags = randULONG() & 0x3C0CD5; /* Randomize the stack pointer as much as possible */ continueContext.Esp = (ULONG)(((ULONG_PTR)&bogus) & 0xFFFFFFFF) + sizeof(bogus) - (randULONG() & 0xF) * 4; /* continuePoint() is implemented in assembler */ continueContext.Eip = (ULONG)((ULONG_PTR)continuePoint & 0xFFFFFFF); /* Can't do a lot about segments */ #endif ZwContinue(&continueContext, FALSE); } /* Second time */ else return 0; assert(0); return 1; }