编译和使用Android平台下的libpcap和jpcap

〇、写在前面

笔者一直想尝试编写Android平台的抓包APP,于是网上调研了些资料,发现大部分文章都说移植libpcap+jpcap或者libpcap+jnetpcap的方式来实现,但按照他们所说的编译方式step by step执行,发现基本编译都通不过,很是蛋疼。后来经过一番折腾通过自己的方式完成了Android平台下的编译和使用。

一、编译libpcap和jpcap

1. 下载源代码

1.1 libpcap

git clone https://android.googlesource.com/platform/external/libpcap

1.2 jpcap

jpcap这个有点坑,我先尝试下载了官方仓库源代码,发现编译文件有makefile和build.xml,说明它支持gnu make和ant build两种方式。都尝试了一下,不出意外都失败了。

后来在git上找到了某个jpcap仓库,基于它编译竟然OK,读者请下载这个仓库的代码。

2. 编译libpcap

libpcap网上都说使用ndk-build去编译,自己创建Android.mk去编译,我嫌麻烦就直接使用NDK_TOOLS_CHAINS编译,编译前请配置环境变量,请读者参照自己的实际目录更改,如下所示:

export ANDROID_NDK=${android_ndk_root} ;\ 
export CC=${ANDROID_NDK}/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-gcc ;\ 
export CCOPT="-O2 -fpic --sysroot=/your-path-to-android-ndk-toolchain-sysroot -DANDROID -DOS_ANDROID" ;\
export CFLAGS="--sysroot=/your-path-to-android-ndk-toolchain-sysroot -DANDROID -DOS_ANDROID -I./usr/include " ;\
export LDFLAGS="--sysroot=/your-path-to-android-ndk-toolchain-sysroot -fPIC -mandroid -L./usr/lib" ;\
./configure --host=arm-linux --with-pcap=linux --prefix=/your-path-to-android-ndk-toolchain-sysroot/usr

然后一键make:

make

最后生成libpcap.a, libpcap.so.1.9.0。

3. 编译jpcap

前面说了使用gnu make和ant build去编译都失败了,于是乎去网上各种搜看看别人是怎么编译jpcap的,后来找到了在 Cygwin 下编译Android的libpcap.a和libjpcap.so这篇文章,然后参照他的方法编译。

重新创建任意名称目录“/a/b/jni”,然后把libpcap里面的“libpcap.a、libpcap.so、pcap.c、pcap.h、pcap-bpf.c、pcap-bpf.h”拷贝到jni下面,还需要某些头文件也要搞过来。

cp /path-to-your-libpcap/libpcap.a .
cp /path-to-your-libpcap/pcap.c .
cp /path-to-your-libpcap/pcap.h .
cp /path-to-your-libpcap/pcap-bpf.c .
cp /path-to-your-libpcap/pcap-bpf.h .
cp -r  /path-to-your-libpcap/pcap .

然后再把jpcap里面所有的cpp和c文件拷贝过来,以及部分头文件(Jpcap_sub.h、Jpcap_ether.h、jpcap_JpcapCaptor.h、jpcap_JpcapSender.h、jpcap_JpcapSender.h)也需要拷贝过来。

for i in `find -E /path-to-your-jpcap  -regex '.*\.(c|cpp)'` ; do cp $i .;done

接着,创建Android.mk文件,内容如下:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
#LOCAL_MODULE:= libpcap
#LOCAL_SRC_FILES:= $(LOCAL_PATH)/libs/libpcap.a
#include $(PREBUILT_STATIC_LIBRARY)
#include $(CLEAR_VARS)

LOCAL_MODULE:= jpcap

LOCAL_SRC_FILES:=\
 JpcapCaptor.c\
 JpcapSender.c\
 JpcapWriter.c\
 packet_arp.c\
 packet_datalink.c\
 packet_icmp.c\
 packet_ip.c\
 packet_ipv6.c\
 packet_tcp.c\
 packet_udp.c

LOCAL_CFLAGS:=-O2 -g

