Raised This Month: $31 Target: $400

[DEV/Windows] Interrupts, undefined opcodes.

Post New Thread Reply   
Thread Tools Display Modes
Author Message
Zero Posts
Join Date: Apr 2019
Location: Russian Federation
Old 02-18-2021 , 12:42   [DEV/Windows] Interrupts, undefined opcodes.
Reply With Quote #1

Interrupt handler based on VEH (SEH) exceptions with unused interrupts and unused opcodes.

  • About SEH and VEH.
  • About Interrupts and unused opcodes.
  • How it works with VEH (SEH)?
  • Why it?

About SEH and VEH.

Structured exception handling (SEH) is a Microsoft extension to C to handle certain exceptional code situations, such as hardware faults, gracefully. Source

Vectored exception handlers are an extension to structured exception handling (SEH). In a nutshell, vectored exception handling is similar to regular SEH, with three key differences:
  • Handlers aren't tied to a specific function nor are they tied to a stack frame.
  • The compiler doesn't have keywords (such as try or catch) to add a new handler to the list of handlers.
  • Vectored exception handlers are explicitly added by your code, rather than as a byproduct of try/catch statements.
Source 1
Source 2

VEH does not replace Structured Exception Handling (SEH), rather VEH and SEH coexist, with VEH handlers having priority over SEH handlers.

About Interrupts and unused opcodes.

In modern operating systems, the programmer often doesn't need to use interrupts. In Windows, for example, the programmer conducts business with the Win32 API. However, these API calls interface with the kernel, and the kernel will often trigger interrupts to perform different tasks. In older operating systems (specifically DOS), the programmer didn't have an API to use, and so they had to do all their work through interrupts. Source
A software interrupt is requested by the processor itself upon executing particular instructions or when certain conditions are met. Every software interrupt signal is associated with a particular interrupt handler. Source

I did do research work and can tell which interrupts are NOT used in the standard windows of the latest version.
Unused interrupts:
  • 0x0F
  • 0x16-0x1E
  • 0x21-0x28
  • 0x2A-0x2B
  • 0x2E
  • 0x37-0x50
  • 0x53-0x60
  • 0x63-0x6F
  • 0x78-0x80
  • 0x83-0x91
  • 0x93-0xA0
  • 0xA4-0xAF
  • 0xB8-0xD0
  • 0xD3-0xD6
  • 0xD9-0xDE
  • 0xE0
  • 0xE4-0xFD
  • 0xFF

Undocumented interrupts:
  • 0x17
  • 0x1A
  • 0x2A
  • 0x47
  • 0x4B
  • 0x53-0x57
  • 0x60
  • 0x69
  • 0x6F
  • 0x79
  • 0x80
  • 0x83-0x85
  • 0xF2-0xF9
  • 0xFC
  • 0xFD

Reserved for user interrupts:
  • 0x63-0x66
  • 0xF1

True unused interrupts (these interrupts should always be unused):
  • 0x7D
  • 0x7E
To avoid errors with driver interrupts and future interrupts, use truly unused interrupts.

Unused (Undefined) opcodes:
Generates an invalid opcode exception. UD (Instruction)
Unused opcodes (instructions):
  • UD (UD0) - 0x0F 0xFF
  • UD1 - 0x0F 0xB9
  • UD2 - 0x0F 0x0B

How it works with VEH (SEH)?

So. We repeated the theory and learned something new, but how does it work? I will briefly talk about this.
The called interrupt refers to the kernel, the kernel executes the code located at a specific address in the interrupt vector. If the interrupt is not used, the address will be "null", and the program code will refer to a non-existent address and throw an exception (0xC0000005 - EXCEPTION_ACCESS_VIOLATION), in this case we can use the exception handler and then read and modify the registers!

Sample program:
PHP Code:
#include <Windows.h>
#include <iostream>

#define CALL_FIRST 1 // Will be called first
#define CALL_LAST  0 // Will be called last after first

PVOID pVEH nullptr;

