Chinaunix首页 | 论坛 | 博客
  • 博客访问: 232897
  • 博文数量: 37
  • 博客积分: 933
  • 博客等级: 军士长
  • 技术积分: 511
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-16 10:15
文章分类
文章存档

2012年(1)

2011年(36)

分类: LINUX

2011-04-19 14:51:17

  1. #include<stdio.h>
  2. #include <sys/socket.h>
  3. #include <sys/user.h>
  4. #include <sys/types.h>
  5. #include <sys/wait.h>
  6. #include <inttypes.h>
  7. #include <sys/reg.h>
  8. #include <unistd.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <sys/mman.h>
  12. #include <sys/personality.h>

  13. void (*aaa)();

  14. void null_func()

  15. {

  16. printf("THIS is NULL!!!\n");

  17. }

  18. void map_and_call_null()

  19. {

  20.         char *addr = NULL;

  21.         addr = mmap(0, 0x1000, PROT_READ|PROT_WRITE|PROT_EXEC,MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, 0, 0);

  22.         addr[0] = '\xff';

  23.         addr[1] = '\x25';
  24.         *(unsigned int *)&addr[2] = 6;

  25.         *(unsigned long *)&addr[6] = (unsigned long)&null_func;


  26.         aaa = NULL; //...NULL

  27.         (*aaa)();

  28.         int *empty = NULL;
  29.         printf("%x\n",*empty);
  30.         printf("%x\n",*(empty+1));
  31.         printf("%x\n",*(empty+2));
  32. }

  33. int main()

  34. {

  35.         map_and_call_null();

  36. }
我们都知道 对于NULL指针的应用是不对的,然而更加深入的探讨NULL指针后你会发现:NULL其实只是一个概念性的东西,也就是说 如果我原因 我可以把任何地址规定为NULL,只要我对其进行处理就可以了。
 
那么我们会有一个疑问:既然NULL是形式上的概念 ,我们可以利用0地址呢?答案是当然可以。
1)首先,我们通过系统调用mmap 将线性地址的第一个PAGE 加入VMA。注意:必须带用参数MAP_FIXED 否则你系统的
[root@localhost ~]# cat /proc/sys/vm/mmap_min_addr
4096
这个变量值会限制你必须从第二页空闲的地方开始映射。
2)通过1,第一个线性地址page(0-4095),我们已经可以利用,我们写入我们要跳转去执行的函数 指令
 
        addr[0] = '\xff';
        addr[1] = '\x25';
        *(unsigned int *)&addr[2] = 6;
        *(unsigned long *)&addr[6] = (unsigned long)&null_func;
这里有几个地方需要说明一下:
        0xff25 这是无条件绝对跳转的opcode
        后面紧跟的四个字节:0x00000006 指示了jmp将要跳去的地址在哪。
        在这里jmp要跳去的地址存储在0x00000006线性地址中,而0x00000006线性地址存储的正是函数null_func的地址。
3)OK,一切准备就绪。main函数首先调用map_and_call_null(),然后调用aaa函数。此时eip寄存器的值就为0x00000000,CPU去执行0地址处的代码。而0地址处的代码为一绝对跳转指令。从而,去执行了null_func函数。
这就是所谓的hook吧。。。。。
 
而内核代码是如何处理NULL的呢?
 
我们知道,缺页时,会触发CPU发出一个PGFAULT缺页异常,而对于缺页异常,由函数do_page_fault进行处理。在将发生缺页异常的线性地址保存在address变量中后,函数转去__do_page_fault 进行处理。
由于存在相应的VMA(mmap函数调用的结果)所以函数不会转去:进行处理。由于我们是读请求造成的缺页,调用handle_mm_fault进行处理,处理完成后,函数返回。
 
我们的函数也得以继续执行完成,不会被KILL掉。。no segment fault :)
阅读(1855) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~