Return2libc --- 修改函数返回地址 , 让其指向内存中的一段指令
该类攻击方法的主要任务是 : 在内存中确定某个函数的地址 , 并用其覆盖掉返回地址 .
由于 libc 动态链接库中的函数被广泛使用 , 所以大概率可以在内存中找到该动态库 , 同时由于该库包含了一些系统级函数( 比如 system()
... ) , 因此可以使用这些系统级函数来获得当前进程的控制权
Libc : C standard library( C标准函数库 ) , 是在C语言程序设计中 , 所有匹配标准的头文件的集合 , 以及常用的函数库实现程序 , 几乎所有的C语言程序都是由标准库的函数来创建的
Libc泛指C标准函数库 , 而应用最广泛 , 功能最强大的当属 GNU Libc( glibc ) . 它属于GNU 系统的标准C库 , 其中定义了用C语言编写程序时所需的系统调用和其他基本功能 , 它不仅处理与内核通信的低级功能( 比如进程管理和文件管理 ) , 也处理更高级别的功能( 比如字符串操作或者命令行参数处理 )
libc 的动态库文件叫做 libc.so , 通常路径是 /usr/lib/../libc.so , so文件是Linux下的共享库文件 , 其文件格式被称为 ELF 文件格式 .
就拿系统级函数 system()
为例 , 大多数要执行的函数都需要参数 , 比如调用 system()
函数打开 shell 的完整形式为 : system("/bin/bash") . 所以溢出数据中必须包含必要的参数
下面以执行 system("/bin/bash")
为例 , 研究溢出数据的组成部分 , 以及在栈中它们是如何被填充的
- 溢出数据组成分析
在函数调用发生后 , 栈中的结构是这样的
这里溢出数据的组成部分有所不同 , 如下图所示
padding1 : 这里的数据可以任意填充 , 但注意填充数据中不要包含" \x00 " , 否则会截断后面的数据 . 数据长度应该刚好覆盖函数的基地址 address of system() : 这里填写 system() 函数在内存中地址 , 用来覆盖 callee 的返回地址 padding2 : 数据长度是变化的( 比如32位机这里的数据长度为4 ) , 对应调用 system() 函数时的返回地址 , 因为这里只需要打开shell就可以了 , 而不用关心 shell 退出后的事件 , 所以这里padding2可以用任意数据填充 address of "/bin/bash" : "/bin/bash" 在内存中的地址 , 也就是传递给 system() 的参数
- 需要解决的问题
- 返回地址之前的数据 padding1 应该有多长
可以用调试工具( gdb , objdump , ... )查看汇编代码来确定这个距离 , 也可以在运行程序时不断修改输入长度来试探( 如果返回地址被无效地址( 比如 "AAAA" )覆盖 , 则程序会报错并终止 )这与 ShellCode 技术使用的方法相同 , 填充任意字符直到程序因返回地址被覆盖而报错
-
system() 函数地址应该是多少?
这与程序是如何调用动态链接库( 比如 libc )中的函数了 , 若指定函数要被动态链接至程序中 , 运行的程序会先判断动态链接库在内存的起始地址 , 再加上需要的函数在动态链接库中的相对偏移量 , 最终才能得到函数在内存中的绝对地址那么就需要确定动态链接库的内存地址 , 这里同样要考虑 ASLR( 地址空间布局随机化 )技术 , 该项技术会将动态库加载的起始地址做随机化处理 . , 因此如果操作系统开启了 ASLR , 那么程序每次运行时动态链接库的起始地址都会随机变化 , 也就无法确定目标函数相对于内存空间的绝对地址
所以 ,
Return2libc
仅能在操作系统关闭 ASLR 的前提下攻击成功 .在操作系统关闭 ASLR 的前提下 , 可以通过调试工具在程序运行过程中直接查看
system()
函数的绝对地址 . 也可以先查看动态链接库在内存中起始地址 , 再查看system
函数在动态链接库中的相对偏移量 , 计算得到该函数的绝对地址 -
"/bin/bash" 的地址在哪
可以在动态库中搜索这个字符串 , 如果存在就可以按照 动态链接库的起始地址 + 相对偏移量 来确定该字符串的绝对地址若在动态链接库中找不到这个字符串 , 可以把这个字符串加到环境变量中 , 再通过
getenv()
等函数来确定字符串绝对地址
- 返回地址之前的数据 padding1 应该有多长
后续
该方法是通过覆盖 callee 的返回地址来执行动态链接库中的函数的 . 该方法与 ShellCode 类似 , 都需要目标操作关闭 ASLR 防御机制的
那么有没有方法可以绕过 ASLR( 内存空间布局随机化 )的方法呢 ? 接下来你就会看到 ~