【Android 应用开发】Android 上实现非root的 Traceroute -- 非Root权限下移植可执行二进制文件 脚本文件
作者 : 万境绝尘
转载请著名出处 : http://blog.csdn.net/shulianghan/article/details/36438365
示例代码下载 :
-- CSDN : http://download.csdn.net/detail/han1202012/7639253;
-- GitHub : https://github.com/han1202012/TracerouteAndBusybox ;
1. 原理思路
文件权限修改无法实现 : 如果 没有 root 权限, 就不能改变二进制文件的文件权限;
-- 将busybox推送到Android系统中 : 使用 adb push 命令, 将 busybox 传入到 sd 卡中, 注意, 上传到内存中无法实现;
-- 上传到sd卡成功 : 使用 adb push 文件名 手机中的文件全路径名 命令;
octopus@octopus:~/csdn$ adb push busybox-armv7l /sdcard/octopus/busybox 3256 KB/s (1109128 bytes in 0.332s)
-- 上传到内存失败 : 使用 adb push 上传到内存中失败, 因为 adb 使用的是 system 用户, 只有 root 用户才有权限向内存中写入数据;
octopus@octopus:~/csdn$ adb push busybox-armv7l /data/busybox failed to copy 'busybox-armv7l' to '/data/busybox': Permission denied
-- 查看并修改busybox权限失败 : system 用户没有修改 sd 卡文件模式的权限;
shell@android:/sdcard/octopus $ ll -rw-rw-r-- root sdcard_rw 1109128 2014-07-08 19:49 busybox shell@android:/sdcard/octopus $ chmod 755 busybox Unable to chmod busybox: Operation not permitted
应用程序解决方案 :
-- 应用程序专属用户 : Android 操作系统会为每个应用程序设置一个用户, 这个用户对其安装目录(/data/data/包名/)下的文件有完整的权限;
-- 将可执行二进制文件拷贝到安装目录中 : 将交叉编译好的 busybox 放到 工程目录下的 res/assets/ 目录下;
2. 实现策略
文件初始放置 : 将 交叉编译好的 busybox 文件放在 工程目录的 /res/assets/ 目录下;
文件拷贝 : 将该 二进制文件 拷贝到 app 的安装目录的 files 目录下, 即 /data/data/包名/files/下;
修改文件权限 : 使用命令可以直接修改该目录下的权限, 注意这个操作是可以执行的;
执行busybox : 在代码中执行 ./data/data/包名/files/busybox ;
获取执行结果 :
3. 使用到的api解析
(1) 获取 assets 目录文件的输入流
InputStream is = context.getAssets().open(source);
-- 获取AssetsManager : 调用 Context 上下文对象的 context.getAssets() 即可获取 AssetsManager对象;
-- 获取输入流 : 调用 AssetsManager 的 open(String fileName) 即可获取对应文件名的输入流;
(2) 文件流相关操作
根据输入流获取文件大小 : 调用输入流的 inputStream.available() 方法;
int size = is.available();
将文件读取到缓冲区中 : 创建一个与文件大小相同的字节数组缓冲区, 输入流将数据存放到缓冲区中;
byte[] buffer = new byte[size]; is.read(buffer); is.close();
将文件写到内存中 : 调用上下文对象的 openFileOutput(绝对路径名, 权限), 即可创建一个文件的输出流;
FileOutputStream output = context.openFileOutput(destination, Context.MODE_PRIVATE); output.write(buffer); output.close();
(3) 获取文件的绝对路径
获取app绝对安装路径 : 调用 上下文对象的 getFilesDir().getAbsolutePath() 方法;
String filesPath = context.getFilesDir().getAbsolutePath();
(4) 执行二进制文件
创建 Process 对象, 并使用该 process 执行shell脚本命令 :
Runtime runtime = Runtime.getRuntime(); process = runtime.exec(cmd);
获取执行的命令行结果 :
            InputStream is = process.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            String line = null;
            while ((line = br.readLine()) != null) {
                processList.add(line);
            }
            br.close(); 
