// precomp.h #pragma once #include #include #include #include #include #include "looper.h" // looper.h #pragma once // Typdef for the function to pass as an argument to the looping function. typedef VOID(*looperfunc)(ULONG, PVOID); VOID ExecuteLoop(ULONG count, looperfunc); // looper.c #include "precomp.h" #include #define STACK_RESET_LIMIT 1024 * 800 // 800kb, we should reset typedef struct _loopcontext { ULONG current; // Current count ULONG maximum; // Maximum count jmp_buf jumpBuffer; // Buffer to store the jump location for longjump looperfunc func; // The function to execute ULONG stackStart; // the bottom of the stack } loopcontext, *Ploopcontext; ULONG findStackBase() { // EBP points to the previous value of ebp on the stack PULONG baseptr; __asm { mov baseptr, ebp } // Traverse the list until we get to the end. while (NULL != *baseptr) { baseptr = (PULONG)*baseptr; } return (ULONG)baseptr; } VOID loopHelper(Ploopcontext context) { // Base condition if (context->current >= context->maximum) { return; } // Get the value of esp ULONG currentStackPtr; __asm { mov currentStackPtr, esp }; // Execute our callback context->func(context->current, NULL); // Increment the loop counter context->current++; // Find our distance from the base of the stack (the stack grows downwards) ULONG distance = (context->stackStart - currentStackPtr); if (distance >= STACK_RESET_LIMIT) { longjmp((int*)&context->jumpBuffer, 1); } // Recurse loopHelper(context); } /// /// Execute a loop, using recursion /// VOID ExecuteLoop(ULONG count, looperfunc func) { // Initialize the loop context loopcontext context; context.current = 0; context.maximum = count; context.func = func; context.stackStart = findStackBase(); setjmp((int*)&context.jumpBuffer); // Run the loop loopHelper(&context); } // main.c #include "precomp.h" #include "looper.h" // This is the func VOID testfunc(ULONG l, PVOID val) { ULONG buffer[400]; printf("looping %u \n", l); } int main(int arc, char ** argv) { ExecuteLoop(10000, testfunc); return 0; }