免费注册 查看新帖 |

Chinaunix

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

get system call table in x86-64 Linux - 欢迎测试并报BUG [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-01-18 18:08 |只看该作者 |倒序浏览
  1. #include <linux/kernel.h>
  2. #include <linux/init.h>
  3. #include <linux/module.h>
  4. #include <asm/uaccess.h>
  5. #include <asm/fcntl.h>
  6. #include <asm/unistd.h>
  7. #include <asm/ia32_unistd.h>
  8. #include <asm/msr.h>



  9. #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."
  10. MODULE_DESCRIPTION( THIS_DESCRIPTION );
  11. MODULE_AUTHOR("albcamus <albcamus@gmail.com>");
  12. MODULE_LICENSE("GPL");


  13. /**
  14. * TODO: if you want shut this up, comment the following line.
  15. */
  16. #define BY_IDT_DEBUG

  17. #ifdef BY_IDT_DEBUG
  18. #define dbgprint(format,args...) \
  19.                  printk("get_syscall: function:%s-L%d: "format, __FUNCTION__, __LINE__, ## args);
  20. #else
  21. #define dbgprint(format,args...)  do {} while(0);
  22. #endif


  23. /**
  24. * sys call table
  25. */
  26. void ** my_ia32_syscall_table;
  27. void ** my_syscall_table;



  28. /**
  29. * 10 bytes  -- please refer to AMD64 Architecture Programmer's
  30. *         Manuals for more information.
  31. */
  32. struct idtr {
  33.     unsigned short limit;
  34.     unsigned long base; //in 64bit mode, base address is 8 bytes
  35. } __attribute__ ((packed));


  36. /**
  37. * in long mode -- 64bit mode and compatity mode,
  38. * every IDT entry has a 16-byte size
  39. */
  40. struct idt {
  41.     u16 offset_low;
  42.     u16 segment;
  43.     unsigned ist : 3, zero0 : 5, type : 5, dpl :2, p : 1;
  44.     u16 offset_middle;
  45.     u32 offset_high;
  46.     u32 zero1;
  47. } __attribute__ ((packed));




  48. /**
  49. * Return the first appearence of NEEDLE in HAYSTACK.  -- copied from PHRACK
  50. * */
  51. static void *memmem(const void *haystack, size_t haystack_len,
  52.             const void *needle, size_t needle_len)
  53. {/*{{{*/
  54.     const char *begin;
  55.     const char *const last_possible
  56.         = (const char *) haystack + haystack_len - needle_len;

  57.     if (needle_len == 0)
  58.         /* The first occurrence of the empty string is deemed to occur at
  59.            the beginning of the string.  */
  60.         return (void *) haystack;

  61.     /* Sanity check, otherwise the loop might search through the whole
  62.        memory.  */
  63.     if (__builtin_expect(haystack_len < needle_len, 0))
  64.         return NULL;

  65.     for (begin = (const char *) haystack; begin <= last_possible;
  66.          ++begin)
  67.         if (begin[0] == ((const char *) needle)[0]
  68.             && !memcmp((const void *) &begin[1],
  69.                    (const void *) ((const char *) needle + 1),
  70.                    needle_len - 1))
  71.             return (void *) begin;

  72.     return NULL;
  73. }/*}}}*/


  74. /**
  75. * Find the location of ia32_sys_call_table
  76. */
  77. static unsigned long get_syscall_table_ia32(void)
  78. {/*{{{*/
  79. #define OFFSET_SYSCALL 100    /* from system_call/ia32_syscall, we'll read first 150 bytes */

  80.     struct idtr idtr;
  81.     struct idt idt;

  82.     unsigned long sys_call_off;
  83.     unsigned long retval;

  84.     char sc_asm[OFFSET_SYSCALL], *p;




  85.     /* well, let's read IDTR */
  86.     asm("sidt %0"
  87.         :"=m"(idtr)
  88.         : );

  89.     dbgprint("idtr base at %p\n", (void *)idtr.base);

  90.     /**
  91.      * Read in IDT for vector 0x80 (syscall)
  92.      */
  93.     memcpy(&idt, (char *) idtr.base + 16 * 0x80, sizeof(idt));
  94.     sys_call_off =  ( ( (unsigned long)idt.offset_high ) << 32 ) |
  95.         ( ((idt.offset_middle << 16 ) | idt.offset_low) & 0x00000000ffffffff );
  96.     dbgprint("sys_call_off at %p\n", (void *)sys_call_off);

  97.     /* we have syscall routine address now, look for syscall table
  98.        dispatch (indirect call) */
  99.     memcpy(sc_asm, (void *)sys_call_off, OFFSET_SYSCALL);
  100.     /**
  101.      * ia32_call > ia32_tracesys > ia32_do_syscall > 'call *ia32_sys_call_table(,%rax,8)'
  102.      * Find callq *ia32_sys_call_table(,%rax,8)
  103.      *
  104.      * (gdb) disassemble ia32_syscall
  105.      * Dump of assembler code for function ia32_syscall:
  106.      * 0xffffffff81066b98 <ia32_syscall+0>:    swapgs
  107.      * 0xffffffff81066b9b <ia32_syscall+3>:    sti
  108.      * 0xffffffff81066b9c <ia32_syscall+4>:    mov    %eax,%eax
  109.      * 0xffffffff81066b9e <ia32_syscall+6>:    push   %rax
  110.      * 0xffffffff81066b9f <ia32_syscall+7>:    cld
  111.      * 0xffffffff81066ba0 <ia32_syscall+8>:    sub    $0x48,%rsp
  112.      * 0xffffffff81066ba4 <ia32_syscall+12>:   mov    %rdi,0x40(%rsp)
  113.      * 0xffffffff81066ba9 <ia32_syscall+17>:   mov    %rsi,0x38(%rsp)
  114.      * 0xffffffff81066bae <ia32_syscall+22>:   mov    %rdx,0x30(%rsp)
  115.      * 0xffffffff81066bb3 <ia32_syscall+27>:   mov    %rcx,0x28(%rsp)
  116.      * 0xffffffff81066bb8 <ia32_syscall+32>:   mov    %rax,0x20(%rsp)
  117.      * 0xffffffff81066bbd <ia32_syscall+37>:   mov    %gs:0x10,%r10
  118.      * 0xffffffff81066bc6 <ia32_syscall+46>:   sub    $0x1fd8,%r10
  119.      * 0xffffffff81066bcd <ia32_syscall+53>:   orl    $0x2,0x14(%r10)
  120.      * 0xffffffff81066bd2 <ia32_syscall+58>:   testl  $0x181,0x10(%r10)
  121.      * 0xffffffff81066bda <ia32_syscall+66>:   jne    0xffffffff81066c04 <ia32_tracesys>
  122.      * End of assembler dump.
  123.      * (gdb) disassemble ia32_tracesys
  124.      * Dump of assembler code for function ia32_tracesys:
  125.      * 0xffffffff81066c04 <ia32_tracesys+0>:   sub    $0x30,%rsp
  126.      * 0xffffffff81066c08 <ia32_tracesys+4>:   mov    %rbx,0x28(%rsp)
  127.      * 0xffffffff81066c0d <ia32_tracesys+9>:   mov    %rbp,0x20(%rsp)
  128.      * 0xffffffff81066c12 <ia32_tracesys+14>:  mov    %r12,0x18(%rsp)
  129.      * 0xffffffff81066c17 <ia32_tracesys+19>:  mov    %r13,0x10(%rsp)
  130.      * 0xffffffff81066c1c <ia32_tracesys+24>:  mov    %r14,0x8(%rsp)
  131.      * 0xffffffff81066c21 <ia32_tracesys+29>:  mov    %r15,(%rsp)
  132.      * 0xffffffff81066c25 <ia32_tracesys+33>:  movq   $0xffffffffffffffda,0x50(%rsp)
  133.      * 0xffffffff81066c2e <ia32_tracesys+42>:  mov    %rsp,%rdi
  134.      * 0xffffffff81066c31 <ia32_tracesys+45>:  callq  0xffffffff81073a02 <syscall_trace_enter>
  135.      * 0xffffffff81066c36 <ia32_tracesys+50>:  mov    0x30(%rsp),%r11
  136.      * 0xffffffff81066c3b <ia32_tracesys+55>:  mov    0x38(%rsp),%r10
  137.      * 0xffffffff81066c40 <ia32_tracesys+60>:  mov    0x40(%rsp),%r9
  138.      * 0xffffffff81066c45 <ia32_tracesys+65>:  mov    0x48(%rsp),%r8
  139.      * 0xffffffff81066c4a <ia32_tracesys+70>:  mov    0x58(%rsp),%rcx
  140.      * 0xffffffff81066c4f <ia32_tracesys+75>:  mov    0x60(%rsp),%rdx
  141.      * 0xffffffff81066c54 <ia32_tracesys+80>:  mov    0x68(%rsp),%rsi
  142.      * 0xffffffff81066c59 <ia32_tracesys+85>:  mov    0x70(%rsp),%rdi
  143.      * 0xffffffff81066c5e <ia32_tracesys+90>:  mov    0x78(%rsp),%rax
  144.      * 0xffffffff81066c63 <ia32_tracesys+95>:  mov    (%rsp),%r15
  145.      * 0xffffffff81066c67 <ia32_tracesys+99>:  mov    0x8(%rsp),%r14
  146.      * 0xffffffff81066c6c <ia32_tracesys+104>: mov    0x10(%rsp),%r13
  147.      * 0xffffffff81066c71 <ia32_tracesys+109>: mov    0x18(%rsp),%r12
  148.      * 0xffffffff81066c76 <ia32_tracesys+114>: mov    0x20(%rsp),%rbp
  149.      * 0xffffffff81066c7b <ia32_tracesys+119>: mov    0x28(%rsp),%rbx
  150.      * 0xffffffff81066c80 <ia32_tracesys+124>: add    $0x30,%rsp
  151.      * 0xffffffff81066c84 <ia32_tracesys+128>: jmpq   0xffffffff81066bdc <ia32_do_syscall>
  152.      * End of assembler dump.
  153.      * (gdb) disassemble ia32_do_syscall
  154.      * Dump of assembler code for function ia32_do_syscall:
  155.      * 0xffffffff81066bdc <ia32_do_syscall+0>: cmp    $0x13d,%eax
  156.      * 0xffffffff81066be1 <ia32_do_syscall+5>: ja     0xffffffff81066c89 <ia32_badsys>
  157.      * 0xffffffff81066be7 <ia32_do_syscall+11>:        mov    %edi,%r8d
  158.      * 0xffffffff81066bea <ia32_do_syscall+14>:        mov    %ebp,%r9d
  159.      * 0xffffffff81066bed <ia32_do_syscall+17>:        xchg   %ecx,%esi
  160.      * 0xffffffff81066bef <ia32_do_syscall+19>:        mov    %ebx,%edi
  161.      * 0xffffffff81066bf1 <ia32_do_syscall+21>:        mov    %edx,%edx
  162.      * 0xffffffff81066bf3 <ia32_do_syscall+23>:        callq  *0xffffffff812e7c70(,%rax,8)
  163.      * End of assembler dump.
  164.      * (gdb) x/xw ia32_do_syscall+23
  165.      * 0xffffffff81066bf3 <ia32_do_syscall+23>:        0x70c514ff
  166.      * (gdb)
  167.      *
  168.      */
  169.     p = (char *) memmem(sc_asm, OFFSET_SYSCALL, "\xff\x14\xc5", 3);
  170.     if (p == NULL) {
  171.         printk("opcode not found, meats that we cannot find sys_call_table.\n");
  172.         return 0;
  173.     }

  174.     retval = *(unsigned long *) (p + 3);
  175.     return retval;
  176. #undef OFFSET_SYSCALL
  177. }/*}}}*/


  178. /**
  179. * Find the location of long-mode sys_call_table
  180. */
  181. static unsigned long get_syscall_table_long(void)
  182. {/*{{{*/
  183. #define OFFSET_SYSCALL 150
  184.     unsigned long syscall_long, retval;
  185.     char sc_asm[OFFSET_SYSCALL];

  186.     rdmsrl(MSR_LSTAR, syscall_long);
  187.     dbgprint("long mode: system_call is at %p\n", (void *)syscall_long);

  188.     memcpy(sc_asm, (char *)syscall_long, OFFSET_SYSCALL);


  189.     /**
  190.      * Find callq *sys_call_table(,%rax,8)
  191.      * -------------------------------------
  192.      * (gdb) disassemble system_call
  193.      * Dump of assembler code for function system_call:
  194.      * 0xffffffff81063750 <system_call+0>:     swapgs
  195.      * 0xffffffff81063753 <system_call+3>:     mov    %rsp,%gs:0x18
  196.      * 0xffffffff8106375c <system_call+12>:    mov    %gs:0x10,%rsp
  197.      * 0xffffffff81063765 <system_call+21>:    sti
  198.      * 0xffffffff81063766 <system_call+22>:    sub    $0x50,%rsp
  199.      * 0xffffffff8106376a <system_call+26>:    mov    %rdi,0x40(%rsp)
  200.      * 0xffffffff8106376f <system_call+31>:    mov    %rsi,0x38(%rsp)
  201.      * 0xffffffff81063774 <system_call+36>:    mov    %rdx,0x30(%rsp)
  202.      * 0xffffffff81063779 <system_call+41>:    mov    %rax,0x20(%rsp)
  203.      * 0xffffffff8106377e <system_call+46>:    mov    %r8,0x18(%rsp)
  204.      * 0xffffffff81063783 <system_call+51>:    mov    %r9,0x10(%rsp)
  205.      * 0xffffffff81063788 <system_call+56>:    mov    %r10,0x8(%rsp)
  206.      * 0xffffffff8106378d <system_call+61>:    mov    %r11,(%rsp)
  207.      * 0xffffffff81063791 <system_call+65>:    mov    %rax,0x48(%rsp)
  208.      * 0xffffffff81063796 <system_call+70>:    mov    %rcx,0x50(%rsp)
  209.      * 0xffffffff8106379b <system_call+75>:    mov    %gs:0x10,%rcx
  210.      * 0xffffffff810637a4 <system_call+84>:    sub    $0x1fd8,%rcx
  211.      * 0xffffffff810637ab <system_call+91>:    testl  $0x181,0x10(%rcx)
  212.      * 0xffffffff810637b2 <system_call+98>:    jne    0xffffffff81063889 <tracesys>
  213.      * 0xffffffff810637b8 <system_call+104>:   cmp    $0x117,%rax
  214.      * 0xffffffff810637be <system_call+110>:   ja     0xffffffff8106387b <badsys>
  215.      * 0xffffffff810637c4 <system_call+116>:   mov    %r10,%rcx
  216.      * 0xffffffff810637c7 <system_call+119>:   callq  *0xffffffff812e6d60(,%rax,8)
  217.      * 0xffffffff810637ce <system_call+126>:   mov    %rax,0x20(%rsp)
  218.      * End of assembler dump.
  219.      * (gdb) x/xw system_call+119
  220.      * 0xffffffff810637c7 <system_call+119>:   0x60c514ff
  221.      * (gdb)
  222.      */
  223.     retval = (unsigned long) memmem(sc_asm, OFFSET_SYSCALL, "\xff\x14\xc5", 3);
  224.     if ( retval != 0 ) {
  225.         dbgprint("long mode : sys_call_table is at %p\n",
  226.                 (void *) (* (unsigned long *)(retval+3)) ) ;
  227.         retval = (unsigned long) ( * (unsigned long *)(retval+3) );
  228.     } else {
  229.         printk("long mode : memmem found nothing, returning NULL:( \n");
  230.         retval = 0;
  231.     }

  232. #undef OFFSET_SYSCALL
  233.     return retval;
  234. }/*}}}*/




  235. static int get_syscall_init_module(void)
  236. {/*{{{*/
  237.     printk(KERN_DEBUG "get_syscall: Hi, you fucking linux!\n");

  238.     my_ia32_syscall_table = (void **) get_syscall_table_ia32();
  239.     if (my_ia32_syscall_table == 0)
  240.         return -1;

  241.     my_syscall_table = (void **) get_syscall_table_long();
  242.     if (my_syscall_table == 0)
  243.         return -1;

  244.     dbgprint("ia32_sys_call_table address : %p\n", (void *) my_ia32_syscall_table);
  245.     dbgprint("long mode : sys_call_table address : %p\n", (void *) my_syscall_table);

  246. #define REPLACE_IA32(x) o_sys_##x = my_ia32_syscall_table[__NR_ia32_##x];\
  247.     my_ia32_syscall_table[__NR_ia32_##x] = my_sys_##x

  248. #define GET_OLD_IA32_SYSCALL_ADDR(x) my_ia32_syscall_table[__NR_ia32_##x]
  249. //    dbgprint("sys_read at %p, my_read at %p\n", (void *)GET_OLD_IA32_SYSCALL_ADDR(read), (void *)my_sys_read);

  250. //    REPLACE_IA32(read);
  251. #undef REPLACE_IA32


  252.     return 0;
  253. }/*}}}*/


  254. static void get_syscall_exit_module(void)
  255. {/*{{{*/
  256.     printk(KERN_DEBUG "get_syscall: bye, you fucking linux!\n");

  257. #define RESTORE_IA32(x) my_ia32_syscall_table[__NR_ia32_##x] = o_sys_##x

  258. //    RESTORE_IA32(read);

  259. #undef RESTORE_IA32
  260. }/*}}}*/

  261. module_init(get_syscall_init_module);
  262. module_exit(get_syscall_exit_module);
复制代码




Reference :
http://phrack.org/archives/58/p58-0x07

[ 本帖最后由 albcamus 于 2007-1-19 09:33 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2007-01-18 20:38 |只看该作者
不错。

论坛徽章:
0
3 [报告]
发表于 2007-01-18 20:48 |只看该作者
不错,顶了

论坛徽章:
0
4 [报告]
发表于 2007-01-19 09:33 |只看该作者
这个程序前天刚刚做完, 没怎么测试, 我仅仅在linux-2.6.18  Turion64 X2上测试过, 欢迎大家测试, 把BUG发给我

论坛徽章:
0
5 [报告]
发表于 2008-02-16 09:55 |只看该作者
直接oops,在替换系统调用的时候

我好像看过i386的一篇文章,应该也是你写的吧,在替换之前清掉cr0的第20位, 这个64位的不用清吗?

论坛徽章:
0
6 [报告]
发表于 2008-02-16 09:56 |只看该作者
我现在是能够找到syscall_table的地址,但是,一替换就死机

论坛徽章:
0
7 [报告]
发表于 2008-02-17 08:50 |只看该作者
我查了查,cr0的第5-30位都必须为0,第31位为PE位,
不知道第20位是干什么的,望解惑
谢谢

论坛徽章:
0
8 [报告]
发表于 2008-02-18 09:30 |只看该作者
原帖由 anhongkui 于 2008-2-17 08:50 发表
我查了查,cr0的第5-30位都必须为0,第31位为PE位,
不知道第20位是干什么的,望解惑
谢谢


看手册卷三图2-6

论坛徽章:
0
9 [报告]
发表于 2008-02-18 15:06 |只看该作者
请问是什么手册?
哪里能够找到这个手册?

我只找到了一个关于讲保护模式的
谢谢

论坛徽章:
0
10 [报告]
发表于 2008-02-18 17:45 |只看该作者
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP