内存溢出,技术求解

xmu_才盛 2009-02-07 01:34:31
看这段代码,下面是我不成熟的分析及提问,望踊跃回答。
#include <stdio.h>;
void overFlow ()
{
int a[] = { 0x78787868 };
*(a + 2) += 7;
}

int main ()
{
int aa = 3;
overFlow ();
aa = 4;
printf ("%d\n", aa);
}

结果还为3. (请解释一下)


自己的设想:
查看到*(a+1)的值正好是&aa+sizeof(int),由此猜想缓冲区(堆)中*(a+1)的值应该是代码中函数的返回地址
aa = 3; -------------1(内存)
overFlow (); --------5
aa = 4;--------------9


提问:
1.a+2到底改的是什么内容,能让程序跳到哪里?
2.我的设想是不是错了,a+1不是返回地址,而a+1同a+2共同确定返回地址(类似于段地址+offset)
...全文
317 32 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
32 条回复
切换为时间正序
请发表友善的回复…
发表回复
yuzl32 2009-02-08
  • 打赏
  • 举报
回复

void overFlow()
{
int a[] = { 0x78787868 };
*(a + 2) += 7; //将main函数中的下一条指令地址+7,也就是跳过了aa = 4。为什么+7,看下面的分析.
}


.text:00401020 ; int __cdecl main(int argc, const char **argv, const char *envp)
.text:00401020 _main proc near ; CODE XREF: ___tmainCRTStartup+15Ap
.text:00401020
.text:00401020 var_4 = dword ptr -4
.text:00401020 argc = dword ptr 8
.text:00401020 argv = dword ptr 0Ch
.text:00401020 envp = dword ptr 10h
.text:00401020
.text:00401020 push ebp
.text:00401021 mov ebp, esp
.text:00401023 push ecx
.text:00401024 mov [ebp+var_4], 3
.text:0040102B call sub_401000 ; 调用overFlow ();
.text:00401030 mov [ebp+var_4], 4 ; aa = 4;这条指令占7个字节(00401037-00401030)
.text:00401037 mov eax, [ebp+var_4]
.text:0040103A push eax
.text:0040103B push offset unk_40C000
.text:00401040 call sub_40104E
.text:00401045 add esp, 8
.text:00401048 xor eax, eax
.text:0040104A mov esp, ebp
.text:0040104C pop ebp
.text:0040104D retn
.text:0040104D _main endp


int a[] = { 0x78787868 };
*(a + 2) += 7;
在中间加一个局部变量。结果还是3,为什么呢?
----------------------------------------
因为在中间加个局部变量也不影响*(a + 2)的指向,如果在int a[] = ... 上加变量的话,*(a + ?) += 7; 问号处就要修改了。
xmu_才盛 2009-02-07
  • 打赏
  • 举报
回复
[Quote=引用 27 楼 tianya0609 的回复:]
引用 19 楼 newstudent_never 的回复:
感谢上边的哥们们,

本函数局部变量*a ebp(*(a+1)) 汇编返回地址(*(a+2))
78787868 0x0012ff80 0x004010C4 +7= printf起始地址


还有一个问题 ebp存贮的应该是堆栈指针,那么这个指针所指向的堆栈是存储什么的?

int a[] = { 0x78787868 };
*(a + 2) += 7;
在中间加一个局部变量。结果还是3,为什么呢?
[/Quote]

直接在汇编的层次上跳过了一些执行语句
xqhrs232 2009-02-07
  • 打赏
  • 举报
回复
好东西,学习了
hechaomyoracle 2009-02-07
  • 打赏
  • 举报
回复
结果是为3,我有事下次在做说明
xqhrs232 2009-02-07
  • 打赏
  • 举报
回复
debug一下,看内存就可以明白一切吧?!
tianya0609 2009-02-07
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 newstudent_never 的回复:]
感谢上边的哥们们,

本函数局部变量*a ebp(*(a+1)) 汇编返回地址(*(a+2))
78787868 0x0012ff80 0x004010C4 +7= printf起始地址


