在Android上使用qemu-user运行可执行文件

作者:寻禹@阿里聚安全

前言

QEMU简要介绍:

QEMU可以解释执行可执行程序。既然QEMU可以解释执行可执行程序,那么QEMU就能够知道执行了哪些指令,从而可以跟踪指令的执行。QEMU编译出来的结果分为系统模式和用户模式,QEMU用户模式编译出来的可执行文件名为:qemu-user。关于QEMU更多的介绍请浏览官方网站:QEMU

关于如何编译QEMU用户模式可执行文件,请参考这篇文章:编译可在Android上运行的qemu user mode

    qemu-user的main函数源码在文件”linux-user/main.c”中。

设置前提

本文研究的QEMU用户模式的可执行文件运行在(Android & arm cpu)上,下文中说的“设备”一词指的就是Android arm设备,设备的系统是CyanogenMod12.1 ROM,该ROM基于Android5.1.1。

运行qemu-user

将qemu-user拷贝到设备中,运行该可执行程序时会提示无法找到libglib-2.0.so.0和libgthread-2.0.so.0这两个库,如果读者按照上文中引用的文章《编译可在Android上运行的qemu user mode》编译成功qemu-user,那么这两个库就会存在于Android NDK目录下,将这两个目录拷贝到设备的”/system/lib/”目录下,然后就可以成功运行qemu-user程序。

运行错误解决:FATAL: kernel did not supply AT_SECURE

我在设备上运行qemu-user的时候出现了标题上显示的错误”FATAL: kernel did not supply AT_SECURE”。

 

解决办法一

