ret2libc攻击方式:针对动态链接(Dynamic linking) 编译的程序,静态链接一般利用简单ROP能构造出payload进行攻击(详见ROP博客)。一般情况下无法在程序中直接找到system、execve这一类系统函数,动态链接过程中动态连接器会将程序所有需要的链接库加载到内存进程空间,而libc.so是最基本的一个。
libc.so 是 linux 下 C 语言库中的运行库glibc 动态链接版,里面包含了大量可利用的函数,ret2libc的原理便是将 libc.so在内存中我们所需要的函数返回地址获取,进而取得控制权。通常是利用system("/bin/sh")打开shell,简单可以判定为两个步骤:
1.system地址获取
2."/bin/sh"字符串地址获取
现在需要了解动态链接的过程:
1) 重点理解PLT以及got (Global offset Table)表:
【pwn】CTF学习:4、PLT表与GOT表 | 延迟绑定机制_哔哩哔哩_bilibili
调用动态链接函数时,如printf函数时,先去plt表和got表寻找printf函数的真实地址。plt表指向got表中的地址,got表指向glibc中的地址。
即第一次调用:plt->got->plt->公共plt->动态连接器_dl_runtime_resolve->锁定函数地址
第二次:plt->got->直接锁定函数地址,此时got表已记录函数地址
got表:包含函数的真实地址,包含libc函数的基址,用于泄露地址
plt表:不用知道libc函数真实地址,使用plt地址就可以调用函数
libc就是linux下的c函数库:
libc中包含着各种常用的函数,在程序执行时才被加载到内存中
libc是一定可以执行的,跳转到libc中函数绕过NX保护
攻击步骤:
1、泄露任意一个函数的真实地址:只有被执行过的函数才能获取地址
2、获取libc的版本
3、根据偏移获取shell和sh的位置:a、求libc的基地址(函数动态地址-函数偏移量)b、求其他函数地址(基地址+函数偏移量)
4、执行程序获取shell
实例代码:
1)源码中不包含system及sh等敏感信息,推测是泄露libc基地址来进行exp
2)当执行vuln函数后,会生成write的got表地址,通过got的地址可以寻址到write函数的真实地址(里面保存的数值就是write函数的真实地址),同时在第一次read时可构建payload获取write@got,同时将vuln地址写入read中进行二次调用,达到第二次payload机会。最后再利用第一次的got地址进行获取system和/bin/sh的地址进行二次payload构建
代码构建过程:
首先确认linux 调用的so文件(远程一般会给相应so文件,没有的话用libsearch寻址):
构造第一次payload:
发送后获取write_addr:
此时write的真实地址已找出,便可以计算出libc的真实地址,基于此真实地址便可以进行第二次payload构造(忽视打错了):
至此完成payload提权