Android tcpdump抓包应用实现

Android应用很多时候都会涉及到网络,在请求网络出错时,我们可以通过抓包来分析网络请求,返回的数据等,通常我们是用tcpdump这个工具来抓包,再通过wireshark工具来分析生成的文件,关于tcpdump的使,可以从网上查一下,有很多介绍,比如:http://www.cnblogs.com/likwo/archive/2012/09/06/2673944.html。关于如何用wireshark来分析文件,本文不作介绍。

使用adb的命令来操作,还是比较麻烦,所以我写了一个应用,把这些命令封装了起来。实现的最根本的原理是通过Runtime.exec来执行linux命令。

运行截图

实现代码

CommandsHelper.java
/**
 * 
 * @author lihong06
 * @since 2014-3-3
 */
public class CommandsHelper {
    private static final String NAME = "tcpdump";
    private static final String TAG = "CommandsHelper";
    public static final String DEST_FILE = Environment.getExternalStorageDirectory() + "/capture.pcap";
    
    public static boolean startCapture(Context context) {
        InputStream is = null;
        OutputStream os = null;
        boolean retVal = false;
        try {
            AssetManager am = context.getAssets();
            is = am.open(NAME);
            File sdcardFile = Environment.getExternalStorageDirectory();
            File dstFile = new File(sdcardFile, NAME);
            os = new FileOutputStream(dstFile);
            
            copyStream(is, os);
            
            String[] commands = new String[7];
            commands[0] = "adb shell";
            commands[1] = "su";
            commands[2] = "cp -rf " + dstFile.toString() + " /data/local/tcpdump";
            commands[3] = "rm -r " + dstFile.toString();
            commands[4] = "chmod 777 /data/local/tcpdump";
            commands[5] = "cd /data/local";
            commands[6] = "tcpdump -p -vv -s 0 -w " + DEST_FILE;
            
            execCmd(commands);
        } catch (IOException e) {
            e.printStackTrace();
            Log.i(TAG, "    error: " + e.getMessage());
        } finally {
            closeSafely(is);
            closeSafely(os);
        }
        
        return retVal;
    }
    
    public static void stopCapture(Context context) {
        // 找出所有的带有tcpdump的进程
        String[] commands = new String[2];
        commands[0] = "adb shell";
        commands[1] = "ps|grep tcpdump|grep root|awk ‘{print $2}‘";
        Process process = execCmd(commands);
        String result = parseInputStream(process.getInputStream());
        if (!TextUtils.isEmpty(result)) {
            String[] pids = result.split("\n");
            if (null != pids) {
                String[] killCmds = new String[pids.length];
                for (int i = 0; i < pids.length; ++i) {
                    killCmds[i] = "kill -9 " + pids[i];
                }
                execCmd(killCmds);
            }
        }
    }
    
    public static Process execCmd(String command) {
        return execCmd(new String[] { command }, true);
    }
    
    public static Process execCmd(String[] commands) {
        return execCmd(commands, true);
    }
    
    public static Process execCmd(String[] commands, boolean waitFor) {
        Process suProcess = null;
        try {
            suProcess = Runtime.getRuntime().exec("su");
            DataOutputStream os = new DataOutputStream(suProcess.getOutputStream());
            for (String cmd : commands) {
                if (!TextUtils.isEmpty(cmd)) {
                    os.writeBytes(cmd + "\n");
                }
            }
            os.flush();
            os.writeBytes("exit\n");
            os.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }

        if (waitFor) {
            boolean retval = false;
            try {
                int suProcessRetval = suProcess.waitFor();
                if (255 != suProcessRetval) {
                    retval = true;
                } else {
                    retval = false;
                }
            } catch (Exception ex) {
                Log.w("Error ejecutando el comando Root", ex);
            }
        }
        
        return suProcess;
    }
    
    private static void copyStream(InputStream is, OutputStream os) {
        final int BUFFER_SIZE = 1024;
        try {
            byte[] bytes = new byte[BUFFER_SIZE];
            for (;;) {
                int count = is.read(bytes, 0, BUFFER_SIZE);
                if (count == -1) {
                    break;
                }

                os.write(bytes, 0, count);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    private static void closeSafely(Closeable is) {
        try {
            if (null != is) {
                is.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    private static String parseInputStream(InputStream is) {
        InputStreamReader isr = new InputStreamReader(is);
        BufferedReader br = new BufferedReader(isr);
        String line = null;
        StringBuilder sb = new StringBuilder();
        try {
            while ( (line = br.readLine()) != null) {
                sb.append(line).append("\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        return sb.toString();
    }
}

MainActivity.java
public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        final TextView textView = (TextView) findViewById(R.id.textView1);
        String oldText = textView.getText().toString();
        textView.setText(oldText + "\n\n" + "目标文件: " + CommandsHelper.DEST_FILE);
        
        findViewById(R.id.start_capture).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                v.setEnabled(false);
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        final boolean retVal = CommandsHelper.startCapture(MainActivity.this);
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Toast.makeText(MainActivity.this, "startCapture result = " + retVal, Toast.LENGTH_SHORT).show();
                            }
                        });
                    }
                }).start();
            }
        });
        
        findViewById(R.id.stop_capture).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                CommandsHelper.stopCapture(MainActivity.this);
                findViewById(R.id.start_capture).setEnabled(true);
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
}

说明

1、手机必须要Root,没有root的我没有测试过,另外,我也只测试了我一台手机,没有覆盖到所有的手机。
2、大家如果发现问题,请告知于我,谢谢。




Android tcpdump抓包应用实现,,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。