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 上实现非root的 Traceroute -- 非Root权限下移植可执行二进制文件 脚本文件的更多相关文章
- 【Android 应用开发】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 上使用协程 ?
前言 你还记得是哪一年的 Google IO 正式宣布 Kotlin 成为 Android 一级开发语言吗?是 Google IO 2017 .如今两年时间过去了,站在一名 Android 开发者的角 ...
- 【Android】使用persist属性来调用脚本文件
Android系统中有许多属性,属性由两个部分组成:name & value,可以使用这些属性来记录系统设置或进程之间的信息交换.Android系统在启动过程时会按序从以下几个文件中加载系统属 ...
- 执行sh脚本文件下载Github上的代码(雷霄骅的ffmpeg示例代码)
今天想重新学习下ffmpeg,于是又来到了雷晓骅的博客,先下载了他的所有代码,这里记录一下在Windows上使用sh脚本下载GitHub上代码的过程. CygWin(最后并没有用到) 可以 ...
- Android程序执行shell脚本
在做Android应用时,经常需要执行shell脚本,以快速实现某些功能: 在Android应用程序中执行shell脚本可以省去一大堆繁琐的代码,还可以避免不必要的错误: 比如:拷贝文件夹时,可以执行 ...
- Android Studio怎样import module(针对非gradle)
相同的,非gradle编译的project和gradle编译的在import module上相同有一些差别. 包含操作上,显示上的一些差别,曾经的文章中,仅仅要没有标注"非gradle&qu ...
- linux下非root用户怎样改动root权限的文件
在linux下会出现把一些配置文件參数配错.rootpassword忘记等导致系统无法启动或进入root的窘迫境界.本文以redhat enterprise linux server ...
- Asp.Net实现无刷新文件上传并显示进度条(非服务器控件实现)(转)
Asp.Net实现无刷新文件上传并显示进度条(非服务器控件实现) 相信通过Asp.Net的服务器控件上传文件在简单不过了,通过AjaxToolkit控件实现上传进度也不是什么难事,为什么还要自己辛辛苦 ...
随机推荐
- h5跳转到app的实现
随着业务的增加,可能存在这么一种需求,就是需要从h5中直接跳转到app.如果没有安装app的话,则提示到应用市场或者app store下载安装.不过问题就在这个地方,单纯的用h5是没有方法判断是否安装 ...
- WIN10下WNMP开发环境部署
刚刚开始学习PHP时,一直使用phpstudy,后面发现很多东西自己单独配置安装会理解更深刻,所以自己总结了一下windows下开发环境的部署教程. 以前经常在CSDN和博客园看别人的教程,今天才注册 ...
- mysql 多主多从配置,自增id解决方案
MySQL两主(多主)多从架构配置 一.角色划分 1.MySQL数据库规划 我现在的环境是:zhdy04和zhdy05已经做好了主主架构配置,现在需要的是把两台或者多台从服务器与主一一同步. 主机名 ...
- php源码建博客5--建库建表-配置文件-错误日志
主要: 整理框架 建库建表 配置文件类 错误日志记录 --------------本篇后文件结构:-------------------------------------- blog ├─App │ ...
- 学习新框架laravel4 第三天
请求与输入 获取请求参数 如果没有传递默认值位1 $id= Input::get('id',1); //获取所有请求内容 Input::all() 取得请求 URI $uri = Request::p ...
- 树莓派如何连接WIFI
hello,大家好,我是叶秋! 上一期呢,给大家介绍了如何给树莓派安装系统,有细心的朋友就会发现上一期安装系统的文章漏了一点点知识,不知道机智的你是否有发现呢~~(尴尬
- 使用ansible安装lnmp
主机互信 生成密钥对,并将公钥发送给其他需要操作的主机 ssh-keygen -t rsa cd /root/.ssh ssh-copy-id -i id_rsa.pub root@192.168.1 ...
- java 异常与捕获
几乎所有的代码里面都会出现异常,为了保证程序在出现异常之后可以正常执行完毕,就需要进行异常处理. 先来看一下异常的继承类结构: 所有的异常都是由Throwable继承而来,我们来看他下面的两个子类Er ...
- C#中如何使用JS脚本
C#中如何使用JS脚本 目前在做的组态软件中就使用到了js脚本,这部分js脚本是供用户编写的,用户可以通过我们提供的脚本以及js自身的逻辑,用户就可以随心所欲的控制设备的运行.有比较了几款在C#中执行 ...
- axios请求封装和异常统一处理
前端网络请求封装前端采用了axios来处理网络请求,为了避免在每次请求时都去判断各种各样的网络情况,比如连接超时.服务器内部错误.权限不足等等不一而足,我对axios进行了简单的封装,这里主要使用了a ...