Android 上實現非root的 Traceroute -- 非Root許可權下移植可執行二進位檔案 指令檔

來源:互聯網
上載者:User

標籤:android   busybox   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 檔案名稱 手機中的檔案全路徑名 命令;

[email protected]:~/csdn$ adb push busybox-armv7l /sdcard/octopus/busybox3256 KB/s (1109128 bytes in 0.332s)
-- 上傳到記憶體失敗 : 使用 adb push 上傳到記憶體中失敗, 因為 adb 使用的是 system 使用者, 只有 root 使用者才有許可權向記憶體中寫入資料;

[email protected]:~/csdn$ adb push busybox-armv7l /data/busyboxfailed to copy ‘busybox-armv7l‘ to ‘/data/busybox‘: Permission denied
-- 查看並修改busybox許可權失敗 : system 使用者沒有修改 sd 卡檔案模式的許可權;

[email protected]:/sdcard/octopus $ ll -rw-rw-r-- root     sdcard_rw  1109128 2014-07-08 19:49 busybox[email protected]:/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;@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();}/** 按鈕點擊事件 */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



聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.