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/busybox3256 KB/s (1109128 bytes in 0.332s)-- 上传到内存失败 : 使用 adb push 上传到内存中失败, 由于 adb 使用的是 system 用户, 仅仅有 root 用户才有权限向内存中写入数据;
octopus@octopus:~/csdn$ adb push busybox-armv7l /data/busyboxfailed 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 busyboxshell@android:/sdcard/octopus $ chmod 755 busybox Unable to chmod busybox: Operation not permitted
应用程序解决方式 :
-- 应用程序专属用户 : Android 操作系统会为每一个应用程序设置一个用户, 这个用户对其安装文件夹(/data/data/包名/)下的文件有完整的权限;
-- 将可运行二进制文件复制到安装文件夹中 : 将交叉编译好的 busybox 放到 project文件夹下的 res/assets/ 文件夹下;
2. 实现策略
文件初始放置 : 将 交叉编译好的 busybox 文件放在 project文件夹的 /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;@Overrideprotected 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();}/** button点击事件 */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
更多相关文章
- 一款常用的 Squid 日志分析工具
- GitHub 标星 8K+!一款开源替代 ls 的工具你值得拥有!
- RHEL 6 下 DHCP+TFTP+FTP+PXE+Kickstart 实现无人值守安装
- Linux 环境下实战 Rsync 备份工具及配置 rsync+inotify 实时同步
- Android下如何杀死后台进程
- Android(安卓)实现文件分享功能(共享多个文件)
- Android修改、设置锁屏密码
- 在Ubuntu16.04下编译FFmpeg4.2.3
- 移植Android(安卓)遇到的问题