致命异常:主要用于数据包嗅探应用程序

Posted

技术标签:

【中文标题】致命异常:主要用于数据包嗅探应用程序【英文标题】:Fatal Exception:main for packet sniffing application 【发布时间】:2012-08-17 01:19:49 【问题描述】:

我是 android 编程的初学者,我正在做我的期末项目,我需要开发一个数据包嗅探应用程序。我在互联网上找到了一些代码,并试图将其扩展到我的项目中。但得到 FATAL EXCEPTION: main 和 following 错误。

代码如下:

public class Main extends Activity 

    // Variable declarations for handling the view items in the layout.
    private Button start_button;
    private Button stop_button;
    private Button read_button;
    private EditText parameters;

    // Variable declarations for handling the TCPdump process.
    private TCPdump tcpdump = null;
    private TCPdumpHandler tcpDumpHandler = null;
    private SharedPreferences settings = null;

    // Variable declarations for handling the options and reader activities.
    private Intent optionsIntent = null;
    private Intent readerIntent = null;

    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // Associating the items in the view to the variables.
        start_button = (Button) findViewById(R.id.start_button);
        stop_button = (Button) findViewById(R.id.stop_button);
        read_button = (Button) findViewById(R.id.read_button);
        parameters = (EditText) findViewById(R.id.params_text);

        // Accessing the app's preferences.
        settings = getSharedPreferences(GlobalConstants.prefsName, 0);

        // Extracting the TCPdump binary to the app folder.
        if (RootTools.installBinary(Main.this, R.raw.tcpdump, "tcpdump") == false) 
            new AlertDialog.Builder(Main.this)
                    .setTitle(R.string.extraction_error)
                    .setMessage(R.string.extraction_error_msg)
                    .setNeutralButton(R.string.ok, null).show();
        

        // Creating a new TCPdump object.
        tcpdump = new TCPdump();

        // Creating a TCPdump handler for the TCPdump object created after.
        tcpDumpHandler = new TCPdumpHandler(tcpdump, this, this, true);

        // Obtaining the command from the options that were saved last time
        // Shark was running.
        tcpDumpHandler.generateCommand();

        start_button.setOnClickListener(new OnClickListener() 
            // Setting the action to perform when the start button is pressed.
            public void onClick(View v) 
                startTCPdump();
            
        );

        stop_button.setOnClickListener(new OnClickListener() 
            // Setting the action to perform when the stop button is pressed.
            public void onClick(View v) 
                stopTCPdump();
            
        );

        read_button.setOnClickListener(new OnClickListener() 
            // Setting the action to perform when the open in reader button is
            // pressed.
            public void onClick(View v) 
                launchReader();
            
        );

        BroadcastReceiver connectionReceiver = new BroadcastReceiver() 
            @Override
            public void onReceive(Context context, Intent intent) 
                // Setting the action to be performed when the network status
                // changes.
                if ((tcpDumpHandler.checkNetworkStatus() == false)
                        && (tcpdump.getProcessStatus())) 
                    stopTCPdump();
                    new AlertDialog.Builder(Main.this)
                            .setTitle(
                                    getString(R.string.network_connection_down))
                            .setMessage(
                                    getString(R.string.network_connection_down_msg))
                            .setNeutralButton(getString(R.string.ok), null)
                            .show();
                
            
        ;

        // Registering the BroadcastReceiver and associating it with the
        // connectivity change event.
        registerReceiver(connectionReceiver, new IntentFilter(
                "android.net.conn.CONNECTIVITY_CHANGE"));
    

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) 
        // Setting the action to perform when returning to this activity from
        // another activity which had been called.
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK && requestCode == 1) 
            if (tcpdump.getProcessStatus()) 
                new AlertDialog.Builder(Main.this)
                        .setTitle(getString(R.string.settings_changed))
                        .setMessage(getString(R.string.settings_changed_msg))
                        .setNeutralButton(getString(R.string.ok), null).show();
            
            tcpDumpHandler.generateCommand();
        
    

    @Override
    public void onDestroy() 
        // Setting the action to perform when the Android O.S. kills this
        // activity.
        if (tcpdump.getProcessStatus()) 
            stopTCPdump();
        
    

    public boolean onCreateOptionsMenu(Menu menu) 
        // This code makes the activity to show a menu when the device's menu
        // key is pressed.
        menu.add(0, 0, 0, getString(R.string.options_text));
        menu.add(0, 1, 0, getString(R.string.about_text));
        return true;
    

    public boolean onOptionsItemSelected(MenuItem item) 
        // Setting the action to perform when an option from the menu is
        // selected.
        switch (item.getItemId()) 
        case 0:
            optionsIntent = new Intent(Main.this, Options.class);
            startActivityForResult(optionsIntent, 1);
            return true;
        case 1:
            new AlertDialog.Builder(Main.this).setTitle(R.string.about_text)
                    .setMessage(getString(R.string.about_shark))
                    .setNeutralButton(getString(R.string.ok), null).show();
            return true;
        
        return false;
    

    /**
     * Calls TCPdumpHandler to try start the packet capture.
     */
    private void startTCPdump() 
        if (tcpDumpHandler.checkNetworkStatus()) 

            switch (tcpDumpHandler.start(parameters.getText().toString())) 
            case 0:
                Toast.makeText(Main.this, getString(R.string.tcpdump_started),
                        Toast.LENGTH_SHORT).show();
                break;
            case -1:
                Toast.makeText(Main.this,
                        getString(R.string.tcpdump_already_started),
                        Toast.LENGTH_SHORT).show();
                break;
            case -2:
                new AlertDialog.Builder(Main.this)
                        .setTitle(getString(R.string.device_not_rooted_error))
                        .setMessage(
                                getString(R.string.device_not_rooted_error_msg))
                        .setNeutralButton(getString(R.string.ok), null).show();
                break;
            case -4:
                new AlertDialog.Builder(Main.this).setTitle("Error")
                        .setMessage(getString(R.string.command_error))
                        .setNeutralButton(getString(R.string.ok), null).show();
                break;
            case -5:
                new AlertDialog.Builder(Main.this).setTitle("Error")
                        .setMessage(getString(R.string.outputstream_error))
                        .setNeutralButton(getString(R.string.ok), null).show();
                break;
            default:
                new AlertDialog.Builder(Main.this).setTitle("Error")
                        .setMessage(getString(R.string.unknown_error))
                        .setNeutralButton(getString(R.string.ok), null).show();
            
         else 
            new AlertDialog.Builder(Main.this)
                    .setTitle(getString(R.string.network_connection_error))
                    .setMessage(
                            getString(R.string.network_connection_error_msg))
                    .setPositiveButton(getString(R.string.yes),
                            new DialogInterface.OnClickListener() 
                                public void onClick(DialogInterface dialog,
                                        int which) 
                                    startActivity(new Intent(
                                            Settings.ACTION_WIRELESS_SETTINGS));
                                
                            ).setNegativeButton(getString(R.string.no), null)
                    .show();
        
    

    /**
     * Calls TCPdumpHandler to try to stop the packet capture.
     */
    private void stopTCPdump() 
        switch (tcpDumpHandler.stop()) 
        case 0:
            Toast.makeText(Main.this, getString(R.string.tcpdump_stoped),
                    Toast.LENGTH_SHORT).show();
            break;
        case -1:
            Toast.makeText(Main.this,
                    getString(R.string.tcpdump_already_stoped),
                    Toast.LENGTH_SHORT).show();
            break;
        case -2:
            new AlertDialog.Builder(Main.this)
                    .setTitle(getString(R.string.device_not_rooted_error))
                    .setMessage(getString(R.string.device_not_rooted_error_msg))
                    .setNeutralButton(getString(R.string.ok), null).show();
            break;
        case -4:
            new AlertDialog.Builder(Main.this).setTitle("Error")
                    .setMessage(getString(R.string.command_error))
                    .setNeutralButton(getString(R.string.ok), null).show();
            break;
        case -5:
            new AlertDialog.Builder(Main.this).setTitle("Error")
                    .setMessage(getString(R.string.outputstream_error))
                    .setNeutralButton(getString(R.string.ok), null).show();
            break;
        case -6:
            new AlertDialog.Builder(Main.this).setTitle("Error")
                    .setMessage(getString(R.string.close_shell_error))
                    .setNeutralButton(getString(R.string.ok), null).show();
            break;
        case -7:
            new AlertDialog.Builder(Main.this).setTitle("Error")
                    .setMessage(getString(R.string.process_finish_error))
                    .setNeutralButton(getString(R.string.ok), null).show();
        default:
            new AlertDialog.Builder(Main.this).setTitle("Error")
                    .setMessage(getString(R.string.unknown_error))
                    .setNeutralButton(getString(R.string.ok), null).show();
        

    

    /**
     * Tries to launch the reader activity.
     */
    private void launchReader() 
        readerIntent = new Intent(Main.this, Reader.class);
        if (FileManager.checkFile(GlobalConstants.dirName,
                settings.getString("fileText", "shark_capture.pcap"))) 
            if (tcpdump.getProcessStatus() == false) 
                startActivity(readerIntent);
             else 
                new AlertDialog.Builder(Main.this)
                        .setTitle(getString(R.string.capture_in_progress_error))
                        .setMessage(
                                getString(R.string.capture_in_progress_error_msg))
                        .setPositiveButton(getString(R.string.yes),
                                new DialogInterface.OnClickListener() 
                                    public void onClick(DialogInterface arg0,
                                            int arg1) 
                                        stopTCPdump();
                                        startActivity(readerIntent);
                                    
                                )
                        .setNegativeButton(getString(R.string.no), null).show();
            
         else 
            new AlertDialog.Builder(Main.this)
                    .setTitle(getString(R.string.file_error))
                    .setMessage(getString(R.string.file_error_msg))
                    .setNeutralButton(getString(R.string.ok), null).show();
        
    

