Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 上實現非root的 Traceroute -- 非Root權限下移植可執行二進制文件 腳本文件

Android 上實現非root的 Traceroute -- 非Root權限下移植可執行二進制文件 腳本文件

編輯:關於Android編程

 

 

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 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 exe(String cmd) {
		/* 獲取執行工具 */
		Process process = null; 
		/* 存放腳本執行結果 */
        List list = new ArrayList();  
        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 布局文件代碼 :

 




    


 

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


 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved