BROP的使用环境:
不能直接构造ROP gadget
目标服务在崩溃后会重新运行
Canary不会重置,没有ASLR
这是因为Blind ROP其实核心部分都是类似于爆破的概念,
因此会不断的引起目标服务崩溃,挂起,如果崩溃后不能重新启动,
且启动后Canary或者其他地址改变,那么之前的爆破也就无意义了。
那么BROP每一步在做什么呢。
爆破Canary:
当我们获取到崩溃长度后,根据
Canary->EBP->Ret
的栈结构,我们可以开始爆破Canary,爆破的方法就是一字节一字节爆破。
获取Hang addr和PLT:
随后就是找hang gadget了,这个也叫stop gadget。
这种特殊的地址,既不会造成Nginx崩溃,也不会造成Nginx返回内容,
而是让进程进入无限循环,挂起或者sleep的状态,
它是我们后面寻找BROP gadget的重要依据。
plt的原理和hang gadget很像。
在这之前我大概说一下为什么找plt的原理和hang gadget很像。
plt项是连续的,而且在0字节,和6字节之后执行的内容都会正常进入后续处理,
而不会崩溃或有返回,因此只要连续有多个16字节都会让进程block且每个16字节地址+6之后,
也会block,那么这就有可能是个plt项。
找到BROP gadget:
接下来,有了hang gadget,我们就可以找到BROP gadget了,这个BROPgadget,是我们组成在开头提到通过write方法dump内存的重要部分,
和ROP gadget的概念很像,为了组成这个write函数,需要三个参数,
也就是需要三个ROP gadget:
pop rdi,ret;
pop rsi,ret;
pop rdx,ret;
因为在64位Linux中,参数不是靠push寄存器入栈决定的,
而是由寄存器本身决定的,这三个参数对应的就是rdi,rsi和rdx寄存器中的内容。
因此我们利用hang gadget来暴力搜索这些BROPgadget,如何判断呢?
在ret后放很多hangaddr,只要命中pop ret,pop pop ret这种gadget,都会进入block状态,通过这种方法,我们找到6个pop ret,就能找到一个在linux下常见的结构,通过计算这个结构的偏移,
就能得到pop rsi,ret和pop rdi,ret了。
找到strcmp plt和write plt
这一步完成后,我们就需要进行strcmp和write对应plt项的查找了,
为什么要找strcmp呢,因为strcmp的汇编功能是对rdx赋予一个长度值,
通过这种方法可以对rdx,
也就是第三个参数赋值,因为在.text字段中很难找到pop rdx,ret这样的gadget。
找这两个plt项,需要利用这两个plt项的特性,
比如strcmp就是对比两个字符串内容。如果两个字符串相等,
没有崩溃,且不相等,crash的话,这就是一个strcmp。
Dump内存,执行shellcode
跳出内存完成正常攻击,
或者使用libcdatabase找出libc版本