作者 : 万境绝尘

转载请著名出处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 放到 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; @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(); } /** 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

Android 上实现非root的 Traceroute -- 非Root权限下移植可运行二进制文件 脚本文件的更多相关文章

  1. 【Android 应用开发】Android 上实现非root的 Traceroute -- 非Root权限下移植可执行二进制文件 脚本文件

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

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

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

  3. Ubuntu 14.04 在桌面上双击运行shell 脚本文件

    http://askubuntu.com/questions/465531/how-to-make-a-shell-file-execute-by-double-click up vote7down ...

  4. 如何正确的在 Android 上使用协程 ?

    前言 你还记得是哪一年的 Google IO 正式宣布 Kotlin 成为 Android 一级开发语言吗?是 Google IO 2017 .如今两年时间过去了,站在一名 Android 开发者的角 ...

  5. 【Android】使用persist属性来调用脚本文件

    Android系统中有许多属性,属性由两个部分组成:name & value,可以使用这些属性来记录系统设置或进程之间的信息交换.Android系统在启动过程时会按序从以下几个文件中加载系统属 ...

  6. 以非root权限安装nginx及运行

    本章主要讲如何在无root权限(包含无sudo权限)条件下于centos命令行中安装nginx以及在大于1024的端口(这里用8080)上运行. 1. 安装 两种方式,一是下载预编译好的rpm包安装, ...

  7. Android Studio怎样import module(针对非gradle)

    相同的,非gradle编译的project和gradle编译的在import module上相同有一些差别. 包含操作上,显示上的一些差别,曾经的文章中,仅仅要没有标注"非gradle&qu ...

  8. linux下非root用户怎样改动root权限的文件

           在linux下会出现把一些配置文件參数配错.rootpassword忘记等导致系统无法启动或进入root的窘迫境界.本文以redhat  enterprise linux server ...

  9. Asp.Net实现无刷新文件上传并显示进度条(非服务器控件实现)(转)

    Asp.Net实现无刷新文件上传并显示进度条(非服务器控件实现) 相信通过Asp.Net的服务器控件上传文件在简单不过了,通过AjaxToolkit控件实现上传进度也不是什么难事,为什么还要自己辛辛苦 ...

随机推荐

  1. BestR #31

    hdu 5178 求|a[i] - a[j]| <= k (i < j) <i,j>的对数,一开始认为数据不大就直接ans++了,后来结果出来才知道,啊啊啊,too young ...

  2. 轻应用 lapp

    轻应用 LAPP (Light App) 即轻应用是一种无需下载.即搜即用的全功能 App,既有媲美甚至超越native app的用户体验,又具备webapp的可被检索与智能分发的特性,将有效解决优质 ...

  3. 3D空间中射线与三角形的交叉检測算法

    引言 射线Ray,在3D图形学中有非常多重要的应用.比方,pick操作就是使用射线Ray来实现的,还有诸如子弹射线的碰撞检測等等都能够使用射线Ray来完毕. 所以,在本次博客中,将会简单的像大家介绍下 ...

  4. Java_io体系之BufferedWriter、BufferedReader简介、走进源码及示例——16

    Java_io体系之BufferedWriter.BufferedReader简介.走进源码及示例——16 一:BufferedWriter 1.类功能简介: BufferedWriter.缓存字符输 ...

  5. TPL异步并行编程之回调

    Task是基于ThreadPool线程池基础上的高度异步多线程编程,如果有一天我希望一个需要长时间运行的Task,在被某些异常终止后还能回调一些代码就可以知道Task终止的原因了吧 是的,且看代码 p ...

  6. 积累的VC编程小技巧之属性页

    1.属性页的添加: 创建对话框的类,该类要从CpropertyPage继承:然后在要添加该对话框为属性页的类(头文件)里创建CpropertySheet类的一个对象m_tabsheet和新创建的对话框 ...

  7. .NET Core 1.0.0 RC2

    .NET Core 1.0.0 RC2 在.NET Core 1.0.0 RC2即将正式发布之际,我也应应景,针对RC2 Preview版本编写一个史上最简单的MVC应用.由于VS 2015目前尚不支 ...

  8. 爬虫总结_python

    import sqlite3 Python 的一个非常大的优点是很容易写很容易跑起来,缺点就是很多不那么著名的(甚至一些著名的)程序和库都不像 C 和 C++ 那边那样专业.可靠(当然这也有动态类型 ...

  9. EndNote是一款着名的参考文献管理软件

    EndNote是一款着名的参考文献管理软件,我们可以通过该软件创建个人参考文献库,此外对公司DCC.法务和专 利部门十分的有用,甚至对我们写SOP 也有些帮忙,并且该软件可以在其中加入文本.图像.表格 ...

  10. wikioi 1014 装箱问题

    来源:http://wikioi.com/problem/1014/ 1014 装箱问题 29人推荐 收藏 发题解 提交代码 报错 题目描写叙述 输入描写叙述 输出描写叙述 例子输入 例子输出 提示 ...