How to obtain the sys_call_table address through the module in the kernel of Linux2.6

Source: Internet
Author: User
How to obtain the sys_call_table address through the module in the kernel of Linux2.6-Linux general technology-Linux programming and kernel information. The following is a detailed description. This article describes how to modify the base address in the Linux 2.6 kernel. I tested all the code on Fedora Core 6 Based on the 2.6.19 kernel.

For security reasons, the Linux 2.6 kernel does not export the base address of the system call list, sys_call_table. However, to replace the system call, you must obtain the base address, so I got this article.

The basic idea I used here is this, because the system calls are all implemented through 0x80 interruption, so we can find the address of sys_call_table by finding the handler for 0x80 interruption. The basic step is to first obtain the address of the Interrupt Descriptor Table, then find the 0x80 interrupted service routine, and then search the memory space of the routine to get the address of sys_call_table. The Code is as follows:

# Include
# Include

// Interrupt Descriptor Table register structure
Struct {
Unsigned short limit;
Unsigned int base;
} _ Attribute _ (packed) idtr;


// Interrupt Descriptor Table Structure
Struct {
Unsigned short off1;
Unsigned short sel;
Unsigned char none, flags;
Unsigned short off2;
} _ Attribute _ (packed) idt;

// Find the address of sys_call_table
Void disp_sys_call_table (void)
{
Unsigned int sys_call_off;
Unsigned int sys_call_table;
Char * p;
Int I;

// Obtain the address of the Interrupt Descriptor Table register
Asm ("sidt % 0": "= m" (idtr ));
Printk ("addr of idtr: % x \ n", & idtr );

// Obtain the address of the 0x80 interrupt handler
Memcpy (& idt, idtr. base + 8*0x80, sizeof (idt ));
Sys_call_off = (idt. off2 <16) | idt. off1 );
Printk ("addr of idt 0x80: % x \ n", sys_call_off );

// Search for the sys_call_table address from the 0x80 interrupt service routine
P = sys_call_off;
For (I = 0; I <100; I ++)
{
If (p = '\ xff' & p [I + 1] =' \ x14' & p [I + 2] = '\ x85 ')
{
Sys_call_table = * (unsigned int *) (p + I + 3 );
Printk ("addr of sys_call_table: % x \ n", sys_call_table );
Return;
}
}
}

// Called during module Loading
Static int _ init init_get_sys_call_table (void)
{
Disp_sys_call_table ();
Return 0;
}

Module_init (init_get_sys_call_table );

// Called when the module is detached
Static void _ exit exit_get_sys_call_table (void)
{
}

Module_exit (exit_get_sys_call_table );

// Module information
MODULE_LICENSE ("GPL2.0 ");
MODULE_AUTHOR ("Xizhi Zhu ");

After compiling and loading this module, you can see the following output through the dmesg command:
Addr of idtr: d0af4680
Addr of idt 0x80: c0103e04
Addr of sys_call_table: c03094c0

It can be seen that the above program can obtain the address of sys_call_table.

In the above Code, the most complex part is to search for the sys_call_table section from the service routine interrupted by 0x80. The following is an explanation.

First, run the command "gdb-q/usr/src/kernels/2.6.19/vmlinux" to decompile the kernel, run the "disass system_call" and "disass syscall_call" gdb commands to view the assembly code of the kernel. The result is as follows:

(Gdb) disass system_call
Dump of worker er code for function system_call:
0xc0103e04 : Push % eax
0xc0103e05 : Cld
0xc0103e06 : Push % es
0xc0103e07 : Push % ds
0xc0103e08 : Push % eax
0xc0103e09 : Push % ebp
0xc0103e0a : Push % edi
0xc0103e0b : Push % esi
0xc0103e0c : Push % edx
0xc0103e0d : Push % ecx
0xc0103e0e : Push % ebx
0xc0103e0f : Mov $ 0x7b, % edx
0xc0103e14 : Movl % edx, % ds
0xc0103e16 : Movl % edx, % es
0xc0103e18 : Mov $0xfffff000, % ebp
0xc0103e1d : And % esp, % ebp
0xc0103e1f : Testl $0x100,0x30 (% esp)
0xc0103e27 : Je 0xc0103e2d
0xc0103e29 : Orl $0x10, 0x8 (% ebp)
End of worker er dump.
(Gdb) disass syscall_call
Dump of Cycler code for function syscall_call:
0xc0103e44 : Call * 0xc03094c0 (, % eax, 4)
0xc0103e4b : Mov % eax, 0x18 (% esp)
End of worker er dump.

Among them, system_call is the entry of the service routine interrupted at 0x80, and syscall_call is the part that calls the specified system call. In the obtained disassembly code, we can see that the address 0xc03094c0 is the address of sys_call_table to be searched.

P.s. If portability is not considered, we can use this address directly. However, for better compatibility, we should search for this value by code segment.

Through further disassembly, we can find that the assembly code from system_call to syscall_call is as follows:

0xc0103e04 : Push % eax
0xc0103e05 : Cld
0xc0103e06 : Push % es
0xc0103e07 : Push % ds
0xc0103e08 : Push % eax
0xc0103e09 : Push % ebp
0xc0103e0a : Push % edi
0xc0103e0b : Push % esi
0xc0103e0c : Push % edx
0xc0103e0d : Push % ecx
0xc0103e0e : Push % ebx
0xc0103e0f : Mov $ 0x7b, % edx
0xc0103e14 : Movl % edx, % ds
0xc0103e16 : Movl % edx, % es
0xc0103e18 : Mov $0xfffff000, % ebp
0xc0103e1d : And % esp, % ebp
0xc0103e1f : Testl $0x100,0x30 (% esp)
0xc0103e27 : Je 0xc0103e2d
0xc0103e29 : Orl $0x10, 0x8 (% ebp)

0xc0103e2d : Testw $0x1c1, 0x8 (% ebp)
0xc0103e33 : Jne 0xc0103ef8
0xc0103e39 : Cmp $0x140, % eax
0xc0103e3e : Jae 0xc0103f6b

0xc0103e44 : Call * 0xc03094c0 (, % eax, 4)
0xc0103e4b : Mov % eax, 0x18 (% esp)

We don't need to worry about the specific operations performed in this Code. The only thing that deserves attention is that the first call statement does not appear until the system call occurs. We can use this to search. Run the "x/xw (syscall_call)" command to check that the command code of the call Statement is 0xc03094c08514ff. In this way, we can use the code given in the program to search.

So far, we have successfully obtained the sys_call_table address and can operate it as in previous kernel versions.

GetscTable () is a function used to find the sys_call_table address in the memory.
Every system call enters the core through int 0x80 interruption, and the interruption description
The description table maps the interrupt service program with the interrupt vector. For system calls
The operating system calls the system_call to interrupt the service program.
The system_call function is found and
Call the corresponding system call service routine. The idtr register points to the interrupt description.
The start address of the table. Use sidt [asm ("sidt % 0": "= m" (idtr);]
Command to get the starting address of the Interrupt Descriptor Table, the pointer obtained from this command
The int 0x80 interrupt server descriptor location can be obtained and then calculated
The address of the system_call function. Decompile the system_call function.
In the system_call function, the call sys_call_table command is used.
To call the system call function. Therefore, you only need to find the system_call
The machine command of the call sys_call_table (, eax, 4) command can be obtained.
The entry address of the system call table.
Related Article

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.