Implementing a software interrupt

I’m working on a project (purely educational for a security class) where I need to write my own software interrupt handler. When I call the interrupt from an app, this will let me verify the EIP that is pushed on the stack by the int n instruction.

My problem is that when the iretd instruction is executed at the end of my handler and control transfers back to my user-mode app, the fs register is now 0. This of course causes a crash later.

My setup: Targeting Windows XP, running in VMWare, using WDK 6000

I wrote a driver that adds by interrupt handler to the idt (0x25 is my interrupt number)

#define TASK_GATE 5
#define TRAP_GATE 7

/* Decriptor Entry corresponding to interrupt gate */
typedef struct _IDT_ENTRY {
unsigned short OffsetLow;
unsigned short Selector;
unsigned char Reserved:5;
unsigned char Always0_1:3;
unsigned char Type:3;
unsigned char Is32bit:1;
unsigned char Always0_2:1;
unsigned char Dpl:2;
unsigned char Present:1;
unsigned short OffsetHigh;

#define ADDINT 0x25

NTSTATUS AddInterrupt()

/* Get the Base and Limit of IDTR Register */

_asm sidt g_idtr

pIdtEntry = (PIDT_ENTRY)g_idtr.Base;

pIdtEntry += ADDINT;

if ((pIdtEntry->OffsetLow!=0)||(pIdtEntry->OffsetHigh!=0))

/* Save away the old IDT entry */
memcpy(&g_oldIdtEntry, pIdtEntry, sizeof(g_oldIdtEntry));

_asm cli

/* Initialize the IDT entry according to the interrupt gate requirement */
pIdtEntry->OffsetLow=(unsigned short)InterruptHandler;
pIdtEntry->Type = INTERRUPT_GATE;
pIdtEntry->Is32bit = 1;
pIdtEntry->OffsetHigh= (unsigned short)((unsigned int) InterruptHandler >> 16);

_asm sti


My interrupt handler is currently:
__declspec( naked ) void InterruptHandler()
push edi
push ebx
push fs
mov ebx, 30h
mov fs, bx

mov edi, [esp + 24]
mov ebx, [esp + 12]

push edi
push ebx
push edx
call VerifyHandler

pop fs
pop ebx
pop edi
I have this problem even if the handler is just iretd.

user-mode code:
int _tmain(int argc, _TCHAR* argv)
DWORD status;
_tprintf(_T(“Performing syscall…\n”));
_asm mov edx, 4
_asm int 25h
_asm mov status, eax

_tprintf(_T(“Status = 0x%x\n”), status);
_tprintf(_T(“Exception caught %d\n”), GetExceptionCode());

return 0;

Reading the intel docs, I’m confused as to why fs is being reset. From what I understand, this should only occur when switching operating modes, not privilege level. What am I missing?


And yes, I realize this a little off topic, but I’d appreciate your insight if you have the time.