Friday, May 20, 2011

libpcap for Android


The Android project includes libpcap as an external library as can be seen from the source here on kernel.org and Github

My project for Google Summer of Code - The mobile network scanner requires the use of libpcap or tcpdump. I was successful in compiling libpcap from its source and loading the library to use the native functions in JNI. But since an Android application does not run with Root privileges, it is a challenge to get the native functions to work in the same process.

The native code and the Java code for an android application runs in the same process. So the native code does not have root privileges. So as of now, it is not possible to get libpcap functions to work using the NDK. But there are alternatives which I will be suggesting in this blog post.

First of all, here are the instructions to successfully compile the libpcap.so library for use in the JNI code.

Create a folder called jni in the application root.

Android.mk

LOCAL_PATH := ./jni  

include $(CLEAR_VARS)  
LOCAL_MODULE    := pcaptest  
LOCAL_SRC_FILES := libpcap-native.c  

LOCAL_C_INCLUDES := $(NDK_ROOT)/external/libpcap   

LOCAL_STATIC_LIBRARIES := libpcap  

LOCAL_LDLIBS := -ldl -llog  

include $(BUILD_SHARED_LIBRARY)   

include $(NDK_ROOT)/external/libpcap/Android.mk  

Libpcap for android is built as a static library and its functions are then used as a shared library.
A shared library build specifications are defined in the Android.mk make file in the JNI folder of the project. The JNI folder contains the make files for the library. It also contains the native C code with function definitions according to the Java package.


This is a sample JNI code for getting the list of available network interfaces by using the pcap_lookupdevs function

#include <jni.h>  
#include <string.h>  
#include <android/log.h>  
#include <pcap.h>  

#define DEBUG_TAG "Sample_LIBPCAP_DEBUGGING"  

void Java_org_umit_android_libpcaptest_libpcaptest_testLog(JNIEnv *env, jclass clazz, jstring message)  
{  
    char errbuf[1024];  
    errbuf[0] = '\0';  

    char *szLogThis;  
    char *dev = pcap_lookupdev(errbuf);  

    if (dev == NULL) {  
        szLogThis = "Couldn't find default device";       
    }  
    else szLogThis = dev;  

    __android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "Device status: [%s]", szLogThis);  
    __android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "errbuf [%s]", errbuf);  

    (*env)->ReleaseStringUTFChars(env, message, szLogThis);  
}  
The C code can now be called as native functions from inside Java code by loading the shared library

static{  
    System.loadLibrary("pcaptest");  
}  

private native void testLog(String logThis);  



The native code needs to compiled with ndk-build command and requires the android-ndk to be downloaded from the official website.

For now, I am getting the error

D/Sample_LIBPCAP_DEBUGGING( 364): Device status: [Couldn't open device]
D/Sample_LIBPCAP_DEBUGGING( 364): errbuf [socket: Operation not permitted]


And when I try and use the pcap_open_live function, I get the following error
 D/Sample_LIBPCAP_DEBUGGING(  310): errbuf [socket: Operation not permitted]

The reason for this error is that the native code and the application both lie in the same process. Invoking a "su" here would not work because an "su" just forks a new process that has root privileges but that process would not contain our native code.

So a work around for this is that a binary or a unix library should be compiled before hand and then supplied with the apk. The binary can be extracted from the apk. The binary may require root privileges but it would be as easy as forking another process with "su" command.

Here is a blog post explaining that http://nerdposts.blogspot.com/2010/11/android-superuser-shared-jni-libs.html

For now, I am just sticking to tcpdump for the requirements of this project. If we need a specific implementation of packet sniffing from libpcap, the plan is to compile a binary or a unix shared library and supply it with the apk.

7 comments:

  1. Did you try to implement libcap on android? I have similar needs and I'd like to know if somebody succeded in it before me.

    ReplyDelete
  2. Did you try to implement libcap on android did you find any other way to make a packet sniffer? I have similar project and I'd like to know if someone succeded in this.

    ReplyDelete
  3. Thanks for the post and the work behind. It is really helpful.

    I have some troubles compiling the libpcap with NDK. You can found the trouble here:

    http://stackoverflow.com/questions/5952878/android-ndk-trying-to-port-jnetpcap

    ReplyDelete
  4. do any one is able implement to packet sniffing using above said process?

    ReplyDelete
  5. This two projects should be useful:

    https://github.com/umitproject/pm-mobile
    https://github.com/umitproject/ns-mobile

    ReplyDelete
  6. I'm currently developing a packet sniffer for android.
    My executable sends the captured packets via loopback to my application.
    The application also contains an ARP-spoofer and is able to display to packets wireshark like (extracting and displaying the packet headers in a human-readable format).
    TCP-Stream reassembly/injection and the extraction of passwords/sessions from some protocols is yet to come.
    Screenshots and information can be found on my blog (German):
    http://4meme.de

    I'll release the source-code soon enough on github.

    ReplyDelete
  7. That's awesome! Have you forked https://github.com/umitproject/pm-mobile?

    By the way, is it open source? :)

    But it seems quite nice. Congrats.

    ReplyDelete