unsigned charEIP const_cast<const unsigned char*>(reinterpret_cast<unsigned char*>(pExcPtrs->ContextRecord->Eip)); // Exception EIP
if ((EIP[0] == 0x0Fu) && (EIP[1] == 0xFFu) && (pExcPtrs->ExceptionRecord->ExceptionCode == EXCEPTION_ILLEGAL_INSTRUCTION)) { // IF EIP = UD (UD0) AND ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION
pExcPtrs->ContextRecord->Eip += 2// Bypass current instruction
pExcPtrs->ContextRecord->Eax 1// Store 1 in EAX register
    if ((
EIP[0] == 0x0Fu) && (EIP[1] == 0xB9u) && (pExcPtrs->ExceptionRecord->ExceptionCode == EXCEPTION_ILLEGAL_INSTRUCTION)) { // IF EIP = UD1 AND ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION
pExcPtrs->ContextRecord->Eip += 2// Bypass current instruction
pExcPtrs->ContextRecord->Eax 2// Store 2 in EAX register
    if ((
EIP[0] == 0x0Fu) && (EIP[1] == 0x0Bu) && (pExcPtrs->ExceptionRecord->ExceptionCode == EXCEPTION_ILLEGAL_INSTRUCTION)) { // IF EIP = UD2 AND ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION
pExcPtrs->ContextRecord->Eip += 2// Bypass current instruction
pExcPtrs->ContextRecord->Eax 3// Store 3 in EAX register
    if ((
EIP[0] == 0xCDu) && (pExcPtrs->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)) // IF EIP = Interrupt AND ExceptionCode = EXCEPTION_ACCESS_VIOLATION
        switch (
EIP[1]) {
0x7Du: { // IF InterruptNumber is 0x7D (int 0x7D)
pExcPtrs->ContextRecord->Eip += 2// Bypass current instruction
unsigned int edi pExcPtrs->ContextRecord->Edi;
unsigned int esi pExcPtrs->ContextRecord->Esi;
pExcPtrs->ContextRecord->Eax edi esi// EAX=EDI+ESI
0x7Eu: { // IF InterruptNumber is 0x7E (int 0x7E)
pExcPtrs->ContextRecord->Eip += 2// Bypass current instruction
unsigned int edi pExcPtrs->ContextRecord->Edi;
unsigned int esi pExcPtrs->ContextRecord->Esi;
pExcPtrs->ContextRecord->Eax edi esi// EAX=EDI-ESI
pExcPtrs->ContextRecord->Eip += 2// Bypass current instruction
pExcPtrs->ContextRecord->Eax 0// DEFAULT: EAX=0

#define UD0 __asm _emit 0x0F __asm _emit 0xFF
#define UD1 __asm _emit 0x0F __asm _emit 0xB9
#define UD2 __asm _emit 0x0F __asm _emit 0x0B

int main(void) {
#pragma region Adding VEH Handler
pVEH AddVectoredExceptionHandler(CALL_FIRSTVEH);
    if (!
pVEH) {
printf("AddVectoredExceptionHandler error!\n");
#pragma endregion

#pragma region Start
    // Reset+Start
unsigned int v_eax 0u// Variable for EAX
__asm { xor eaxeax // Zeroing the register
__asm mov v_eaxeax // Store EAX register in variable
printf("eax start = %08X\n"v_eax); // Printing variable
#pragma endregion

#pragma region Running UDs
    // UD0
mov v_eaxeax // Store EAX register in variable
printf("eax ud0 = %08X\n"v_eax); // Printing variable
    // UD1
mov v_eaxeax // Store EAX register in variable
printf("eax ud1 = %08X\n"v_eax); // Printing variable
    // UD2
mov v_eaxeax // Store EAX register in variable
printf("eax ud2 = %08X\n"v_eax); // Printing variable
#pragma endregion

#pragma region Running Interrupts
    // int 7D (EAX=EDI+ESI)
__asm mov edi// Store 2 in EDI register
__asm mov esi// Store 2 in ESI register
__asm int 0x7D // Calling Interrupt
__asm mov v_eaxeax // Store EAX register in variable
printf("eax int7D = %08X\n"v_eax); // Printing variable
    // int 7E (EAX=EDI-ESI)
__asm mov edi// Store 2 in EDI register
__asm mov esi// Store 2 in ESI register
__asm int 0x7E // Calling Interrupt
__asm mov v_eaxeax // Store EAX register in variable
printf("eax int7E = %08X\n"v_eax); // Printing variable
    // int F1 (Default: EAX=0)
__asm int 0xF1 // Calling Interrupt
__asm mov v_eaxeax // Store EAX register in variable
printf("eax intF1 = %08X\n"v_eax); // Printing variable
#pragma endregion

#pragma region Removing VEH Handler
if (pVEH) {
#pragma endregion
return 0;

Why it?

The reasons for this may be:
  • Security - The use of interrupts complicates decompilation, but this can be bypassed if it is known that the program uses VEH (SEH).
  • Optimization - Large algorithms can be used without the need to import functions from a specific library, because VEH applies to the entire program and its modules.
  • Fun - How about the BIOS in the program?

Thanks for attention!

Last edited by Sam839; 03-21-2021 at 22:38. Reason: Added exception code for example + added php syntax.
Sam839 is offline

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

All times are GMT -4. The time now is 08:20.

Powered by vBulletin®
Copyright ©2000 - 2021, vBulletin Solutions, Inc.
Theme made by Freecode