今天发现一个问题,在Android5.0系统下用tcpdump抓包失败,但是在5.0之前的系统上可以正常抓包,报如下错误
1 |
error: only position independent executables (PIE) are supported. |
这是由于PIE安全机制所引起的,从Android4.1开始引入该机制,但是Android L之前的系统版本并不会去检验可执行文件是否基于PIE编译出的。因此不会报错。但是Android L已经开启验证,如果调用的可执行文件不是基于PIE方式编译的,则无法运行。解决办法非常简单,编译的时候加上如下的flag就行。
1 2 |
LOCAL_CFLAGS += -pie -fPIE LOCAL_LDFLAGS += -pie -fPIE |
编译tcpdump
准备编译环境
系统环境:Ubuntu
Android NDK:Android NDK rev 10e (32 bit)
源码:Libpcap v1.7.4, Tcpdump v4.7.4
在编译之前首先确保有lex和yacc工具,如果没有则需要安装,执行如下脚本。
1 |
sudo apt-get install flex bison |
执行编译脚本
接下来在NDK目录下执行如下脚本,这个脚本会自动下载tcpdump和libpcap,注意脚本的216,217行,设置了-pie -fPIE标志
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 |
#!/bin/sh tcpdump_ver=4.7.4 libpcap_ver=1.7.4 android_api_def=21 ndk_dir_def=android-ndk-r10e #-------------------------------------------------------# tcpdump_dir=tcpdump-${tcpdump_ver} libpcap_dir=libpcap-${libpcap_ver} if [ ${NDK} ] then ndk_dir=${NDK} else ndk_dir=${ndk_dir_def} fi ndk_dir=`readlink -f ${ndk_dir}` if [ ${ANDROID_API} ] then android_api=${ANDROID_API} else android_api=${android_api_def} fi echo "_______________________" echo "" echo "NDK - ${ndk_dir}" echo "Android API: ${android_api}" echo "_______________________" exit_error() { echo " _______" echo "| |" echo "| ERROR |" echo "|_______|" exit 1 } { if [ $# -ne 0 ] then if [ -d $1 ] then cd $1 else echo directory $1 not found exit_error fi else mkdir tcpdumpbuild cd tcpdumpbuild fi } # create env { echo " ____________________" echo "| |" echo "| CREATING TOOLCHAIN |" echo "|____________________|" if [ -d toolchain ] then echo Toolchain already exist! Nothing to do. else echo Creating toolchain... mkdir toolchain bash ${ndk_dir}/build/tools/make-standalone-toolchain.sh --arch=arm --platform=android-${android_api} --install-dir=toolchain if [ $? -ne 0 ] then rm -fr toolchain exit_error fi fi export CC=arm-linux-androideabi-gcc export RANLIB=arm-linux-androideabi-ranlib export AR=arm-linux-androideabi-ar export LD=arm-linux-androideabi-ld export PATH=`pwd`/toolchain/bin:$PATH } # download & untar libpcap + tcpdump { echo " _______________________________" echo "| |" echo "| DOWNLOADING LIBPCAP & TCPDUMP |" echo "|_______________________________|" tcpdump_file=${tcpdump_dir}.tar.gz libpcap_file=${libpcap_dir}.tar.gz tcpdump_link=http://www.tcpdump.org/release/${tcpdump_file} libpcap_link=http://www.tcpdump.org/release/${libpcap_file} if [ -f ${tcpdump_file} ] then echo ${tcpdump_file} already downloaded! Nothing to do. else echo Download ${tcpdump_file}... wget ${tcpdump_link} if [ ! -f ${tcpdump_file} ] then exit_error fi fi if [ -f ${libpcap_file} ] then echo ${libpcap_file} already downloaded! Nothing to do. else echo Download ${libpcap_file}... wget ${libpcap_link} if [ ! -f ${libpcap_file} ] then exit_error fi fi if [ -d ${tcpdump_dir} ] then echo ${tcpdump_dir} directory already exist! Nothing to do. else echo untar ${tcpdump_file} tar -zxf ${tcpdump_file} fi if [ -d ${libpcap_dir} ] then echo ${libpcap_dir} directory already exist! Nothing to do. else echo untar ${libpcap_file} tar -zxf ${libpcap_file} fi } # build libpcap { cd ${libpcap_dir} echo " _____________________" echo "| |" echo "| CONFIGURING LIBPCAP |" echo "|_____________________|" chmod +x configure ./configure --host=arm-linux --with-pcap=linux ac_cv_linux_vers=2 if [ $? -ne 0 ] then exit_error fi echo " __________________" echo "| |" echo "| BUILDING LIBPCAP |" echo "|__________________|" chmod +x runlex.sh make if [ $? -ne 0 ] then exit_error fi cd .. } # build tcpdump { cd ${tcpdump_dir} echo " _____________________" echo "| |" echo "| CONFIGURING TCPDUMP |" echo "|_____________________|" chmod +x configure # Compile PIE (position independent executable) for Lollipop compatibility. ./configure --host=arm-linux ac_cv_linux_vers=2 --with-crypto=no CFLAGS='-fPIE' LDFLAGS='-fPIE -pie' if [ $? -ne 0 ] then exit_error fi echo " __________________" echo "| |" echo "| BUILDING TCPDUMP |" echo "|__________________|" #setprotoent endprotoen not supported on android sed -i".bak" "s/setprotoent/\/\/setprotoent/g" print-isakmp.c sed -i".bak" "s/endprotoent/\/\/endprotoent/g" print-isakmp.c # NBBY is not defined => FORCE definition make CFLAGS='-DNBBY=8' # for tcpdump < 4.2.1 (CFLAGS redefined in Makefile) => just make if [ $? -ne 0 ] then exit_error fi cd .. } cp ${tcpdump_dir}/tcpdump . chmod +x tcpdump echo " __________________" echo "| |" echo "| TCPDUMP IS READY |" echo "|__________________|" echo `pwd`/tcpdump |
如果一切顺利的话,你将会在脚本的执行路径下看到一个tcpdumpbuild目录,其中包含源代码,和编译结果tcpdump。如果你比较懒,可以用我已经编译好的tcpdump。看完这篇文章,就可以完美移植tcpdump到Android系统。
参考链接:http://muzso.hu/2015/07/14/how-to-compile-tcpdump-for-android-5.-lollipop