当我运行这个 Eclipse 时,我在日志中收到一个错误 cat 以下错误。我尝试了很多建议的解决方案,即使那样我也无法获得解决方案。

08-21 15:38:01.483: D/AndroidRuntime(499): Shutting down VM

08-21 15:38:01.483: W/dalvikvm(499): threadid=1: thread exiting with uncaught exception (group=0x4001d800)

08-21 15:38:01.504: E/AndroidRuntime(499): FATAL EXCEPTION: main

08-21 15:38:01.504: E/AndroidRuntime(499): java.lang.RuntimeException: Unable to start activity ComponentInfocom.shark/com.shark.Main: java.lang.NullPointerException

08-21 15:38:01.504: E/AndroidRuntime(499):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2663)

08-21 15:38:01.504: E/AndroidRuntime(499):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)

08-21 15:38:01.504: E/AndroidRuntime(499):  at android.app.ActivityThread.access$2300(ActivityThread.java:125)

08-21 15:38:01.504: E/AndroidRuntime(499):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)

08-21 15:38:01.504: E/AndroidRuntime(499):  at android.os.Handler.dispatchMessage(Handler.java:99)

08-21 15:38:01.504: E/AndroidRuntime(499):  at android.os.Looper.loop(Looper.java:123)

08-21 15:38:01.504: E/AndroidRuntime(499):  at android.app.ActivityThread.main(ActivityThread.java:4627)

