intercepting an exception handler.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

I am trying to replace the exception handler address in the IDT (for int 3)
with my own handler.  In the kernel one handler is actually split into two:
1) The generic handler 2) the actual handler in C code.
An example for what I mean is :
1) = ENTRY(debug)
2) = do_debug()

I read an article (at phrack) and the article recommends that when we
intercept a handler , we  should also install a generic (or asm) handler
and then write our own C handler.
All this works very well.
That is, i have got the following working -
1) Get the IDT table  from sidt , idtr etc.
2) Save the low and high offset from the desired idt entry
3) Replace the low and high offsets with my own GENERIC HANDLER.
4) The generic handler actually calls the c handler which is of the
following type - void foobar(void);
5) write test programs to see if things work.  They do :)
6)  During the cleanup_module , put the old handler into the high and low
offsets.  (uninstalling the hook).

Now my question is : can't we skip the generic handler part and directly
write the address of the c handler into the IDT table?    If i do this the
user program gives me an OOPs.  In step 3 above, if we save the low and
high offsets of the C handler, things should work right?
I am attaching the code for your reference.

#include<linux/module.h>
#include<linux/init.h>
#include<linux/kernel.h>


EXPORT_NO_SYMBOLS;

struct idt_entry {
      unsigned short offset_low, selector;
      unsigned char flag, reserved;
      unsigned short offset_high;
};
unsigned long old_func;

void my_code(void)
{
      printk(KERN_ALERT "Int 3 hooked\n");
}

extern void my_stub(void);

void mk_stub(void)
{
      __asm__ (".global my_stub   \n"
            ".align 4,0x90    \n" // 4 for intel 0x90 for NOP
             "my_stub:  \n"
            "     call *%0   \n"
            "     jmp *%1     \n"::"m"(my_code),"m"(old_func)
            );

}

struct idt_entry *idt0;

int my_init(void)
{
      unsigned char idtr[6];  // IDTR is 48 bits
      // see intel manual vol 3

      //get idt address
      __asm__ volatile("sidt %0": "=m"(idtr));

      //  see intel manual of how the things are stored in mem
      //  16bits + 32bits in memory
      idt0 =(struct idt_entry*) *((unsigned *)(idtr + 2));

      printk(KERN_ALERT "IDT table address %x\n ",(unsigned long)idt0);

      //Get old address
      old_func = (idt0[3].offset_high << 16) + (idt0[3].offset_low);
      printk(KERN_ALERT "old int 3 function %x",old_func);


      // copy new address into idt
      idt0[3].offset_high =(unsigned short)  ( (unsigned long) my_stub
/*my_code*/  >> 16);
      idt0[3].offset_low = (unsigned short) (  (unsigned long) my_stub
/*my_code*/ & 0x0000ffff);
      //thatz it


/**/
      printk(KERN_ALERT "Exception hook installed\n");
      return 0;
}


void my_exit(void)
{
      //restore old handler

      idt0[3].offset_high = old_func >> 16;
      idt0[3].offset_low = old_func & 0x0000ffff;
      printk(KERN_ALERT " Exception hook uninstalled\n");
}

module_init(my_init);
module_exit(my_exit);



Regards,
Mohit Kalra

"It is a capital mistake to theorize before one has data.
Insensibly one begins to twist facts to suit theories, instead of theories
to suit facts."
-SH

--
Kernelnewbies: Help each other learn about the Linux kernel.
Archive:       http://mail.nl.linux.org/kernelnewbies/
FAQ:           http://kernelnewbies.org/faq/


[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux