三种基础题型
1.ret2text
原理:
顾名思义,ret2text指的是漏洞利用点就在原文件中,即进程存在危险函数如system("/bin")或execve("/bin/sh")的片段,可以直接劫持返回地址到目标函数地址上。从而getshell。
利用前提:
程序开启了NX,栈上无法写入shellcode。
代码:
1 | void test(){ |
利用思路:
1.checksec和file 查看文件信息和文件保护。
2.把文件丢进ida中查看源码(如上)。
3.确认是ret2text在pwndbg中找偏移量
4.编写脚本。
脚本exp:
1 |
|
2.ret2shellcode
原理:
ret2shellcode,即控制程序执行shellcode代码。shellcode指用于完成某个功能的汇编代码,常见功能主要是获取目标系统的shell。一般来说,shellcode需要我们自己填充。
说白了,程序中没有类似system("/bin/sh")后门函数,需要自己填充。
利用前提:
1 . 程序存在溢出,且能够控制返回地址
2 . 程序运行时,shellcode所在区域有可执行权限(NX保护关闭、bss段可执行)
3 . 操作系统关闭ASLR保护(或关闭PIE保护)
代码:
1 | int __cdecl main(int argc, const char **argv, const char **envp){ |
利用思路:
1 . file和checksec查看文件信息,丢到ida中查看程序运行逻辑
2 . 找到程序的栈溢出漏洞,用pwndbg找到偏移量offset
3 . 在ida中查看bss段或者用pwndbg的vmmap查看bss段(一般是用户创建的变量在bss段中)
4 . 构造shellcode, 构造payload,构造exp
脚本exp:
1 |
|
其中asm函数将 汇编指令→二进制机器码 ,逆操作为disasmshellcraft.p()获得执行system("/bin/sh")的汇编指令,效果等价于执行system("/bin/sh")但更底层、不依赖libc。
3 . ret2syscall(32位ELF)
原理:
顾名思义,ret2syscall就是调用系统函数以达到getshell的目的
要做的就是:让程序调用execve("/bin/sh", NULL, NULL)函数即可拿到shell.
利用前提:
NX 开启,存在栈溢出,程序存在可以利用的gadgets
一般是静态链接,这样会有较多可以用的gadgets.
代码:
1 | int __cdecl main(int argc, const char **argv, const char **envp){ |
利用思路:
开启了NX保护,无法使用ret2shellcode,没有system函数,也不能使用ret2text,考虑直接利用程序的gadgets,控制rop链,最后直接执行execve(“/bin/sh”)
实现条件:
用 ROPgadget 查找符合条件的gadgets.
1 | ROPgadget --binary rop --only "pop|ret" | grep "xxx" |
目的是达到:
32位操作系统
系统调用号,即eax应该为 0xb
第一个参数,即ebx应该指向 /bin/sh的地址,其实执行sh的地址也可以
第二个参数,即ecx应该为 0
第三个参数,即edx应该为 0
64位操作系统
系统调用号,即rax应该为 0x3b
第一个参数,即rdi应该指向 /bin/sh的地址,其实执行sh的地址也可以
第二个参数,即rsi应该为 0
第三个参数,即rdx应该为 0
补充关键注意点
1 . 构造 payload 时需在syscall指令前加一个ret指令,保证执行syscall时栈满足 16 字节对齐,否则系统调用会失败;
2 . 上述寄存器传参顺序严格遵循 64 位 Linux 系统调用规范,不可混淆(如不能用rbx替代rdi传第一个参数)。
脚本exp:
1 | # 32位 |
1 |
|






