免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1056 | 回复: 0
打印 上一主题 下一主题

get system call table in x86-64 Linux [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-01-19 10:58 |只看该作者 |倒序浏览

本程序在x86-64 linux上动态获取系统调用表地址。 如果你有在x86-64上运行的2.6 Linux系统, 欢迎测试本程序, 并报告BUG:)
#include linux/kernel.h>
#include linux/init.h>
#include linux/module.h>
#include asm/uaccess.h>
#include asm/fcntl.h>
#include asm/unistd.h>
#include asm/ia32_unistd.h>
#include asm/msr.h>
#define THIS_DESCRIPTION "Dynamically get sys_call_table/ia32_sys_call_table in kernel module.\n\t\tI don't think there would be anyone who won't enable CONFIG_IA32_EMULATION these days.\n\t\tso you can add the unessary check if you really want to."
MODULE_DESCRIPTION( THIS_DESCRIPTION );
MODULE_AUTHOR("albcamus ");
MODULE_LICENSE("GPL");
/**
* TODO: if you want shut this up, comment the following line.
*/
#define BY_IDT_DEBUG
#ifdef BY_IDT_DEBUG
#define dbgprint(format,args...) \
                 printk("get_syscall: function:%s-L%d: "format, __FUNCTION__, __LINE__, ## args);
#else
#define dbgprint(format,args...)  do {} while(0);
#endif
/**
* sys call table
*/
void ** my_ia32_syscall_table;
void ** my_syscall_table;
/**
* 10 bytes  -- please refer to AMD64 Architecture Programmer's
*         Manuals for more information.
*/
struct idtr {
    unsigned short limit;
    unsigned long base; //in 64bit mode, base address is 8 bytes
} __attribute__ ((packed));
/**
* in long mode -- 64bit mode and compatity mode,
* every IDT entry has a 16-byte size
*/
struct idt {
    u16 offset_low;
    u16 segment;
    unsigned ist : 3, zero0 : 5, type : 5, dpl :2, p : 1;
    u16 offset_middle;
    u32 offset_high;
    u32 zero1;
} __attribute__ ((packed));
/**
* Return the first appearence of NEEDLE in HAYSTACK.  -- copied from PHRACK
* */
static void *memmem(const void *haystack, size_t haystack_len,
            const void *needle, size_t needle_len)
{/*{{{*/
    const char *begin;
    const char *const last_possible
        = (const char *) haystack + haystack_len - needle_len;
    if (needle_len == 0)
        /* The first occurrence of the empty string is deemed to occur at
           the beginning of the string.  */
        return (void *) haystack;
    /* Sanity check, otherwise the loop might search through the whole
       memory.  */
    if (__builtin_expect(haystack_len  needle_len, 0))
        return NULL;
    for (begin = (const char *) haystack; begin = last_possible;
         ++begin)
        if (begin[0] == ((const char *) needle)[0]
            && !memcmp((const void *) &begin[1],
                   (const void *) ((const char *) needle + 1),
                   needle_len - 1))
            return (void *) begin;
    return NULL;
}/*}}}*/
/**
* Find the location of ia32_sys_call_table
*/
static unsigned long get_syscall_table_ia32(void)
{/*{{{*/
#define OFFSET_SYSCALL 100    /* from system_call/ia32_syscall, we'll read first 100 bytes */
    struct idtr idtr;
    struct idt idt;
    unsigned long sys_call_off;
    unsigned long retval;
    char sc_asm[OFFSET_SYSCALL], *p;
    /* well, let's read IDTR */
    asm("sidt %0"
        :"=m"(idtr)
        : );
    dbgprint("idtr base at %p\n", (void *)idtr.base);
    /**
     * Read in IDT for vector 0x80 (syscall)
     */
    memcpy(&idt, (char *) idtr.base + 16 * 0x80, sizeof(idt));
    sys_call_off =  ( ( (unsigned long)idt.offset_high )  32 ) |
        ( ((idt.offset_middle  16 ) | idt.offset_low) & 0x00000000ffffffff );
    dbgprint("sys_call_off at %p\n", (void *)sys_call_off);
    /* we have syscall routine address now, look for syscall table
       dispatch (indirect call) */
    memcpy(sc_asm, (void *)sys_call_off, OFFSET_SYSCALL);
    /**
     * ia32_call > ia32_tracesys > ia32_do_syscall > 'call *ia32_sys_call_table(,%rax,8)'
     * Find callq *ia32_sys_call_table(,%rax,8)
     *
     * (gdb) disassemble ia32_syscall
     * Dump of assembler code for function ia32_syscall:
     * 0xffffffff81066b98 :    swapgs
     * 0xffffffff81066b9b :    sti
     * 0xffffffff81066b9c :    mov    %eax,%eax
     * 0xffffffff81066b9e :    push   %rax
     * 0xffffffff81066b9f :    cld
     * 0xffffffff81066ba0 :    sub    $0x48,%rsp
     * 0xffffffff81066ba4 :   mov    %rdi,0x40(%rsp)
     * 0xffffffff81066ba9 :   mov    %rsi,0x38(%rsp)
     * 0xffffffff81066bae :   mov    %rdx,0x30(%rsp)
     * 0xffffffff81066bb3 :   mov    %rcx,0x28(%rsp)
     * 0xffffffff81066bb8 :   mov    %rax,0x20(%rsp)
     * 0xffffffff81066bbd :   mov    %gs:0x10,%r10
     * 0xffffffff81066bc6 :   sub    $0x1fd8,%r10
     * 0xffffffff81066bcd :   orl    $0x2,0x14(%r10)
     * 0xffffffff81066bd2 :   testl  $0x181,0x10(%r10)
     * 0xffffffff81066bda :   jne    0xffffffff81066c04
     * End of assembler dump.
     * (gdb) disassemble ia32_tracesys
     * Dump of assembler code for function ia32_tracesys:
     * 0xffffffff81066c04 :   sub    $0x30,%rsp
     * 0xffffffff81066c08 :   mov    %rbx,0x28(%rsp)
     * 0xffffffff81066c0d :   mov    %rbp,0x20(%rsp)
     * 0xffffffff81066c12 :  mov    %r12,0x18(%rsp)
     * 0xffffffff81066c17 :  mov    %r13,0x10(%rsp)
     * 0xffffffff81066c1c :  mov    %r14,0x8(%rsp)
     * 0xffffffff81066c21 :  mov    %r15,(%rsp)
     * 0xffffffff81066c25 :  movq   $0xffffffffffffffda,0x50(%rsp)
     * 0xffffffff81066c2e :  mov    %rsp,%rdi
     * 0xffffffff81066c31 :  callq  0xffffffff81073a02
     * 0xffffffff81066c36 :  mov    0x30(%rsp),%r11
     * 0xffffffff81066c3b :  mov    0x38(%rsp),%r10
     * 0xffffffff81066c40 :  mov    0x40(%rsp),%r9
     * 0xffffffff81066c45 :  mov    0x48(%rsp),%r8
     * 0xffffffff81066c4a :  mov    0x58(%rsp),%rcx
     * 0xffffffff81066c4f :  mov    0x60(%rsp),%rdx
     * 0xffffffff81066c54 :  mov    0x68(%rsp),%rsi
     * 0xffffffff81066c59 :  mov    0x70(%rsp),%rdi
     * 0xffffffff81066c5e :  mov    0x78(%rsp),%rax
     * 0xffffffff81066c63 :  mov    (%rsp),%r15
     * 0xffffffff81066c67 :  mov    0x8(%rsp),%r14
     * 0xffffffff81066c6c : mov    0x10(%rsp),%r13
     * 0xffffffff81066c71 : mov    0x18(%rsp),%r12
     * 0xffffffff81066c76 : mov    0x20(%rsp),%rbp
     * 0xffffffff81066c7b : mov    0x28(%rsp),%rbx
     * 0xffffffff81066c80 : add    $0x30,%rsp
     * 0xffffffff81066c84 : jmpq   0xffffffff81066bdc
     * End of assembler dump.
     * (gdb) disassemble ia32_do_syscall
     * Dump of assembler code for function ia32_do_syscall:
     * 0xffffffff81066bdc : cmp    $0x13d,%eax
     * 0xffffffff81066be1 : ja     0xffffffff81066c89
     * 0xffffffff81066be7 :        mov    %edi,%r8d
     * 0xffffffff81066bea :        mov    %ebp,%r9d
     * 0xffffffff81066bed :        xchg   %ecx,%esi
     * 0xffffffff81066bef :        mov    %ebx,%edi
     * 0xffffffff81066bf1 :        mov    %edx,%edx
     * 0xffffffff81066bf3 :        callq  *0xffffffff812e7c70(,%rax,8)
     * End of assembler dump.
     * (gdb) x/xw ia32_do_syscall+23
     * 0xffffffff81066bf3 :        0x70c514ff
     * (gdb)
     *
     */
    p = (char *) memmem(sc_asm, OFFSET_SYSCALL, "\xff\x14\xc5", 3);
    if (p == NULL) {
        printk("opcode not found, meats that we cannot find sys_call_table.\n");
        return 0;
    }
    retval = *(unsigned long *) (p + 3);
    return retval;
#undef OFFSET_SYSCALL
}/*}}}*/
/**
* Find the location of long-mode sys_call_table
*/
static unsigned long get_syscall_table_long(void)
{/*{{{*/
#define OFFSET_SYSCALL 150
    unsigned long syscall_long, retval;
    char sc_asm[OFFSET_SYSCALL];
    rdmsrl(MSR_LSTAR, syscall_long);
    dbgprint("long mode: system_call is at %p\n", (void *)syscall_long);
    memcpy(sc_asm, (char *)syscall_long, OFFSET_SYSCALL);
    /**
     * Find callq *sys_call_table(,%rax,8)
     * -------------------------------------
     * (gdb) disassemble system_call
     * Dump of assembler code for function system_call:
     * 0xffffffff81063750 :     swapgs
     * 0xffffffff81063753 :     mov    %rsp,%gs:0x18
     * 0xffffffff8106375c :    mov    %gs:0x10,%rsp
     * 0xffffffff81063765 :    sti
     * 0xffffffff81063766 :    sub    $0x50,%rsp
     * 0xffffffff8106376a :    mov    %rdi,0x40(%rsp)
     * 0xffffffff8106376f :    mov    %rsi,0x38(%rsp)
     * 0xffffffff81063774 :    mov    %rdx,0x30(%rsp)
     * 0xffffffff81063779 :    mov    %rax,0x20(%rsp)
     * 0xffffffff8106377e :    mov    %r8,0x18(%rsp)
     * 0xffffffff81063783 :    mov    %r9,0x10(%rsp)
     * 0xffffffff81063788 :    mov    %r10,0x8(%rsp)
     * 0xffffffff8106378d :    mov    %r11,(%rsp)
     * 0xffffffff81063791 :    mov    %rax,0x48(%rsp)
     * 0xffffffff81063796 :    mov    %rcx,0x50(%rsp)
     * 0xffffffff8106379b :    mov    %gs:0x10,%rcx
     * 0xffffffff810637a4 :    sub    $0x1fd8,%rcx
     * 0xffffffff810637ab :    testl  $0x181,0x10(%rcx)
     * 0xffffffff810637b2 :    jne    0xffffffff81063889
     * 0xffffffff810637b8 :   cmp    $0x117,%rax
     * 0xffffffff810637be :   ja     0xffffffff8106387b
     * 0xffffffff810637c4 :   mov    %r10,%rcx
     * 0xffffffff810637c7 :   callq  *0xffffffff812e6d60(,%rax,8)
     * 0xffffffff810637ce :   mov    %rax,0x20(%rsp)
     * End of assembler dump.
     * (gdb) x/xw system_call+119
     * 0xffffffff810637c7 :   0x60c514ff
     * (gdb)
     */
    retval = (unsigned long) memmem(sc_asm, OFFSET_SYSCALL, "\xff\x14\xc5", 3);
    if ( retval != 0 ) {
        dbgprint("long mode : sys_call_table is at %p\n",
                (void *) (* (unsigned long *)(retval+3)) ) ;
        retval = (unsigned long) ( * (unsigned long *)(retval+3) );
    } else {
        printk("long mode : memmem found nothing, returning NULL:( \n");
        retval = 0;
    }
#undef OFFSET_SYSCALL
    return retval;
}/*}}}*/
static int get_syscall_init_module(void)
{/*{{{*/
    printk(KERN_DEBUG "get_syscall: Hi, you fucking linux!\n");
    my_ia32_syscall_table = (void **) get_syscall_table_ia32();
    if (my_ia32_syscall_table == 0)
        return -1;
    my_syscall_table = (void **) get_syscall_table_long();
    if (my_syscall_table == 0)
        return -1;
    dbgprint("ia32_sys_call_table address : %p\n", (void *) my_ia32_syscall_table);
    dbgprint("long mode : sys_call_table address : %p\n", (void *) my_syscall_table);
#define REPLACE_IA32(x) o_sys_##x = my_ia32_syscall_table[__NR_ia32_##x];\
    my_ia32_syscall_table[__NR_ia32_##x] = my_sys_##x
#define GET_OLD_IA32_SYSCALL_ADDR(x) my_ia32_syscall_table[__NR_ia32_##x]
//    dbgprint("sys_read at %p, my_read at %p\n", (void *)GET_OLD_IA32_SYSCALL_ADDR(read), (void *)my_sys_read);
//    REPLACE_IA32(read);
#undef REPLACE_IA32
    return 0;
}/*}}}*/
static void get_syscall_exit_module(void)
{/*{{{*/
    printk(KERN_DEBUG "get_syscall: bye, you fucking linux!\n");
#define RESTORE_IA32(x) my_ia32_syscall_table[__NR_ia32_##x] = o_sys_##x
//    RESTORE_IA32(read);
#undef RESTORE_IA32
}/*}}}*/
module_init(get_syscall_init_module);
module_exit(get_syscall_exit_module);
Reference :
http://phrack.org/archives/58/p58-0x07


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/548/showart_234533.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP