返回信息流看“Smashing The Stack For Fun And Profit”里面example3.c
void fun(int a, int b,int c)
{
char buffer1[5];
char buffer2[10];
int *ret;
ret = buffer1 + 12;
(*ret) += 8;
}
void main(){
int x;
x=0;
fun(1,2,3);
x=1;
printf("%d\n",x);
}
作者的目的是修改stack上的返回地址,所以ret = buffer1 + 12;我不知道他的gcc版本,他用的gdb的版本号是GDB 4.15,此时stack的图如下
buffer2 buffer1 sfp ret a b c
<------ [ 12bytes ][ 8bytes ][ 4bytes ][ 4bytes][ ][ ][ ]
top of bottom of
stack stack
所以要达到作者的效果buffer2应该挨着buffer1,buffer1挨着sfp(ebp)。
这是我用GCC: (GNU) 3.4.3编译后的反汇编结果
.file "example3.c"
.text
.globl fun
.type fun, @function
fun:
pushl %ebp
movl %esp, %ebp
subl $56, %esp --问题就在这里,要达到作者效果,这里应该是subl $20, %esp 才对吧
leal -24(%ebp), %eax
addl $12, %eax
movl %eax, -44(%ebp)
movl -44(%ebp), %edx
movl -44(%ebp), %eax
movl (%eax), %eax
addl $8, %eax
movl %eax, (%edx)
leave
ret
.size fun, .-fun
.section .rodata
.LC0:
.string "%d\n"
.text
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
movl $0, %eax
addl $15, %eax
addl $15, %eax
shrl $4, %eax
sall $4, %eax
subl %eax, %esp
movl $0, -4(%ebp)
subl $4, %esp
pushl $3
pushl $2
pushl $1
call fun
addl $16, %esp
movl $1, -4(%ebp)
subl $8, %esp
pushl -4(%ebp)
pushl $.LC0
call pritnf
addl $16, %esp
leave
ret
我试改了buffer1,2的大小,没有什么规律,好像为本地变量预留的空间是随机的。用vc时也发现过这个问题,它减esp的数值远大于局部变量的大小。
我认为这就是一种反溢出的简单手段,至少不能通过buffer的地址推测返回地址。buffer1,buffer2可能是随机分布在56bytes的空间中。
我在想应该可以用内嵌汇编取得函数的返回地址。
不知道对不对,谁讲讲,谢啦。
这是一条镜像帖。来源:北邮人论坛 / soft-design / #3526同步于 2006/2/16
该镜像源已超过 30 天没有更新,可能在源站已被删除。
SoftDesign机器人发帖
关于溢出与反溢出
zzm7000
2006/2/16镜像同步12 回复
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
nasm的语法看起来很不习惯,我研究过win32下的溢出,VC给局部变量留下的空间是固定的,即是局部变量的总大小,当然是双字对齐的。另外,测试溢出点的时候,对于栈溢出二分法是个不错的方法, 一个程序的溢出点,在同一个平台下,多半是固定的。你说的这种反溢出的简单手段在win32下是行不通的,unix我研究不多,不敢妄下结论。
我没太明白,比如这个
void fun(int a, int b)
{
int d=a;
int e=b;
}
void main()
{
fun(1,2);
}
我用的vs。net 2003
void fun(int a, int b)
{
00411A40 push ebp
00411A41 mov ebp,esp
00411A43 sub esp,0D8h ----这里不是有216字节吗?四字对齐也只需要8字节啊?我没懂
00411A49 push ebx
00411A4A push esi
00411A4B push edi
00411A4C lea edi,[ebp-0D8h]
00411A52 mov ecx,36h ------ 54 54*4=216
00411A57 mov eax,0CCCCCCCCh ------初始化?为什么初始0CCCCCCCCh
00411A5C rep stos dword ptr [edi]
int d=a;
00411A5E mov eax,dword ptr [a]
00411A61 mov dword ptr [d],eax
int e=b;
00411A64 mov eax,dword ptr [b]
00411A67 mov dword ptr [e],eax
}
00411A6A pop edi
00411A6B pop esi
00411A6C pop ebx
00411A6D mov esp,ebp
00411A6F pop ebp
00411A70 ret
大牛再给我讲讲呵
cl version
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86
Copyright (C) Microsoft Corporation 1984-2002.
把你编译好的程序发上来看看,release版的,
我当年在vc6.0下试过,确实是一个int或一个char,就留下一个双字。
另外,你编译出来的是.net程序吗?.net的PE文件格式有所变化,变化还不小,没太研究过了。
【 在 zzm7000 的大作中提到: 】
: 看“Smashing The Stack For Fun And Profit”里面example3.c
: void fun(int a, int b,int c)
: {
: ...................
附件(21.5KB) test.exe