LOCAL_CFLAGS+=-DHAVE_CONFIG_H -D_U_="__attribute__((unused))" -Dlinux -D__GLIBC__ -D_GNU_SOURCE

LOCAL_LDFLAGS := $(LOCAL_PATH)/libs/libpcap.so

include $(BUILD_SHARED_LIBRARY)

这个文件内容也改了好几次,先前是引用静态库libpcap.a编译,结果报错undefine的符号引用没找到的问题。于是干脆换成了引用动态库的方式,从注释部分也看得出来。

最后,我一键ndk-build,结果还报错说是第三方库是“不兼容的目标”,排查后知道原因是ndk-build默认使用了32位编译,然我们的libpcap.so是64位的,于是新建Application.mk文件,添加编译64位目标程序的配置:

APP_ABI := arm64-v8a

这次终于一键ndk-build成功了。生成了libjpcap.so文件。

二、Android APP使用jpcap

1. 导入jpcap.jar和jpcap.so到Android项目

Android studio导入第三方jar包比较容易,不需要特定的存放路径规定,我先想着把它放在了app/src/main/Libs下面,同时也把jpcap.so放在了该目录下面,同时配置app/build.gradle内容,并在dependencies section下面添加如下引用:

dependencies {
	... ...
    compile files('src/main/Libs/jpcap.jar')
}

然后创建jpcap的引用模块代码,网上搜到的jpcap usage事例代码加到SnifferTraffic.java里面,主要是获取网络设备列表。

然后编译生成apk放到手机上运行,结果生成的apk运行后报错,提示libjpcap.so未找到,adb shell到app安装目录下面查看lib文件夹中确实没有任何库文件,说明jpcap.so并没有嵌到apk包里面去。经过一番搜索在一篇博客中找到了答案,原来是jpcap.so存放的路径有问题,最简单的解决办法是在src/main/下面创建jniLibs目录,然后将所有native so放在这下面,更新下dependencies section中引用:

dependencies {
	... ...
    compile files('src/main/jniLibs/jpcap.jar')
}

OK,解决了路径存放的问题,现在编译并运行,结果还是报错,提示libpcap.so.1找不到,这里我陷入了一个误区,误将libpcap.so.1看成了libjpcap.so.1,以为是jpcap还是没正确导入。然后各种改文件名称或者创建链接文件,比如将libjpcap.so改名位libjpcap.so.1试图解决,结果始终提示libpcap.so.1找不到。说明解决方法有问题。

后来仔细一看,卧槽!提示的名字是libpcap.so.1,并不是libjpcap.so.1啊。说明jpcap导入正确了,但是libpcap没有导入正确。然后IDA看来下jpcap.so引用的第三方库就包含libjpcap.so.1,问题终于找到了。那么直接把上面编译成功的libpcap.so重命名成libpcap.so.1,放到jniLibs目录下面呗。

OK,解决了libjpcap.so.1的问题,再次编译并运行,结果仍然报错,还是提示libjpcap.so.1找不到,adb shell到app安装目录下面查看lib文件夹中发现只有libjpcap.so一个文件,并没有libpcap.so.1文件,经过一番折腾得知后缀xx.so.1这种文件根本就不会导入。

然后继续网上搜答案,找到了这篇文章,这篇文章的意思就是说把so文件名称、so ELF文件结构中的SONAME名称、以及java代码里面的System.loadLibrary(soname)这三者要保持一致。仔细分析并没有什么帮助,又走了弯路。

anyway,自己分析解决吧,不就是导入的第三方库名称是xx.so.1,然后xx.so.1又没有办法放入apk里面嘛。我们强行改写导入的第三方库名称为xx.so呗,然后放入xx.so不就行了嘛。好,我们来试一下。首先010editor搜索jpcap.so里面的字符串xx.so.1,然后更改为xx.so保存,然后把xx.so也放到jniLibs下面。

最后,再次编译运行,OK了,不再报错xx库找不到的问题了。代码run起来了。哈哈哈~

但是还有问题,设备列表获取为空,网上说是APP不具备root权限问题。暂时还没解这个问题。后续更新吧。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值