文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>导出Linux系统调用表(sys_call_table)

导出Linux系统调用表(sys_call_table)

时间:2006-04-30  来源:xiaosuo

Linux内核从2.4.18开始就不再导出系统调用表(sys_call_table),这对于我们想对系统调用做些手脚的朋友们来说,确实不是什么好消息。少了很多便利条件,如果说改内核源码,加上EXPORT_SYMBOL(sys_call_table),还是能够导出的,不过这个需要重新编译内核,最烦人就是重启(我们有些时候最怕的就是重启,至于为什么,大家心里明白,哈哈)。如果我们足够幸运,能找到/boot/System.map,通过简单的grep sys_call_table /boot/System.map也能如愿以偿,可是这个文件并不是所有的系统都有的。还好LKM给了我们访问内核空间的能力,可是系统这么大,从何下手呢?
反汇编系统调用相关代码:
(gdb) disas syscall_call
Dump of assembler code for function syscall_call:
0xc0102e0a <syscall_call+0>:    call   *0xc030948c(,%eax,4)
0xc0102e11 <syscall_call+7>:    mov    %eax,0x18(%esp)
End of assembler dump.
(gdb) x/8x 0xc0102e0a
0xc0102e0a <syscall_call>:      0x8c8514ff      0x89c03094      0xfa182444      0x66084d8b
0xc0102e1a <syscall_exit+5>:    0xfeffc1f7      0x00cc850f      0x448b0000      0x648a3024
可以看到蓝色的部分就是需要找的标志字符串,与之紧挨的高地址部分就是我们要找的sys_call_table的地址。为了缩小查找范围,我们只要从int $0x80的入口函数向下顺序查找就行,其地址用命令sidt就能直接得到了。具体代码如下:
/*
 * Copyright (c) 2006 xiaosuo <[email protected]>
 *
 * Copyright (c) 2003 Dallachiesa Michele <[email protected]>
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification are permitted.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *
 * DESCRIPTION
 *
 *   redhat kernels don't export the sys_call_table symbol anymore.. this
 *   is a workaround that let you use your old LKMs without fix them.
 *
 *   In fact, the kernel (>= 2.4.18) don't export the sys_call_table symbol
 *   anymore...
 *
 * USAGE
 *
 *    Build this as a kernel module and loaded
 *
 *  + greetz: (#phrack.it|antifork.org) guys
 *  + sys_call_table[] address lookup code from phrack 58 #0x07 by sd
 */

#ifndef MODULE
#define MODULE
#endif

#ifndef __KERNEL__
#define __KERNEL__
#endif

#include <linux/kernel.h>
#ifdef USE_SYMBOL_NAME
#include <linux/string.h>
#endif
#include <linux/module.h>

#define CALLOFF 100

unsigned long           sys_call_table = 0;
EXPORT_SYMBOL(sys_call_table);

struct {
        unsigned short  limit;
        unsigned int    base;
} __attribute__ ((packed)) idtr;

struct {
        unsigned short  offset_low;
        unsigned short  sel;
        unsigned char   none, flags;
        unsigned short  offset_high;
} __attribute__ ((packed)) * idt;

/*
 * The /proc/kallsyms is not updated.
 */
int set_symbol_value(unsigned long old_value, unsigned long value)
{
        struct kernel_symbol *ksyms;
        int i;

        ksyms = (struct kernel_symbol*)(THIS_MODULE->syms);
        for(i = 0; i < THIS_MODULE->num_syms; i ++){
#ifdef USE_SYMBOL_NAME
                if(strcmp(ksyms[i].name, "sys_call_table") == 0){
#else
                if(ksyms[i].value == old_value){
#endif
                        ksyms[i].value = value;
                        return 0;
                }
        }

        return -1;
}

char* findoffset(char *start)
{
        char           *p;

        for (p = start; p < start + CALLOFF; p++)
                if (*(p + 0) == '\xff' && *(p + 1) == '\x14'
                                && *(p + 2) == '\x85')
                        return p;

        return NULL;
}

int init_module(void)
{
        unsigned        sys_call_off;
        char           *p;

        __asm__("sidt %0":"=m"(idtr));
        idt = (void *) (idtr.base + 8 * 0x80);
        sys_call_off = (idt->offset_high << 16) | idt->offset_low;

        if ((p = findoffset((char *) sys_call_off))) {
                return set_symbol_value((unsigned long)&sys_call_table,
                                *((unsigned long*)(p+3)));
        }

        return -1;
}

void cleanup_module(void)
{
}
另外,因为有这样一个事实:sys_call_table总是在loops_per_jiffy和boot_cpu_data之间,所以可以用这两个符号地址作为边界进行查询!
 /* This method first be found in the dazuko 2.0.6
 */

static void** dazuko_get_sct(void)
{
        unsigned long   ptr;
        extern int      loops_per_jiffy;
        unsigned long   *p;

        for(ptr=(unsigned long)&loops_per_jiffy; ptr<(unsigned long)&boot_cpu_data;
                        ptr+=sizeof(void *)){
                p = (unsigned long *)ptr;
                if (p[6] == (unsigned long)sys_close){
                        return (void **)p;
                }
        }

        return NULL;
}
相关阅读 更多 +
排行榜 更多 +
浴血混战官方下载

浴血混战官方下载

飞行射击 下载
检票员模拟器免广告下载

检票员模拟器免广告下载

模拟经营 下载
最终前哨最终版手机版下载

最终前哨最终版手机版下载

休闲益智 下载