__declspec(noreturn)
void _my_longjmp(jmp_buf jb, int value)
{
#ifdef _M_IX86
static const uint32_t shellcode_my_longjmp[] =
{
0x0424548B,
0x0824448B,
0x8301F883,
0x2A8B00D0,
0x8B045A8B,
0x728B087A,
0x10628B0C,
0xFF04C483,
0x90901462,
};
#elif defined(_M_X64)
static const uint64_t shellcode_my_longjmp[] =
{
0x4808598B48D08948,
0x4818698B4810618B,
0x4C28798B4820718B,
0x4C38698B4C30618B,
0x0F48798B4C40718B,
0x5C69D9E2DB5851AE,
0x6F0F6660716F0F66,
0x80816F0F44667079,
0x896F0F4466000000,
0x6F0F446600000090,
0x0F4466000000A091,
0x4466000000B0996F,
0x66000000C0A16F0F,
0x000000D0A96F0F44,
0x0000E0B16F0F4466,
0x00F0B96F0F446600,
0x9090905061FF0000,
};
#else
// If your computer is not x86 nor x64, implement your own `longjmp()` shellcode for your CPU.
longjmp(jb, value);
#endif
static DWORD dwOldProtect = 0;
if (!dwOldProtect) VirtualProtect((void *)shellcode_my_longjmp, sizeof shellcode_my_longjmp, PAGE_EXECUTE_READ, &dwOldProtect);
void(*my_longjmp)(jmp_buf jb, int value) = (void *)shellcode_my_longjmp;
my_longjmp(jb, value);
}
_jmp_to_new_stack()
__declspec(noreturn)
void _jmp_to_new_stack(void *stack_buffer, size_t stack_size, void(*function_to_run)(void *userdata), void *userdata, jmp_buf returning, int longjmp_val)
{
#ifdef _M_IX86
static const uint32_t shellcode_jmp_to_new_stack[] =
{
0x608be089,
0x08600304,
0xff1870ff,
0x70ff1470,
0x0c50ff10,
0x6804c483,
0xdeadbeef,
0x909002eb,
0x0424548b,
0x0824448b,
0x8301f883,
0x2a8b00d0,
0x8b045a8b,
0x728b087a,
0x10628b0c,
0xff04c483,
0x90901462,
};
#elif defined(_M_X64)
static const uint64_t shellcode_jmp_to_new_stack[] =
{
0x0148cc8948e08948,
0x4c2870ff3070ffd4,
0xff4120ec8348c989,
0xeb5a5920c48348d0,
0x9090909090909007,
0x4808598b48d08948,
0x4818698b4810618b,
0x4c28798b4820718b,
0x4c38698b4c30618b,
0x0f48798b4c40718b,
0x5c69d9e2db5851ae,
0x6f0f6660716f0f66,
0x80816f0f44667079,
0x896f0f4466000000,
0x6f0f446600000090,
0x0f4466000000a091,
0x4466000000b0996f,
0x66000000c0a16f0f,
0x000000d0a96f0f44,
0x0000e0b16f0f4466,
0x00f0b96f0f446600,
0x9090905061ff0000,
};
#else
fprintf(stderr, "[UNIMPLEMENTED] Please provide your shellcode for your CPU to implement `jmp_to_new_stack()` by doing these steps:\n");
fprintf(stderr, "[UNIMPLEMENTED] Save your current stack pointer register to a volatile register whichever you'd like to use, the volatile register stores your original stack pointer and could help you to retrieve your parameters;\n");
fprintf(stderr, "[UNIMPLEMENTED] Set your stack pointer register to the end of my stack buffer: `(size_t)stack_buffer + stack_size`;\n");
fprintf(stderr, "[UNIMPLEMENTED] After moving to the new stack, save your 5th and 6th paramters to the new stack;\n");
fprintf(stderr, "[UNIMPLEMENTED] Retrieve your 4th parameter `userdata` from the original stack (using the saved stack pointer in the volatile register);\n");
fprintf(stderr, "[UNIMPLEMENTED] Your 3rd parameter is a pointer to a callback function (the function to run on the new stack). Call it and pass `userdata`. NOTE: This function will destroy your volatile register as usual occasion;\n");
fprintf(stderr, "[UNIMPLEMENTED] After calling the function, balance your stack;\n");
fprintf(stderr, "[UNIMPLEMENTED] Retrieve your 5th (`jmp_buf`) and 6th (`longjmp_value`) parameters from where you saved them on the new stack, these parameters are for returning to your previous stack via a `longjmp()`;\n");
fprintf(stderr, "[UNIMPLEMENTED] IMPORTANT: Both stacks are actively changing, do not attempt to restore the stack pointer directly;\n");
fprintf(stderr, "[UNIMPLEMENTED] Implement and execute a `longjmp(jmp_buf, longjmp_value)` to return to the original stack\n");
assert(0);
#endif
static DWORD dwOldProtect = 0;
if (!dwOldProtect) VirtualProtect((void *)shellcode_jmp_to_new_stack, sizeof shellcode_jmp_to_new_stack, PAGE_EXECUTE_READ, &dwOldProtect);
void(*jmp_to_new_stack)(void *, size_t, void(*)(void *), void *, jmp_buf, int) = (void *)shellcode_jmp_to_new_stack;
jmp_to_new_stack(stack_buffer, stack_size, function_to_run, userdata, returning, longjmp_val);
}