Raised This Month: $128 Target: $400
 32% 

[DEV/Windows] Interrupts, undefined opcodes.


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

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

Content:
  • 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.

Interrupts:
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:
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;

LONG WINAPI VEH(PEXCEPTION_POINTERS pExcPtrs) {
	const unsigned char* EIP = const_cast<const unsigned char*>(reinterpret_cast<unsigned char*>(pExcPtrs->ContextRecord->Eip)); // Exception EIP
	if ((EIP[0] == 0x0Fu) && (EIP[1] == 0xFFu)) { // IF EIP = UD (UD0)
		pExcPtrs->ContextRecord->Eip += 2; // Bypass current instruction
		pExcPtrs->ContextRecord->Eax = 1; // Store 1 in EAX register
		return EXCEPTION_CONTINUE_EXECUTION;
	}
	if ((EIP[0] == 0x0Fu) && (EIP[1] == 0xB9u)) { // IF EIP = UD1
		pExcPtrs->ContextRecord->Eip += 2; // Bypass current instruction
		pExcPtrs->ContextRecord->Eax = 2; // Store 2 in EAX register
		return EXCEPTION_CONTINUE_EXECUTION;
	}
	if ((EIP[0] == 0x0Fu) && (EIP[1] == 0x0Bu)) { // IF EIP = UD2
		pExcPtrs->ContextRecord->Eip += 2; // Bypass current instruction
		pExcPtrs->ContextRecord->Eax = 3; // Store 3 in EAX register
		return EXCEPTION_CONTINUE_EXECUTION;
	}
	if ((EIP[0] == 0xCDu) && (pExcPtrs->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)) // IF EIP = Interrupt AND ExceptionCode = EXCEPTION_ACCESS_VIOLATION
	{
		switch (EIP[1]) {
			case 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
				break;
			}
			case 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
				break;
			}
			default:
				pExcPtrs->ContextRecord->Eip += 2; // Bypass current instruction
				pExcPtrs->ContextRecord->Eax = 0; // DEFAULT: EAX=0
		}
	}
	return EXCEPTION_CONTINUE_EXECUTION;
}

#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_FIRST, VEH);
	if (!pVEH) {
		printf("AddVectoredExceptionHandler error!\n");
		return 0;
	}
#pragma endregion

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

#pragma region Running UDs
	// UD0
	UD0
	__asm { mov v_eax, eax } // Store EAX register in variable
	printf("eax ud0 = %08X\n", v_eax); // Printing variable
	// UD1
	UD1
	__asm { mov v_eax, eax } // Store EAX register in variable
	printf("eax ud1 = %08X\n", v_eax); // Printing variable
	// UD2
	UD2
	__asm { mov v_eax, eax } // 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, 2 } // Store 2 in EDI register
	__asm { mov esi, 2 } // Store 2 in ESI register
	__asm { int 0x7D } // Calling Interrupt
	__asm { mov v_eax, eax } // Store EAX register in variable
	printf("eax int7D = %08X\n", v_eax); // Printing variable
	// int 7E (EAX=EDI-ESI)
	__asm { mov edi, 2 } // Store 2 in EDI register
	__asm { mov esi, 2 } // Store 2 in ESI register
	__asm { int 0x7E } // Calling Interrupt
	__asm { mov v_eax, eax } // 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_eax, eax } // Store EAX register in variable
	printf("eax intF1 = %08X\n", v_eax); // Printing variable
#pragma endregion

#pragma region Removing VEH Handler
	if (pVEH) {
		RemoveVectoredExceptionHandler(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!
Sam839 is offline
Reply


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 17:55.


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