| 1 | [bobo]$catgotover.c |
| 2 | #include<stdio.h> |
| 3 | #include<string.h> |
| 4 | |
| 5 | intevil_code(char*s) |
| 6 | { |
| 7 | printf("hi,Iamhere!\n"); |
| 8 | return0; |
| 9 | } |
| 10 | |
| 11 | intmain(intargc,char*argv[]) |
| 12 | { |
| 13 | longaddr=*(long*)((long)strlen+2); |
| 14 | |
| 15 | *(long*)addr=(long)evil_code; |
| 16 | |
| 17 | intlen=strlen(argv[0]); |
| 18 | |
| 19 | printf("len=[%d]\n",len); |
| 20 | |
| 21 | return0; |
| 22 | } |
| 23 | |
| 24 | [bobo]$gccgotover.c-ogotover |
| 25 | [bobo]$./gotover |
| 26 | hi,Iamhere! |
| 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
栈溢出与动态库符号解析
本文通过一个具体的C语言程序示例介绍了如何利用栈溢出来修改内存内容,并解释了32位x86架构下动态链接库中函数调用的工作原理。深入探讨了通过修改栈内容来实现特定函数调用的技术细节。
967

被折叠的 条评论
为什么被折叠?