(解决办法来源:https://gist.github.com/jserv/5019475)

找到”bionic/linker/linker_environ.cpp”文件,按照下面的代码修改该文件:

如果读者用过git再看上面的代码就可以很清楚的知道,上面的代码是运行”git diff”后所显示内容,代码做了哪些修改清楚的显示了出来。如果读者没有见过”git diff”命令所显示的内容,那么这么做:找到”-static void __init_AT_SECURE(KernelArgumentBlock& args) {“这一行,从这行开始(包括这一行)每一行以减号开头的表示删除该行。

文件修改完成后在Android源码根目录运行下面的命令:

    . build/envsetup.sh
breakfast hammerhead
mmm <Android源码根目录>/bionic/linker/

mmm命令用于编译”<Android源码根目录>/bionic/linker/”目录下的源码,这个目录下的源码编译完成后会生成一个名为”linker”的可执行文件,这个可执行文件的生成目录会在终端上显示出来,将这个linker覆盖设备上的”/system/bin/linker”文件。

覆盖设备上的”/system/bin/linker”文件的实际操作中,覆盖需要需要ROOT权限。”/system/bin/linker”文件覆盖完成以后,它的文件权限是这样的:

    -rwxr-xr-x root     root       91902 2016-05-01 21:50 linker

即linker属于root用户,并属于root用户组。但是linker原本的权限是下面这样的:

    -rwxr-xr-x root     shell       91902 2016-05-01 21:50 linker

即linker属于root用户,并属于shell用户组。

所以linker覆盖完成后需要执行”chgrp shell /system/bin/linker”命令设置linker的用户组。

    __init_AT_SECURE函数的被调路径:__linker_init -> __linker_init_post_relocation -> linker_env_init -> __init_AT_SECURE

解决办法二

在qemu源码目录下找到”linux-user/elfload.c”文件,文件中有create_elf_tables函数,在该函数中找到这一行代码:

在这行代码下添加一行代码:

在该文件中找到这一行:

将这一行改为:

解决办法思路说明:

[翻译] getauxval() and the auxiliary vector这篇文章中说了,fs/binfmt_elf.c文件中有内核的ELF二进制加载器源码,在该文件中也有一个create_elf_tables函数,fs/binfmt_elf.c文件create_elf_tables函数有下面一行代码:

即在标准的create_elf_tables函数中会添加AT_SECURE这一项。通过阅读“解决办法一”可以推断出,产生”FATAL: kernel did not supply AT_SECURE”错误是因为找不到AT_SECURE这一项,那么“解决办法二”的思路就是在qemu的create_elf_tables函数中添加这一项。

为什么在qemu的create_elf_tables函数中添加的AT_SECURE项对应的值是0呢?这是因为我图方便,标准代码中AT_SECURE项对应的值是函数security_bprm_secureexec(bprm)的返回值,我发现理解security_bprm_secureexec函数比较麻烦。那么为什么是0而不是其他常量值?这是因为在linux系统的终端上输入下面的命令:

    LD_SHOW_AUXV=1 ps

最后显示AT_SECURE对应的值是0。上面命令中的”ps”可以是其他命令,如:ls。关于LD_SHOW_AUXV这个环境变量在《[翻译] getauxval() and the auxiliary vector》一文中有介绍。

    - loader_exec -> linux-user/elfload.c - load_elf_binary -> linux-user/elfload.c - create_elf_tables

作者:寻禹@阿里聚安全,更多安全技术、资讯文章,请访问阿里聚安全博客

在Android上使用qemu-user运行可执行文件的更多相关文章

  1. 编译可在Android上运行的qemu user mode

    前言 本文在Ubuntu 64位系统上对qemu项目进行交叉编译,并且只编译与qemu user mode有关的代码. 下文中的”NDK”若无特殊说明均指”Android NDK”. 下文中”$NDK ...

  2. 系列篇|编译可在Android上运行的依赖库(一):glib库

    前言 这是系列文章,它们由<编译可在Android上运行的glib库>及其他4篇文章组成,这4篇文章在“编译依赖库”一节中列出.由于glib库依赖于其他第三方库,所以需要先将依赖的第三方库 ...

  3. Android 上实现非root的 Traceroute -- 非Root权限下移植可运行二进制文件 脚本文件

    作者 : 万境绝尘 转载请著名出处 : http://blog.csdn.net/shulianghan/article/details/36438365 演示样例代码下载 : -- CSDN : h ...

  4. react native-调用react-native-fs插件时,如果数据的接口是需要验证信息的,在android上运行报错

    调用react-native-fs插件时,如果数据的接口是需要验证信息的,在android上运行报错,而在iOS上运行没问题.原因是因为接口是有验证信息的,而调用这个插件时没有传入,在iOS上会自动加 ...

  5. 在Android上运行Java和C程序

    在linux上运行java程序,直接用javac编译,再用java启动虚拟机运行就行了.但是在Android上,由于虚拟机和pc端的不同,所以操作方法也是不一样的.下面介绍Android上运行Hell ...

  6. 准备开发一个运行在Android上的JavaME模拟器

    在一个虚拟机A上运行另外一个虚拟机B看起来是挺不靠谱的一件事,在手机上运行某个虚拟机也不怎么靠谱.并且如果虚拟机A运行在手机上这个听起来就更不靠谱了.但是很多人就在做这样的事.比如在在手机上运行DOS ...

  7. 在 android 上运行 python 的方法

    在android上运行python脚本,或者在android上使用python交互界面,对熟悉python的研究或开发人员来说,是一件很有吸引力的事情,因为python脚本真是非常高效,另外,有很多非 ...

  8. Unity3D之AssetBundle学习:Android上运行笔记

    路径统一 在Android上加载StreamingAssets文件夹下的AssetBundle文件,首先需要对加载地址进行处理,注意PC.Android和IOS的地址不一致需要针对不同的平台不同的处理 ...

  9. FFmpeg在Android上的移植之第一步

    http://blog.sina.com.cn/s/blog_69a04cf40100x1fr.html 从事多媒体软件开发的人几乎没有不知道FFmpeg的,很多视频播放器都是基于FFmpeg开发的. ...

随机推荐

  1. 从匿名方法到 Lambda 表达式的推演过程

    Lambda 表达式是一种可用于创建委托或表达式目录树类型的匿名函数. 通过使用 lambda 表达式,可以写入可作为参数传递或作为函数调用值返回的本地函数. 以上是msdn官网对Lambda 表达式 ...

  2. VS 2013编译64位版本QT 4.8.6及使用cmake为依赖QT生成VS项目时Could NOT find Qt4

    对于一些已经解决的问题,本博客不再讨论.只将本人遇到的问题做简单的说明. 一.VS 2013编译64位版本QT 4.8.6 QT项目官网中,对于QT4,其只提供了windows X86的版本,并且支持 ...

  3. Git版本控制管理学习笔记4-文件管理和索引

        可以认为使用Git时,我们会遇到3个空间:工作目录.索引.版本库.我们关心的,就是在新建.修改等操作时,这三者之间发生了怎样的变化.     笼统的讲,就是在工作目录下编辑,在索引中积累修改, ...

  4. struts 2 时间控件

    在使用struts2框架时,为我们提供了时间选择器控件:datetimepicker.但是在使用过程中会出现一些问题,主要就是struts2版本更新时做了一些修改.在struts2.0时,使用< ...

  5. CI中的数据库操作

    转载于:http://blog.sina.com.cn/s/blog_76e7bdba01016p2p.html CI中第一次连接数据库,在控制器或模型的构造函数里输入以下语句 $this->l ...

  6. 前端试题本(Javascript篇)

    JS1. 下面这个JS程序的输出是什么:JS2.下面的JS程序输出是什么:JS3.页面有一个按钮button id为 button1,通过原生的js如何禁用?JS4.页面有一个按钮button id为 ...

  7. 两个select 左右添加,上下移动

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  8. Java 之 异常处理

    1.异常: a.问题(Throwable):异常(Exception).错误(Error)   异常(Exception):运行时异常(RuntimeException).编译时异常(Unhandle ...

  9. linux 查看端口号

    在使用Linux系统的过程中,有时候会遇到端口被占用而导致服务无法启动的情况.比如HTTP使用80端口,但当启动Apache时,却发现此端口正在使用. 这种情况大多数是由于软件冲突.或者默认端口设置不 ...

  10. IMap 对map的功能的强化

    为了解决表单提交获得数据的方便性,我们将map的功能进行加强,表单提交的数据会自动将页面数据放入PageData对象中,当从页面获取数据时 new的时候要传request.request.getPar ...