• 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 放到 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 + "
    ";
    			}
    			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



  • 相关阅读:
    一段滚动文字的js (jQuery)
    VB ASP 使用 now() 时默认格式调整方法
    解决标题过长的CSS
    javascript Spline代码
    统计学中的几个重要的分布
    网页游戏开发秘笈 PDF扫描版
    网页设计与开发——HTML、CSS、JavaScript (王津涛) pdf扫描版
    网页设计与开发:HTML、CSS、JavaScript实例教程 (郑娅峰) pdf扫描版
    网页DIV+CSS布局和动画美化全程实例 (陈益材) 随书光盘
    实用掌中宝--HTML&CSS常用标签速查手册 PDF扫描版
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/4356116.html
Copyright © 2020-2023  润新知