4. 代码示例
MainActivity 主程序代码 :
package cn.org.octopus.tracerouteandbusybox;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
/** 看不懂注释我就吃半斤狗粮 :-) */
public class MainActivity extends ActionBarActivity {
	private EditText et_cmd;
	private String app_path;
	private TextView tv_result;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.home_activity);
		/*初始化控件*/
		et_cmd = (EditText) findViewById(R.id.et_cmd);
		tv_result = (TextView) findViewById(R.id.tv_result);
		/* 获取app安装路径 */
		app_path = getApplicationContext().getFilesDir().getAbsolutePath();
	}
	/** 按钮点击事件 */
	public void onClick(View view) {
		int id = view.getId();
		switch (id) {
		case R.id.copy_busybox: /* 拷贝busybox可执行文件 */
			varifyFile(getApplicationContext(), "busybox");
			break;
		case R.id.copy_traceroute:/* 拷贝traceroute可执行文件 */
			varifyFile(getApplicationContext(), "traceroute");
			break;
		case R.id.exe_busybox:/* 将busybox命令添加到Editext中 */
			String cmd = "." + app_path + "/busybox";
			System.out.println(et_cmd);
			et_cmd.setText(cmd);
			break;
		case R.id.exe_traceroute:/* 将traceroute命令添加到Editext中 */
			cmd = "." + app_path + "/traceroute 8.8.8.8";
			et_cmd.setText(cmd);
			break;
		case R.id.exe: /* 执行Editext中的命令 */
			cmd = et_cmd.getText().toString();
			/* 执行脚本命令 */
			List<String> results = exe(cmd);
			String result = "";
			/* 将结果转换成字符串, 输出到 TextView中 */
			for(String line : results){
				result += line + "\n";
			}
			tv_result.setText(result);
			break;
		default:
			break;
		}
	}
	/** 验证文件是否存在, 如果不存在就拷贝 */
	private void varifyFile(Context context, String fileName) {
        try {
        	/* 查看文件是否存在, 如果不存在就会走异常中的代码 */
        	context.openFileInput(fileName);
        } catch (FileNotFoundException notfoundE) {
            try {
            	/* 拷贝文件到app安装目录的files目录下 */
                copyFromAssets(context, fileName, fileName);
                /* 修改文件权限脚本 */
                String script = "chmod 700 " + app_path + "/" + fileName;
                /* 执行脚本 */
                exe(script);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
	/** 将文件从assets目录中拷贝到app安装目录的files目录下 */
	private void copyFromAssets(Context context, String source,
			String destination) throws IOException {
		/* 获取assets目录下文件的输入流 */
		InputStream is = context.getAssets().open(source);
		/* 获取文件大小 */
		int size = is.available();
		/* 创建文件的缓冲区 */
		byte[] buffer = new byte[size];
		/* 将文件读取到缓冲区中 */
		is.read(buffer);
		/* 关闭输入流 */
		is.close();
		/* 打开app安装目录文件的输出流 */
		FileOutputStream output = context.openFileOutput(destination,
				Context.MODE_PRIVATE);
		/* 将文件从缓冲区中写出到内存中 */
		output.write(buffer);
		/* 关闭输出流 */
		output.close();
	}
	/** 执行 shell 脚本命令 */
	private List<String> exe(String cmd) {
		/* 获取执行工具 */
		Process process = null;
		/* 存放脚本执行结果 */
        List<String> list = new ArrayList<String>();
        try {
        	/* 获取运行时环境 */
        	Runtime runtime = Runtime.getRuntime();
        	/* 执行脚本 */
            process = runtime.exec(cmd);
            /* 获取脚本结果的输入流 */
            InputStream is = process.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            String line = null;
            /* 逐行读取脚本执行结果 */
            while ((line = br.readLine()) != null) {
                list.add(line);
            }
            br.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return list;
	}
}
home_activity.xml 布局文件代码 :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="horizontal" >
        <Button
            android:id="@+id/copy_busybox"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onClick"
            android:text="拷贝busybox"
            android:textSize="7dp"
            android:textStyle="bold" />
        <Button
            android:id="@+id/copy_traceroute"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onClick"
            android:text="拷贝traceroute"
            android:textSize="7dp"
            android:textStyle="bold" />
        <Button
            android:id="@+id/exe_busybox"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onClick"
            android:text="执行busybox"
            android:textSize="7dp"
            android:textStyle="bold" />
        <Button
            android:id="@+id/exe_traceroute"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onClick"
            android:text="执行traceroute"
            android:textSize="7dp"
            android:textStyle="bold" />
    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >
        <EditText
            android:id="@+id/et_cmd"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="4"
            android:hint="输入要执行的命令"
            android:textStyle="bold" />
        <Button
            android:id="@+id/exe"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="onClick"
            android:text="执行"
            android:textSize="10dp"
            android:textStyle="bold" />
    </LinearLayout>
    <TextView
        android:id="@+id/tv_result"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#000000"
        android:textColor="#FFF"
        android:textSize="10dp"
        android:textStyle="bold" />
</LinearLayout>
5. 执行结果
执行 busybox 程序 :
执行 traceroute 程序 :
示例代码下载 :
-- CSDN : http://download.csdn.net/detail/han1202012/7639253;
-- GitHub : https://github.com/han1202012/TracerouteAndBusybox ;
作者 : 万境绝尘
转载请著名出处 : http://blog.csdn.net/shulianghan/article/details/36438365
【Android 应用开发】Android 上实现非root的 Traceroute -- 非Root权限下移植可执行二进制文件 脚本文件的更多相关文章
- Android 上实现非root的 Traceroute -- 非Root权限下移植可执行二进制文件 脚本文件
		
作者 : 万境绝尘 转载请著名出处 : http://blog.csdn.net/shulianghan/article/details/36438365 示例代码下载 : -- CSDN : htt ...
 - Android 上实现非root的 Traceroute -- 非Root权限下移植可运行二进制文件 脚本文件
		
作者 : 万境绝尘 转载请著名出处 : http://blog.csdn.net/shulianghan/article/details/36438365 演示样例代码下载 : -- CSDN : h ...
 - 用Android Studio 开发Android应用
		
目前AndroidStudio已经到了1.2版本了,我用了下,觉得还蛮好的,有些自动生成的资源,它会自动帮你管理.下面开始列一下,我的开发环境搭配.在开始前,你得有个VPN,可者代理.嗯.不然你下不了 ...
 - android studio 开发android app 真机调试
		
大家都知道开发android app 的时候可以有2种调试方式, 一种是Android Virtual Device(虚拟模拟器) ,另一种就是真机调试. 这里要说的是真机调试的一些安装步骤: 1. ...
 - 码农人生——从未学过Android如何开发Android App 案例讲解-第002期案例
		
标题有点晃眼,本次分享是002期博文的实践故事,不会有任何代码.也不会教别人android 如何开发,类似博文已经有大批大批,而且还会有陆陆续续的人写,我写的文章,主要是经验之谈,希望总结出的一些方法 ...
 - Android BLE开发——Android手机与BLE终端通信初识
		
蓝牙BLE官方Demo下载地址: http://download.csdn.net/detail/lqw770737185/8116019参考博客地址: http://www.eoeandr ...
 - Android多媒体开发-- android中OpenMax的实现整体框架
		
1.android中用openmax来干啥? android中的AwesomePlayer就 是用openmax来做(code)编解码,其实在openmax接口设计中,他不光能用来当编解码.通过他的组 ...
 - [Hybrid App]--Android混合开发,Android、Js的交互
		
AndroidJs通信 *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !imp ...
 - Android Studio开发Android应用如何签名
		
1.使用jdk自带的工具生成keystore 使用cmd命令行进入到jdk的bin目录(比如:C:\Program Files\Java\jdk1.7.0_01\bin) 运行如下命令: C:\Pro ...
 
随机推荐
- Vim8.0在Debian下,normal模式的O命令出现延时
			
Update 2018/4/26 问题是什么 在Debian的Vim8.0中,normal模式下,使用O创建新行,常常出现延迟情况:按下O后,可以看见O首先在当前光标位置出现,过了大约0.5-1秒,接 ...
 - IOI2016Day2. Messy
			
题目链接:http://uoj.ac/problem/239 题目大意: 这是一道交互题,交互库维护了一个数据结构,可以存储n为二进制串,一开始你可以向空的数据结构中插入若干二进制串, 接下来这个数据 ...
 - Luogu P3740 [HAOI2014]贴海报_线段树
			
线段树版的海报 实际上这个与普通的线段树相差不大,只是貌似数据太水,暴力都可以过啊 本来以为要离散的,结果没打就A了 #include<iostream> #include<cstd ...
 - centos gnome面板菜单任务栏消失后的解决
			
今天终于下决心把我的电脑装成了centos,上网的时候感觉上边的那一行菜单栏碍事儿,就把他给删了 就是桌面最顶上这一行东西,然后百度无果,谷歌上不去,用bing好不容易才找到里解决方案! 症状:进入l ...
 - python环境搭建(python2和python3共存)
			
安装两个版本的意义 验证自己代码对版本的兼容性 网上下载的某些源码只能在python2或者python3中运行 安装过程记录 1.去python官网下载python的安装包, 下载完成后如下图所示 2 ...
 - MySQL系列教程(四)
			
文件打开数(open_files) 我们现在处理MySQL故障时,发现当Open_files大于open_files_limit值时,MySQL数据库就会发生卡住的现象,导致Nginx服务器打不开相应 ...
 - Docker简介/安装/使用
			
什么是Docker?docker是一个开源的应用容器引擎,系统级的轻量虚拟化技术.应用程序的自动化部署解决方案,能够迅速创建一个容器,并在容器上部署和运行应用程序,并通过配置文件可以轻松实现应用程序的 ...
 - dubbo安装
			
dubbo 管控台可以对注册到 zookeeper 注册中心的服务或服务消费者进行管理,分享牛系列,分享牛专栏,分享牛.但管控台是否正常对 Dubbo 服务没有影响,管控台也不需要高可用,因此可以单节 ...
 - Android基础知识点-Manifest清单文件
			
每个应用的根目录中都必须包含一个 AndroidManifest.xml 文件(且文件名精确无误). 清单文件向 Android 系统提供应用的必要信息,系统必须具有这些信息方可运行应用的任何代码. ...
 - Linux 高性能服务器编程——Linux网络编程基础API
			
问题聚焦: 这节介绍的不仅是网络编程的几个API 更重要的是,探讨了Linux网络编程基础API与内核中TCP/IP协议族之间的关系. 这节主要介绍三个方面的内容:套接字(so ...