Code:
/*SEH based VM Engine by Yattering, 2016
*e-mail: yattering (at) sigaint (d0t) org
*jabber: yattering (at) xmpp (d0t) jp
*/
#define WIN32_LEAN_AND_MEAN
#ifdef SELF_TEST
#define __DEBUG__
#endif
#include <windows.h>
#include <stdint.h>
#include "debug_log.h"
#include "sehvm.h"
#ifdef SELF_TEST
#pragma comment(linker, "/ENTRY:main")
#pragma comment(linker, "/SUBSYSTEM:WINDOWS")
#endif
EXCEPTION_DISPOSITION __cdecl exception_handler(struct _EXCEPTION_RECORD *except, void * establisher_frame, struct _CONTEXT *context, void *dispatcher_context);
__DEBUG_GLOBAL_VARIABLES()
EXCEPTION_DISPOSITION __cdecl exception_handler(struct _EXCEPTION_RECORD *except, void * establisher_frame, struct _CONTEXT *context, void *dispatcher_context) {
uint8_t reg;
uint8_t *p_nnm = except->ExceptionAddress;
__DEBUG_PUTS("\r\nEXCEPTION HANDLER\r\n");
if (*p_nnm == SEHVM_INT3_OPCODE) {
p_nnm++;
switch (*p_nnm) {
case SEHVM_TYPE_RET_C8:
__DEBUG_PRINTF("] NANOMITE TYPE <RET_C8>\r\n]] RET 0x%X\r\n", p_nnm[1]);
uint32_t ret_addr = *(uint32_t *)(context->Esp);
context->Esp += 4 + p_nnm[1];
context->Eip = ret_addr;
__DEBUG_PAUSE();
break;
case SEHVM_TYPE_PUSH_C32: {
__DEBUG_PRINTF("] NANOMITE TYPE <PUSH_C32>\r\n]] PUSH 0x%X\r\n", (*(uint32_t *)&p_nnm[1]));
context->Esp-=4;
*(uint32_t *) context->Esp = *(uint32_t *) &p_nnm[1];
context->Eip += 0x6;
__DEBUG_PAUSE();
break;
}
case SEHVM_TYPE_PUSH_R32: {
reg = p_nnm[1] & 0x7;
#ifdef __DEBUG__
char *reg_name = \
((reg == SEHVM_ARG_EAX)?("EAX"):((reg == SEHVM_ARG_EBX)?("EBX"):((reg == SEHVM_ARG_ECX)?("ECX"):\
((reg == SEHVM_ARG_EDX)?("EDX"):((reg == SEHVM_ARG_EDI)?("EDI"):((reg == SEHVM_ARG_ESI)?("ESI"):\
((reg == SEHVM_ARG_EBP)?("EBP"):"INVALID_REGISTER")))))));
__DEBUG_PRINTF("] NANOMITE TYPE <PUSH_R32>\r\n]] PUSH %s\r\n", reg_name);
uint32_t reg_val =
((reg == SEHVM_ARG_EAX)?(context->Eax):\
((reg == SEHVM_ARG_EBX)?(context->Ebx):\
((reg == SEHVM_ARG_ECX)?(context->Ecx):\
((reg == SEHVM_ARG_EDX)?(context->Edx):\
((reg == SEHVM_ARG_EDI)?(context->Edi):\
((reg == SEHVM_ARG_ESI)?(context->Esi):\
((reg == SEHVM_ARG_EBP)?(context->Ebp):\
0xDEADBEEF)))))));
__DEBUG_PRINTF("]]] %s = 0x%X\r\n", reg_name, reg_val);
#endif
context->Esp-=4;
*(uint32_t *)(context->Esp) = \
((reg == SEHVM_ARG_EAX)?(context->Eax):\
((reg == SEHVM_ARG_EBX)?(context->Ebx):\
((reg == SEHVM_ARG_ECX)?(context->Ecx):\
((reg == SEHVM_ARG_EDX)?(context->Edx):\
((reg == SEHVM_ARG_EDI)?(context->Edi):\
((reg == SEHVM_ARG_ESI)?(context->Esi):\
((reg == SEHVM_ARG_EBP)?(context->Ebp):\
0xDEADBEEF)))))));
context->Eip += 0x3;
__DEBUG_PAUSE();
break;
}
case SEHVM_TYPE_POP_R32: {
reg = p_nnm[1] & 0x7;
#ifdef __DEBUG__
char *reg_name = \
((reg == SEHVM_ARG_EAX)?("EAX"):((reg == SEHVM_ARG_EBX)?("EBX"):((reg == SEHVM_ARG_ECX)?("ECX"):\
((reg == SEHVM_ARG_EDX)?("EDX"):((reg == SEHVM_ARG_EDI)?("EDI"):((reg == SEHVM_ARG_ESI)?("ESI"):\
((reg == SEHVM_ARG_EBP)?("EBP"):"INVALID_REGISTER")))))));
if (reg == SEHVM_ARG_INVALID_REGISTER) {
__DEBUG_PRINTF("] NANOMITE TYPE <NOP1>\r\n");
} else {
__DEBUG_PRINTF("] NANOMITE TYPE <POP_R32>\r\n]] POP %s\r\n", reg_name);
uint32_t reg_val =
((reg == SEHVM_ARG_EAX)?(context->Eax):\
((reg == SEHVM_ARG_EBX)?(context->Ebx):\
((reg == SEHVM_ARG_ECX)?(context->Ecx):\
((reg == SEHVM_ARG_EDX)?(context->Edx):\
((reg == SEHVM_ARG_EDI)?(context->Edi):\
((reg == SEHVM_ARG_ESI)?(context->Esi):\
(context->Ebp)))))));
__DEBUG_PRINTF("]]] BEFORE: %s = 0x%X ", reg_name, reg_val);
}
#endif
if (reg != SEHVM_ARG_INVALID_REGISTER) {
*((reg == SEHVM_ARG_EAX)?(&context->Eax):\
((reg == SEHVM_ARG_EBX)?(&context->Ebx):\
((reg == SEHVM_ARG_ECX)?(&context->Ecx):\
((reg == SEHVM_ARG_EDX)?(&context->Edx):\
((reg == SEHVM_ARG_EDI)?(&context->Edi):\
((reg == SEHVM_ARG_ESI)?(&context->Esi):\
(&context->Ebp))))))) = *(uint32_t *)(context->Esp);
context->Esp += 0x4;
}
#ifdef __DEBUG__
if (reg != SEHVM_ARG_INVALID_REGISTER) {
uint32_t reg_val = \
((reg == SEHVM_ARG_EAX)?(context->Eax):\
((reg == SEHVM_ARG_EBX)?(context->Ebx):\
((reg == SEHVM_ARG_ECX)?(context->Ecx):\
((reg == SEHVM_ARG_EDX)?(context->Edx):\
((reg == SEHVM_ARG_EDI)?(context->Edi):\
((reg == SEHVM_ARG_ESI)?(context->Esi):\
(context->Ebp)))))));
__DEBUG_PRINTF("AFTER: %s = 0x%X \r\n", reg_name, reg_val);
}
#endif
context->Eip += 0x3;
__DEBUG_PAUSE();
break;
}
case SEHVM_TYPE_JMP_REL_C32:
__DEBUG_PUTS("] NANOMITE TYPE <JMP_REL_C32>\r\n");
__DEBUG_PRINTF("]] JMP_REL_C32 0x%X\r\n", *(uint32_t *)&p_nnm[1]);
__DEBUG_PRINTF("]]] BEFORE: EIP = 0x%X\r\n", context->Eip);
context->Eip += *(uint32_t *)&p_nnm[1];
__DEBUG_PRINTF("AFTER: EIP = 0x%X\r\n", context->Eip);
__DEBUG_PAUSE();
break;
case SEHVM_TYPE_CALL_REL_C32:
__DEBUG_PUTS("] NANOMITE TYPE <CALL_REL_C32>\r\n");
__DEBUG_PRINTF("]] JMP_CALL_C32 0x%X\r\n", *(uint32_t *)&p_nnm[1]);
__DEBUG_PRINTF("]]] BEFORE: EIP = 0x%X\r\n", context->Eip);
context->Esp -= 4;
*(uint32_t *)(context->Esp) = context->Eip + 0x6;
context->Eip += *(uint32_t *)(&p_nnm[1]);
__DEBUG_PRINTF("AFTER: EIP = 0x%X\r\n", context->Eip);
__DEBUG_PAUSE();
break;
};
};
return(ExceptionContinueExecution);
}
#ifndef SELF_TEST
/*
void __declspec(naked) exception_handler_end(void) {
__asm _emit(0xCA) __asm _emit(0xFE) __asm _emit(0xDE) __asm _emit(0xAD);
} */
#endif
#ifdef SELF_TEST
int main(void) {
__DEBUG_INIT();
__asm {
xor ecx, ecx
push offset exception_handler
push DWord Ptr fs:[ecx]
mov DWord Ptr fs:[ecx], esp
}
__DEBUG_PUTS(" [[[ START SEH BASED VM ENGINE TESTING ]]] \r\n\r\n");
__DEBUG_PUTS("TESTED COMMAND <PUSH_R32 EAX>\r\n");
SEHVM_PUSH_R32(SEHVM_ARG_EAX);
__asm pop eax
__DEBUG_PUTS("TESTED COMMAND <PUSH_R32 EBX>\r\n");
SEHVM_PUSH_R32(SEHVM_ARG_EBX)
__asm pop eax
__DEBUG_PUTS("TESTED COMMAND <PUSH_R32 ECX>\r\n");
SEHVM_PUSH_R32(SEHVM_ARG_ECX)
__asm pop eax
__DEBUG_PUTS("TESTED COMMAND <PUSH_R32 EDX>\r\n");
SEHVM_PUSH_R32(SEHVM_ARG_EDX)
__asm pop eax
__DEBUG_PUTS("TESTED COMMAND <PUSH_R32 EDI>\r\n");
SEHVM_PUSH_R32(SEHVM_ARG_EDI)
__asm pop eax
__DEBUG_PUTS("TESTED COMMAND <PUSH_R32 ESI>\r\n");
SEHVM_PUSH_R32(SEHVM_ARG_ESI)
__asm pop eax
__DEBUG_PUTS("TESTED COMMAND <PUSH_R32 EBP>\r\n");
SEHVM_PUSH_R32(SEHVM_ARG_EBP)
__asm pop eax
__DEBUG_PUTS("TESTED COMMAND <PUSH_R32 INVALID_REGISTER>\r\n");
SEHVM_PUSH_R32(SEHVM_ARG_INVALID_REGISTER)
__asm pop eax
__DEBUG_PUTS("TESTED COMMAND <POP_R32 EAX>\r\nTOS VALUE = 0xDEADBEEF\r\n");
__asm push eax
__asm push 0xDEADBEEF
SEHVM_POP_R32(SEHVM_ARG_EAX)
__asm pop eax
__DEBUG_PUTS("TESTED COMMAND <POP_R32 EBX>\r\nTOS VALUE = 0xDEADCAFE\r\n");
__asm push ebx
__asm push 0xDEADCAFE
SEHVM_POP_R32(SEHVM_ARG_EBX)
__asm pop ebx
__DEBUG_PUTS("TESTED COMMAND <POP_R32 ECX>\r\nTOS VALUE = 0xDEADCAFE\r\n");
__asm push ecx
__asm push 0xDEADCAFE
SEHVM_POP_R32(SEHVM_ARG_ECX)
__asm pop ecx
__DEBUG_PUTS("TESTED COMMAND <POP_R32 EDX>\r\nTOS VALUE = 0xDEADCAFE\r\n");
__asm push edx
__asm push 0xDEADCAFE
SEHVM_POP_R32(SEHVM_ARG_EDX)
__asm pop edx
__DEBUG_PUTS("TESTED COMMAND <POP_R32 ESI>\r\nTOS VALUE = 0xDEADCAFE\r\n");
__asm push esi
__asm push 0xDEADCAFE
SEHVM_POP_R32(SEHVM_ARG_ESI)
__asm pop esi
__DEBUG_PUTS("TESTED COMMAND <POP_R32 EDI>\r\nTOS VALUE = 0xDEADCAFE\r\n");
__asm push edi
__asm push 0xDEADCAFE
SEHVM_POP_R32(SEHVM_ARG_EDI)
__asm pop edi
__DEBUG_PUTS("TESTED COMMAND <POP_R32 EBP>\r\nTOS VALUE = 0xDEADCAFE\r\n");
__asm push ebp
__asm push 0xDEADCAFE
SEHVM_POP_R32(SEHVM_ARG_EBP)
__asm pop ebp
__DEBUG_PUTS("TESTED COMMAND <NOP>\r\n");
SEHVM_NOP();
__DEBUG_PUTS("TESTED COMMAND <SEHVM_JMP_REL_C32>\r\n");
SEHVM_JMP_REL_C32(0x6);
__DEBUG_PUTS("\r\n\r\n [[[ END SEH BASED VM ENGINE TESTING ]]] \r\n\r\n");
__DEBUG_PAUSE();
__asm {
pop DWord Ptr fs:[0]
pop eax
}
return(0x0);
};
#endif