08-21 15:38:01.504: E/AndroidRuntime(499):  at java.lang.reflect.Method.invokeNative(Native Method)

08-21 15:38:01.504: E/AndroidRuntime(499):  at java.lang.reflect.Method.invoke(Method.java:521)

08-21 15:38:01.504: E/AndroidRuntime(499):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)

08-21 15:38:01.504: E/AndroidRuntime(499):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)

08-21 15:38:01.504: E/AndroidRuntime(499):  at dalvik.system.NativeStart.main(Native Method)

08-21 15:38:01.504: E/AndroidRuntime(499): Caused by: java.lang.NullPointerException

08-21 15:38:01.504: E/AndroidRuntime(499):  at com.shark.TCPdumpHandler.generateCommand(TCPdumpHandler.java:322)

08-21 15:38:01.504: E/AndroidRuntime(499):  at com.shark.Main.onCreate(Main.java:93)

08-21 15:38:01.504: E/AndroidRuntime(499):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)

08-21 15:38:01.504: E/AndroidRuntime(499):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)

08-21 15:38:01.504: E/AndroidRuntime(499):  ... 11 more

我找到了错误发生的确切位置。据此,“closeShell”在以下代码中返回 null。进一步循环回三个类。

 public class RootShell 
protected Process process = null;
protected DataOutputStream os = null;
protected DataInputStream is = null;

private boolean deviceRooted = false;

/**
 * RootShell class constructor. Checks if the device is rooted.
 */
public RootShell() 
    deviceRooted = checkRootStatus();


/**
 * RootShell class destructor. Closes the shell if its not already closed.
 */
protected void finalize() 
    if (process != null)
        closeShell();


/**
 * Opens a root shell and waits for commands.
 * 
 * @return 0 Everything went OK.<br>
 *         -1 The shell has already been opened.<br>
 *         -2 The device isn't rooted.<br>
 *         -3 IOException when running the su command.
 */
