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 INTERRUPT_GATE 6
#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;
} IDT_ENTRY, *PIDT_ENTRY;

#define ADDINT 0x25

NTSTATUS AddInterrupt()
{
PIDT_ENTRY pIdtEntry;

/* 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))
{
return STATUS_UNSUCCESSFUL;
}

/* 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->Selector=8;
pIdtEntry->Type = INTERRUPT_GATE;
pIdtEntry->Is32bit = 1;
pIdtEntry->Dpl=3;
pIdtEntry->Present=1;
pIdtEntry->OffsetHigh= (unsigned short)((unsigned int) InterruptHandler >> 16);

_asm sti

return STATUS_SUCCESS;
}

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

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

sti
push edi
push ebx
push edx
call VerifyHandler
cli

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

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

_tprintf(_T(“Status = 0x%x\n”), status);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
_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?

Thanks,
Ben

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