ROP-ret2libc-32实例
ROP 32位实例
32位思路:
1、想办法调用execve("/bin/sh",null,null)
2、传入字符串/bin///sh
3、体统调用execve
eax = 11
ebx = bin sh_addr
ecx = 0
edx = 0
int 0x80
代码如下:
接下来我们检查保护
我们看到是有NX保护,没有canary和pie保护,我们使用ROP进行绕过。关键在于如何获取system 和 /bin/sh。
objdump -d -j .plt ./ret2libc1_32 |grep system
-d 是查看反汇编代码
-j 指定 指定我们后面的plt
然后发现这个程序没有调用system函数的
发现没有这个"/bin/sh"
那就只能自己写了
现在的情况就是没有调用system函数,没有string"/bin/sh",而且有NX保护,所以就要使用ret2libc,ret2libc属于system函数,动态连接库中的函数之间相对偏移是固定的。即使程序有ASLR保护,也只是针对于地址中间位进行随机,最低的12位并不会发生改变
思路:
1、泄露ret2libc_32 任意一个函数的位置
2、获取libc的版本号
3、根据偏移获取shell和sh的位置
4、执行程序获取shell
使用ldd列出动态库的利用关系
现在来计算一下程序的偏移
那么我们现在可以准备exp了
exp思路:
offset是我们用cyclic计算出的
返回地址呢就是用wirte函数来获取真实地址
首先获取write的plt地址
然后获取got表的地址
vul的地址是可以用disass vul来查看,或者用e.symbols来获取
执行完payload1之后就write函数就可以打印出libc函数的真实地址
发送这里使用的是sendlineafet()就是检测到hello之后发送payload1
接收完之后解包,也就是u32()
声明一下libc的文件变量
libc的基地址就是真实地址减去偏移
(libc库中存放的都是偏移,偏移+基地址就可以用了)
找个时候我们要使用system函数,所以就是基地址+e.symbol[‘system’]
然后要找的是system函数中的参数也就是字符串bin/sh 使用第一个就可以,所以就是next()
准备就绪我们要准备payload2
偏移 + system的函数 +返回到哪都无所的+bin/sh这个参数
最后获取交互环境即可
ROP 64位实例
还记着我64和32最大的区别吗?
32是栈传递 64是寄存器调用
调用路径:
/usr/include/x86_64-gnu/asm/unistd_64.h
![在这里插入图片描述](https://img-blog.csdnimg.cn
64位系统中使用寄存器传递参数(32bit是栈哦)
rdi、rsi、rdx、rcx、r8、r9(1-6个参数)
write(1,buf2,20)
需要控制3个参数,rdi,rsi,rdx
第三个参数代表着输出的size,如果没有rdx的gadget可以暂时不管
输出多少无所谓
思路:
1、想办法调用execve("/bin/sh",null,null)
2、借助栈来传入字符串/bin/sh
3、系统调用execve
rax = 0x3b(64bit)
rdi = bin_sh_addr
rsi = 0
rdx = 0
大家有没有注意到啊,32bit的时候是///sh,64的时候恢复成了/sh,这是因为34位是4字节,64是8字节,是完全可以放下这个字符串的,不需要担心反斜杠0的问题。
实例代码如下:
64位exp的思想主要是ret2syscall的思想
第三个实例
step 1
检查保护
开启了NX保护,这个时候我们要想到ret2shellcode和ret2libc
step 2 使用IDA进行流程分析
step 3 objdump查看一下汇编代码吧
objdump -d -M intel ret2libc1