public int openShell() 
    if (process == null) 
        if (deviceRooted) 
            // Trying to get root access.
            try 
                process = Runtime.getRuntime().exec("su");
             catch (IOException e) 
                return -3;
            

            // Getting an output stream to the root shell for introducing
            // commands.
            os = new DataOutputStream(process.getOutputStream());

            // Getting an input stream to the root shell for displaying
            // results.
            is = new DataInputStream(process.getInputStream());

            return 0;
         else
            return -2;
     else
        return -1;


/**
 * Runs the command in the root shell.
 * 
 * @param command
 *            The command which will be executed in the root shell.
 * @return 0 Everything went OK.<br>
 *         -1 The shell wasn't opened.<br>
 *         -2 The device isn't rooted.<br>
 *         -4 IOException when running the user command.<br>
 *         -5 IOException when flushing the DataOutputStream.
 */
public int runCommand(String command) 
    if (process != null) 
        if (deviceRooted) 
            try 
                os.writeBytes(command + "\n");
             catch (IOException e) 
                return -4;
            

            try 
                os.flush();
             catch (IOException e) 
                return -5;
            
            return 0;
         else
            return -2;
     else
        return -1;


/**
 * Closes a shell which is already open.
 * 
 * @return -1 The shell wasn't opened.<br>
 *         -2 The device isn't rooted.<br>
 *         -6 IOException when running the exit command.<br>
 *         -7 InterruptedException when waiting for the process to stop.
 */
public int closeShell() 
    if (process != null) 

        if (deviceRooted) 
            try 
                os.writeBytes("exit\n");
             catch (IOException e1) 
                return -6;
            

            try 
                process.waitFor();
             catch (InterruptedException e) 
                return -7;
            

            process.destroy();

            process = null;
            os = null;
            is = null;

            return 0;
         else
            return -2;
     else
        return -1;



/**
 * Checks if an Android device is rooted or not.<br>
 * Code borrowed from: http://www
 * .stealthcopter.com/blog/2010/01/android-requesting-root-access-in
 * -your-app/
 * 
 * @return true: The device is rooted.<br>
 *         false: The device isn't rooted.
 */
private static boolean checkRootStatus() 
    Process p;
    try 
        // Preform su to get root privileges
        p = Runtime.getRuntime().exec("su");

        // Attempt to write a file to a root-only
        DataOutputStream os = new DataOutputStream(p.getOutputStream());
        os.writeBytes("echo \"Do I have root?\" >/system/sd/temporary.txt\n");

        // Close the terminal
        os.writeBytes("exit\n");
        os.flush();
        try 
            p.waitFor();
            if (p.exitValue() != 255) 
                return true;
             else 
                return false;
            
         catch (InterruptedException e) 
            return false;
        
     catch (IOException e) 
        return false;
    


/**
 * @return A DataInputStream to the root shell.
 */
public DataInputStream getInputStream() 
    return is;


/**
 * @return A DataOutputStream to the root shell.
 */
public DataOutputStream getOutputStream() 
    return os;


/**
 * @return true if the shell is opened.<br>
 *         false if the shell isn't opened.
 */
public boolean getProcessStatus() 
    if (process != null)
        return true;
    else
        return false;


我还发现,它给出“08-22 19:05:19.701: I/System.out(275): e1java.io.IOException: Broken pipe”,它在“closeshell”中输入 try catch。

【问题讨论】:

【参考方案1】:

您的R.id.start_button 和其他多个地方的R 是什么? 错误是指tcpDumpHandler.generateCommand(),但您没有提供它的代码。

【讨论】:

非常感谢,我找到了错误的主要原因。尝试获取 root 访问权限时,它在某一时刻返回 null,但我无法更正它。 我还有一个疑问,我们能否在 Eclipse 中在 Android Emulator 上运行需要 root 权限的应用程序?? R 指向 gen 包中的 R.java 文件,该文件与 main.xml 中定义的开始按钮相关,将在 UI 中显示。

以上是关于致命异常:主要用于数据包嗅探应用程序的主要内容,如果未能解决你的问题,请参考以下文章

我的数据包嗅探器是不是应该捕获任何数据包?

Scapy 数据包嗅探器触发对每个嗅探数据包的操作

Python 中的数据包嗅探(Windows)

基于Libpcap实现一个网络数据包嗅探器

安全牛学习笔记抓包嗅探

linux 下如何抓取HTTP流量包(httpry)