还有一个问题 ebp存贮的应该是堆栈指针,那么这个指针所指向的堆栈是存储什么的?
[/Quote]
int a[] = { 0x78787868 };
*(a + 2) += 7;
在中间加一个局部变量。结果还是3,为什么呢?
hityct1 2009-02-07
  • 打赏
  • 举报
回复
mark
xmu_才盛 2009-02-07
  • 打赏
  • 举报
回复


那怎么样将返回位置定为启动command.com 这个shell呢?

看来要研究一下了
yutaooo 2009-02-07
  • 打赏
  • 举报
回复

我是打酱油的。tangshuiling 才是正规军啊。应该谢谢他呀。^_^
thunderarch 2009-02-07
  • 打赏
  • 举报
回复
建议你看看函数栈的结构。

+7主要看你后面的aa = 4.占用几个字节。

如果aa=4占9个字节,那么如果你想要跳过它,就需要加 9.

如果加的东西用问题,你的 代码就会崩溃。

你可以反汇编看看aa =4占用几个字节。(不同的指令占用的字节数是不同的。)
xmu_才盛 2009-02-07
  • 打赏
  • 举报
回复
20楼 的哥们,谢谢了。
xmu_才盛 2009-02-07
  • 打赏
  • 举报
回复
同上楼

搞懂了一些东西,谢谢各位了。

yutaooo 2009-02-07
  • 打赏
  • 举报
回复

ebp 存储的是 帧指针。就是本函数的栈底。
xmu_才盛 2009-02-07
  • 打赏
  • 举报
回复
感谢上边的哥们们,

本函数局部变量*a ebp(*(a+1)) 汇编返回地址(*(a+2))
78787868 0x0012ff80 0x004010C4 +7= printf起始地址


还有一个问题 ebp存贮的应该是堆栈指针,那么这个指针所指向的堆栈是存储什么的?
AlwaysSLH 2009-02-07
  • 打赏
  • 举报
回复
学习了
yutaooo 2009-02-07
  • 打赏
  • 举报
回复

哦 。有汇编代码了。



004010C4 mov dword ptr [ebp-4],4



这条指令 7 字节咯。
yutaooo 2009-02-07
  • 打赏
  • 举报
回复

根据上面的讨论。小结一下。


1.
a[0]: 0x78787868
a[1]: saved_esp
a[2]: ret_addr -> address of 'aa = 4'
2.
aa = 4 -> movl $4, %eax -> 5byte



所以,我觉得 *(a + 2) += 5;就好了。为什么要 +7 ??
vincent_1011 2009-02-07
  • 打赏
  • 举报
回复
楼主喜欢这方面的知识,不妨买failwest写的0day安全那本书

专门写这方面的,有所有你想要的知识
xmu_才盛 2009-02-07
  • 打赏
  • 举报
回复
这就是为什么要加7
13: aa = 4;
004010C4 mov dword ptr [ebp-4],4
14: printf ("%d\n", aa);
004010CB mov eax,dword ptr [ebp-4]
004010CE push eax
004010CF push offset string "%d\n" (0042201c)
004010D4 call printf (00401150)
004010D9 add esp,8

004010C4+7=004010CB--------------开始执行printf
xmu_才盛 2009-02-07
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 thunderarch 的回复:]
#include <stdio.h>;
void overFlow ()
{
int a[] = { 0x78787868 };
*(a + 2) += 7;--------------------> a+2 实际上已经是你overFlow()函数在mian函数中调用时的返回地址(a+1 是 保存的ebp),所以你修改了函数的返回地址。 程序应该是不能正常返回的。结果可能会根据不同的编译器有所不同。 但是这样做事非常危险的,典型的栈溢出。 以前的shellcode就是这么搞,用来编写病毒等。 有兴趣的话可以研究研究。
} …
[/Quote]


9楼的哥们,我是故意这么写的,就是需要知道怎么样用溢出覆盖,而改变返回值的!

还想知道为什么+7就能够跳过aa=4的执行而进入printf.
而且给overFlow加上一个参数后就会内存泄露,估计也是+7所导致的。很想知道是不是加上参数后就修改了执行代码在内存中的位置了,所以泄露了
加载更多回复(12)

65,189

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