puts
函数打印库函数的地址 , 减掉该库函数与libc
加载基地址的偏移 , 就可以计算libc
的基地址 。然后可以利用libc
中的gadget构造可以执行 " /bin/sh" 的ROP , ROPgadget使用ROPgadget检查程序中是否存在/bin/sh字符串或某条指令:ROPgadget --binary 文件名 --string="/bin/sh"ROPgadget --binary 文件名 --sting '/bin/sh'命令: ROPgadget --binary 文件名 --sting 'sh'命令: ROPgadget --binary 文件名 --sting 'cat flag'命令: ROPgadget --binary 文件名 --sting 'cat flag.txt'ROPgadget --binary 文件名 --only="pop|ret"用ROPgadget找一下程序里有没有可以用的改变rdi寄存器的值的gadgetsROPgadget --binary 文件名 --only "pop|ret" | grep rdi
栈溢出栈溢出指的是程序向栈中某个变量中写入的字节数超过了这个变量本身所申请的字节数 , 因而导致与其相邻的栈中的变量的值被改变 。这种问题是一种特定的缓冲区溢出漏洞 , 类似的还有堆溢出 , bss 段溢出等溢出方式 。栈溢出漏洞轻则可以使程序崩溃 , 重则可以使攻击者控制程序执行流程 。此外 , 我们也不难发现 , 发生栈溢出的基本前提是
- 程序必须向栈上写入数据 。
- 写入的数据大小没有被良好地控制 。
#include <stdio.h>#include <string.h>void success() { puts("You Hava already controlled it."); }void vulnerable() {char s[12];gets(s);puts(s);return;}int main(int argc, char **argv) {vulnerable();return 0;}
这个程序的主要目的读取一个字符串 , 并将其输出 。我们希望可以控制程序执行 success 函数 。输入
gcc -m32 -fno-stack-protector stack1.c -o stack1 -no-pie -z execstack
进行编译 , 可以看见报错了(但仍会生成可执行文件) , 可以看出 gets 本身是一个危险函数 。它从不检查输入字符串的长度 , 而是以回车来判断输入是否结束 , 所以很容易可以导致栈 溢出 , 文章插图
gcc 编译指令中 ,
-m32
指的是生成 32 位程序; -fno-stack-protector
指的是不开启堆栈溢出保护 , 即不生成 canary 。-z execstack
表示开启栈的可执行权限 , 在gcc4.1中默认禁用 , 此外 , 为了更加方便地介绍栈溢出的基本利用方式 , 这里还需要关闭 PIE(Position Independent Executable) , 避免加载基址被打乱 。不同 gcc 版本对于 PIE 的默认配置不同 , 我们可以使用命令gcc -v
查看 gcc 默认的开关情况 。如果含有--enable-default-pie
参数则代表 PIE 默认已开启 , 需要在编译指令中添加参数-no-pie
。编译成功后 , 可以使用 checksec 工具检查编译出的文件:
文章插图
提到编译时的 PIE 保护 , Linux 平台下还有地址空间分布随机化(ASLR)的机制 。简单来说即使可执行文件开启了 PIE 保护 , 还需要系统开启 ASLR 才会真正打乱基址 , 否则程序运行时依旧会在加载一个固定的基址上(不过和 No PIE 时基址不同) 。我们可以通过修改
/proc/sys/kernel/randomize_va_space
来控制 ASLR 启动与否 , 具体的选项有
经验总结扩展阅读
- 四十一 增删查改分页 Java开发学习----MyBatisPlus标准数据层开发
- 中 学习ASP.NET Core Blazor编程系列十——路由
- CC1,3,6回顾
- 图学习【参考资料2】-知识补充与node2vec代码注解
- 二十四 设计模式学习:Spring 中使用到的设计模式
- Java安全之CC3
- TensorFlow深度学习!构建神经网络预测股票价格!?
- JUC学习笔记——共享模型之管程
- Seata Server 1.5.2 源码学习
- 2022极端高温!机器学习如何预测森林火灾?? 万物AI