SunBo

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
[bobo]$ cat gotover.c
#include <stdio.h>
#include <string.h>
 
int evil_code(char *s)
{
        printf("hi, I am here!/n");
        return 0;
}
10   
11  int main(int argc, char *argv[])
12  {
13          long addr = *(long *)((long)strlen + 2);
14   
15          *(long *)addr = (long)evil_code;
16   
17          int len = strlen(argv[0]);
18   
19          printf("len = [%d]/n", len);
20   
21          return 0;
22  }
23   
24  [bobo]$ gcc gotover.c -o gotover
25  [bobo]$ ./gotover 
26  hi, I am here!
27  len = [0]

看了这篇帖子,理解了上面这段程序,直接修改栈内容。

详细内容可以参考 , 还有一篇alert7写的动态库符号解析过程
大概是这样的:
对于32位的x86,调用动态库中的函数,比如 printf(); 调用的其实是plt中的一小段代码,这一小段代码如:
address + 0: jmp *0xXXXXXXXX
address + 6 : push 一个常数
jmp 0xYYYYYYYY
第一次调用printf时地址0xXXXXXXXX中的值就是address + 6, 也就是第一次jmp会跳到 address + 6的地方,然后下一个jmp进行如号解析,然后在0xXXXXXXXX中写入真实的printf函数的地址,之后再调用printf时就会直接跳到printf函数去了。
我前面那个代码就是在0xXXXXXXXX中放入evil_code()函数的地址,address + 0: jmp *0xXXXXXXXX 这条指令占用6个字节,前面两个是操作码,后面就是地址,所以有代码中"  + 2"

 

跑了帖子中更能清晰理解栈结构的例子,结果如下:

[S@fedora-1 test]$ cat test1.c
#include

int gi = 1;

f(char *fmt, int *p, int v)
{
        int i;

        for(i = 0; i < 8; i++) {
                printf("%d %p %p/n", i, &i + i, *(&i+i));
        }
        printf("p = %p v = %d/n", p, v);
        return;

        for(i = 0; i < 256; i++) {
                printf("addr = %p value = %d/n", &gi, gi);
        }
}

main()
{
        f("fmt", &gi, gi);
}
[S@fedora-1 test]$ ./a.out
0 0xbf8daf24 (nil)
1 0xbf8daf28 0xbf8daf48
2 0xbf8daf2c 0x8048469
3 0xbf8daf30 0x804855d
4 0xbf8daf34 0x80496d4
5 0xbf8daf38 0x1
6 0xbf8daf3c 0x80484a9
7 0xbf8daf40 0xa7add0
p = 0x80496d4 v = 1

 

程序中的局部数组溢出使用,就能改变栈,结果不可预料。打印出荒唐的信息。

摘自:http://bbs.chinaunix.net/viewthread.php?tid=1652842&extra=page%3D1%26amp;filter%3Ddigest&page=6

posted on 2010-03-12 17:57  SunBo  阅读(286)  评论(0编辑  收藏  举报