tcpsnitch
هي أداة تتبع مصممة لفحص التفاعلات بين التطبيق ومكدس TCP/IP. يقوم tcpsnitch
بتشغيل الأمر المحدد حتى يخرج ويعترض جميع استدعاءات وظائف libc على مقابس الإنترنت.
للبدء بلطف، يمكن للمرء تشغيل الأمر التالي لتتبع برنامج curl
:
$ tcpsnitch curl google.com
لكل مقبس إنترنت مفتوح، ينشئ tcpsnitch
قائمة مرتبة باستدعاءات الوظائف (يسمى استدعاء الوظيفة حدثًا في الجزء المتبقي من هذا المستند). لكل حدث، يقوم tcpsnitch
بتسجيل الوسائط وقيمة الإرجاع ومعلومات متنوعة مثل الطابع الزمني الحالي أو معرف مؤشر الترابط. على وجه التحديد، قد يبدو حدث connect()
كما يلي في تتبع مأخذ التوصيل:
{
"type" : " connect " ,
"timestamp_usec" : 1491043720731853 ,
"return_value" : 0 ,
"success" : true ,
"thread_id" : 17313 ,
"details" : {
"addr" : {
"sa_family" : " AF_INET " ,
"ip" : " 127.0.1.1 " ,
"port" : " 53 "
}
}
}
تتم كتابة آثار مأخذ التوصيل إلى ملفات نصية حيث يكون كل سطر عبارة عن كائن JSON يمثل حدثًا واحدًا. رأس مثل هذا التتبع يمكن أن يكون مثل هذا:
{ "type" : " socket " , "timestamp_usec" : 1491043720731840 , "return_value" : 6 , "success" : true , "thread_id" : 17313 , "details" : { "sock_info" : { "domain" : " AF_INET " , "type" : " SOCK_DGRAM " , "protocol" : 0 , "SOCK_CLOEXEC" : false , "SOCK_NONBLOCK" : true }}}
{ "type" : " ioctl " , "timestamp_usec" : 1491043720765019 , "return_value" : 0 , "success" : true , "thread_id" : 17313 , "details" : { "request" : " FIONREAD " }}
{ "type" : " recvfrom " , "timestamp_usec" : 1491043720765027 , "return_value" : 44 , "success" : true , "thread_id" : 17313 , "details" : { "bytes" : 2048 , "flags" : { "MSG_CMSG_CLOEXEC" : false , "MSG_DONTWAIT" : false , "MSG_ERRQUEUE" : false , "MSG_OOB" : false , "MSG_PEEK" : false , "MSG_TRUNC" : false , "MSG_WAITALL" : false }, "addr" : { "sa_family" : " AF_INET " , "ip" : " 127.0.1.1 " , "port" : " 53 " }}}
{ "type" : " ioctl " , "timestamp_usec" : 1491043720770075 , "return_value" : 0 , "success" : true , "thread_id" : 17313 , "details" : { "request" : " FIONREAD " }}
{ "type" : " recvfrom " , "timestamp_usec" : 1491043720770094 , "return_value" : 56 , "success" : true , "thread_id" : 17313 , "details" : { "bytes" : 65536 , "flags" : { "MSG_CMSG_CLOEXEC" : false , "MSG_DONTWAIT" : false , "MSG_ERRQUEUE" : false , "MSG_OOB" : false , "MSG_PEEK" : false , "MSG_TRUNC" : false , "MSG_WAITALL" : false }, "addr" : { "sa_family" : " AF_INET " , "ip" : " 127.0.1.1 " , "port" : " 53 " }}}
نظرًا لأن أمرًا واحدًا قد يؤدي إلى تشعب عمليات متعددة (ويتبع tcpsnitch
التفرعات)، يتم تجميع جميع آثار المقابس التي تنتمي إلى عملية معينة معًا في دليل، يُسمى على اسم العملية التي تم تتبعها. داخل مثل هذا الدليل، تتم تسمية آثار مأخذ التوصيل بناءً على ترتيب فتحها بواسطة العملية.
افتراضيًا، يتم حفظ الآثار في دليل عشوائي ضمن /tmp
ويتم تحميلها تلقائيًا إلى www.tcpsnitch.org، وهي منصة مصممة لتمركز الآثار وتصورها وتحليلها. لاحظ أن جميع الآثار التي تم تحميلها عامة ومتاحة لأي شخص للاستشارة والتنزيل.
كما هو واضح في مقتطف الشفرة التالي، يمنحك tcpsnitch
عنوان URL الذي يتوفر فيه التتبع.
$ tcpsnitch curl google.com
Trace saved in /tmp/tmp.4ERKizKyU3.
Uploading trace....
Trace successfully uploaded at https://tcpsnitch.org/app_traces/20.
Trace archive will be imported shortly. Refresh this page in a few minutes...
لاحظ أنه يلزم عدة دقائق لاستيراد التتبع (أي استخراج أرشيف التتبع وإدراج كافة الأحداث في قاعدة البيانات). بمجرد الاستيراد، قد تكون هناك حاجة إلى عدة دقائق إضافية لحساب التحليل الكمي للتتبع.
وأخيرًا، يسمح tcpsnitch
أيضًا باستخراج خيار مأخذ التوصيل TCP_INFO
على فترات زمنية محددة من قبل المستخدم وتسجيل تتبع .pcap
لكل مأخذ توصيل فردي. راجع قسم الاستخدام لمزيد من المعلومات.
يسمح tcpsnitch
بتتبع التطبيقات على:
نظرًا لأن tcpsnitch
يعمل عن طريق اعتراض استدعاءات وظائف libc باستخدام متغير البيئة LD_PRELOAD
، فلا يمكن إجراء التتبع للتطبيقات المرتبطة بشكل ثابت بـ libc.
ملاحظة: في نظام التشغيل Linux، من المعروف أن Chrome (وأي تطبيق يستند إلى Chromium مثل Electron وOpera وما إلى ذلك...) غير متوافق.
بالنسبة للمستخدمين الذين يرغبون في تتبع تطبيقات Android، قم بالتمرير لأسفل إلى قسم "Compilation for Android".
تم الاختبار على Ubuntu 16 و14، وDebian 8، وElementary 0.4، وMint 18
sudo dpkg --add-architecture i386 && sudo apt-get update && sudo apt-get install make gcc gcc-multilib libc6-dev libc6-dev:i386 libjansson-dev libjansson-dev:i386 libpcap0.8 libpcap0.8:i386 libpcap0.8-dev
تم اختباره على Fedora 25 وCentOS 7
sudo yum install make gcc glibc-devel glibc-devel.i686 libgcc libgcc.i686 libpcap-devel.x86_64 libpcap-devel.i686 jansson jansson.i686 && curl -O http://www.digip.org/jansson/releases/jansson-2.10.tar.bz2 && bunzip2 -c jansson-2.10.tar.bz2 | tar xf - && rm -f jansson-2.10.tar.bz2 && cd jansson-2.10 && ./configure && make && sudo make install && cd .. && rm -rf jansson-2.10
بناء وتثبيت:
./configure
make
sudo make install
الاستخدام: tcpsnitch [<options>] <cmd> [<cmd_args>]
حيث:
<options>
هي خيارات tcpsnitch
<cmd>
هو أمر التتبع (إلزامي)<cmd_args>
هي وسيطات <cmd>
. فيما يلي مثال بسيط مع curl
وجميع الخيارات الافتراضية:
tcpsnitch curl google.com
يمكن للمرء إصدار tcpsnitch -h
للحصول على مزيد من المعلومات حول الخيارات المدعومة. وأهمها ما يلي:
-b
و -u
لاستخراج TCP_INFO
على فترات زمنية محددة من قبل المستخدم. راجع القسم "استخراج TCP_INFO
" لمزيد من المعلومات.-c
يستخدم لالتقاط آثار pcap
للمآخذ. راجع قسم "التقاط الحزمة" لمزيد من المعلومات.-a
و -k
لتتبع تطبيق Android. راجع قسم "استخدام Android" لمزيد من المعلومات.-n
قم بإلغاء تنشيط التحميل التلقائي للآثار.-d
يعين الدليل الذي سيتم كتابة التتبع فيه (بدلاً من الدليل العشوائي في /tmp
).-f
يضبط مستوى الإسهاب للسجلات المحفوظة في الملف. افتراضيًا، تتم كتابة رسائل التحذير والخطأ فقط في السجلات. يكون هذا مفيدًا بشكل أساسي للإبلاغ عن الأخطاء وتصحيح الأخطاء.-l
يشبه -f
ولكنه يضبط إسهاب السجل على STDOUT، والذي يعرض افتراضيًا رسائل الخطأ فقط. يتم استخدام هذا لأغراض التصحيح.-t
يتحكم في معدل تكرار تفريغ الأحداث إلى الملف. افتراضيًا، تتم كتابة الأحداث في ملف كل 1000 مللي ثانية.-v
عديم الفائدة إلى حد كبير في الوقت الحالي، ولكن من المفترض وضع tcpsnitch
في الوضع المطول بأسلوب strace
. لا يزال يتعين تنفيذه (في الوقت الحالي يعرض فقط أسماء الأحداث).TCP_INFO
-b <bytes>
و -u <usec>
يسمحان باستخراج قيمة خيار مأخذ التوصيل TCP_INFO
لكل مأخذ توصيل على فترات زمنية محددة من قبل المستخدم. لاحظ أن قيم TCP_INFO
تظهر كأي حدث آخر في تتبع JSON الخاص بـ socekt.
-b <bytes>
، يتم تسجيل TCP_INFO
كل <bytes>
يتم إرساله + استلامه على مأخذ التوصيل.-u <usec>
، يتم تسجيل TCP_INFO
كل <usec>
ميكرو ثانية.TCP_INFO
عند مطابقة أي من الشرطين. بشكل افتراضي، يتم إيقاف تشغيل هذا الخيار. لاحظ أيضًا أن tcpsnitch
يتحقق فقط من هذه الشروط عند استدعاء دالة متجاوزة.
يقوم الخيار -c
بتنشيط التقاط تتبع .pcap
لكل مأخذ توصيل. لاحظ أنك تحتاج إلى الحصول على الأذونات المناسبة لتتمكن من التقاط حركة المرور على الواجهة (راجع man pcap
لمزيد من المعلومات حول هذه الأذونات).
هذه الميزة غير متوفرة لنظام Android في الوقت الحالي.
الاستخدام على Android عبارة عن عملية مكونة من خطوتين، تشبه إلى حد كبير الاستخدام على Linux. أولاً، قم بإعداد tcpsnitch
وتشغيل التطبيق المراد تتبعه بالخيارات المناسبة، ثم يتم سحب التتبعات من الجهاز ونسخها إلى الجهاز المضيف.
جميع الخيارات مدعومة على Android، باستثناء خيار -c
لالتقاط آثار .pcap
.
يجب تنفيذ بعض خطوات الإعداد الأولية مرة واحدة على الجهاز:
adb devices
وتأكد من أن هاتفك مرئي (يجب أن ترى device
في العمود الثاني). عندما يمكن الوصول إلى الجهاز عبر adb
، يكون الاستخدام هو نفسه تقريبًا كما هو الحال في Linux:
tcpsnitch
العادي مع الخيار -a
للإشارة إلى أنك تريد تتبع تطبيق ما على جهاز Android المتصل. لاحظ أن الوسيطة <cmd>
يجب أن تتطابق مع اسم الحزمة المثبتة على الجهاز عبر grep
بسيط. على سبيل المثال، لتتبع تطبيق Firefox الذي اسم الحزمة org.firefox.com
، يمكن للمرء إصدار tcpsnitch -a firefox
. سيخبرك tcpsnitch
بالحزمة المطابقة التي تم العثور عليها وسيبدأ التطبيق على الفور.tcpsnitch -k <package>
لإيقاف التطبيق وإنهاء عملية التتبع. سيتم سحب الآثار من الجهاز وحفظها على القرص الخاص بك في /tmp
قبل تحميلها على www.tcpsnitch.org. هام: يجب عليك إعادة تشغيل جهاز Android الخاص بك لإلغاء تنشيط التتبع بشكل كامل. نظرًا لأن tcpsnitch
يستخدم خصائص Android لإعداد مكتبة LD_PRELOAD
، ولا يمكن إلغاء تعيين هذه الخصائص، فيجب إعادة تشغيل الجهاز لإزالة الخصائص (ربما يعرف شخص ما حلاً أفضل؟).
فيما يلي مثال كامل لتتبع Firefox:
$ tcpsnitch -a firefox
Found Android package: ' org.mozilla.firefox ' .
Uploading tcpsnitch library to /data/libtcpsnitch.so.0.1-arm.
Start package ' org.mozilla.firefox ' .
Execute ' ./tcpsnitch -k firefox ' to terminate the capture.
# INTERACTING WITH APPLICATION
$ tcpsnitch -k firefox
Found Android package: ' org.mozilla.firefox ' .
Pulling trace from Android device....
Trace saved in /tmp/tmp.MidCH9rm3x.
Uploading trace....
Trace successfully uploaded at https://tcpsnitch.org/app_traces/21.
Trace archive will be imported shortly. Refresh this page in a few minutes...
لاحظ أنه في حالة وجود تطابقات متعددة لحزمة ما، سيتم استخدام الحزمة المطابقة الأولى. وبالتالي قد تحتاج إلى أن تكون أكثر تحديدًا لتجنب الصراعات. يمكنك تنفيذ adb shell pm list packages
للحصول على اسم جميع الحزم المثبتة على جهازك.
لاحظ أيضًا أن جهازًا واحدًا يجب أن يكون مرئيًا لـ adb
.
من أجل تتبع تطبيقات Android، يجب تجميع tcpsnitch
باستخدام Android Native Development Kit (NDK). يعد التجميع أكثر تعقيدًا ويتطلب الإعداد جهازًا يعمل بنظام Android.
في الأساس، يتضمن الخطوات التالية:
libjansson
و libpcap
باستخدام NDK، واجعل المكتبات المجمعة وملفات الرأس متاحة لسلسلة الأدوات المستقلة.tcpsnitch
باستخدام سلسلة الأدوات المستقلة وقم بإعداد جهاز Android.يقدم القسم التالي مثالاً معقدًا يرشدك خلال جميع الخطوات.
بعض الافتراضات:
<NDK_PATH>
.<TCPSNITCH_PATH>
.أولاً، دعونا نحدد بعض المتغيرات:
export TCPSNITCH=<TCPSNITCH_PATH>
export NDK=<NDK_PATH>
# Where the standalone toolchain WILL be created
export TOOLCHAIN=<TOOLCHAIN_PATH>
الآن، لنبدأ بإنشاء سلسلة أدوات مستقلة لجهاز ARM يعمل بنظام Android API 23 (الإصدار 6.0، Marshmallow). التعيين بين إصدارات Android ومستويات API في الصفحة التالية.
$NDK/build/tools/make_standalone_toolchain.py --arch arm --api 23 --install-dir $TOOLCHAIN
يجب علينا الآن تجميع كل من libjansson
و libpcap
باستخدام NDK. عندما يتم ذلك، يجب علينا تثبيت ملفات الرأس الخاصة بهم والمكتبات المجمعة في "sysroot" في سلسلة الأدوات المستقلة الخاصة بنا.
لنبدأ مع libjansson
:
git clone https://github.com/akheron/jansson && cd jansson
# Configuration file which we don't use, we may leave it empty
touch src/jansson_private_config.h
sed -i 's/BUILD_SHARED_LIBRARY/BUILD_STATIC_LIBRARY/g' Android.mk
$NDK/ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk
cp obj/local/armeabi/libjansson.a $TOOLCHAIN/sysroot/usr/lib/
cp src/jansson.h android/jansson_config.h $TOOLCHAIN/sysroot/usr/include/
cd .. && rm -rf jansson
الآن، دعونا نتناول libpcap
:
git clone https://github.com/the-tcpdump-group/libpcap && cd libpcap
export CC=$TOOLCHAIN/bin/arm-linux-androideabi-gcc
./configure --host=arm-linux --with-pcap=linux --prefix=/usr
# You will need to install some missing dependencies (e.g. `flex` & `bison`)
sudo apt-get install flex bison
# Reissue ./configure untill all dependencies are met
./configure --host=arm-linux --with-pcap=linux --prefix=/usr
# Compile && install in toolchain
make && sudo make install DESTDIR=$TOOLCHAIN/sysroot
cd .. && rm -rf libpcap
نحن الآن جاهزون لتجميع tcpsnitch
:
# First, let's fix the buggy `tcp.h` header from the NDK
sed -i 's/include <linux/tcp.h>/include <sys/cdefs.h>n#include <linux/tcp.h>/g' $TOOLCHAIN/sysroot/usr/include/netinet/tcp.h
# Configure the compiler
export CC_ANDROID=$TOOLCHAIN/bin/arm-linux-androideabi-gcc
# Build & install tcpsnitch
make android && sudo make install
أنت على استعداد للذهاب! راجع قسم استخدام Android لمعرفة كيفية بدء تتبع التطبيقات.
إحدى الميزات المثيرة للاهتمام في رابط Linux الديناميكي ( ld.so
) هي القدرة على ربط المكتبات المشتركة المحددة بواسطة المستخدم قبل المكتبات المحددة في قائمة تبعيات البرنامج. يمكن التحكم في هذه الميزة باستخدام متغير البيئة LD_PRELOAD
الذي يحتوي على قائمة (ربما فارغة) من المكتبات الإضافية المحددة من قبل المستخدم. على وجه الخصوص، قد يجبر متغير LD_PRELOAD
هذا الرابط الديناميكي على ربط مكتبة مشتركة محددة من قبل المستخدم قبل مكتبة libc
. ونتيجة لذلك، أي وظيفة محددة في هذه المكتبة المحددة من قبل المستخدم لها الأسبقية على وظيفة بنفس التوقيع المحدد في libc
.
المعنى الضمني هنا هو أنه يسمح باعتراض المكالمات إلى وظائف مجمع مكالمات النظام. يتعين علينا فقط إضافة مكتبة مشتركة مخصصة تعيد تعريف وظائف أغلفة مكالمات النظام هذه إلى LD_PRELOAD
. تقوم مكتبة الرقائق هذه بعد ذلك باعتراض استدعاءات دالة libc
بشفافية وإجراء بعض المعالجة قبل استدعاء وظائف غلاف libc
الأصلية.
wrong ELF class
؟ لا شيء سيئ، هذه يمكن تجاهلها. تم تجميع مكتبة tcpsnitch
المشتركة لكل من معماريتي 32 بت و64 بت. عند تتبع أمر ما، يتم تحميل كلا المكتبتين في متغير البيئة LD_PRELOAD
نظرًا لعدم وجود طريقة سهلة لمعرفة بنية الأمر الثنائي (غالبًا ما يكون برنامج نصي shell ينفذ ثنائيًا آخر). يتولى الرابط الديناميكي بعد ذلك تحميل المكتبة المتوافقة ويتجاهل المكتبة الثانية (لكنه لا يزال يلقي خطأ).
تعال وناقش حول tcpsnitch
على https://gitter.im/Tcpsnitch.
البريد الإلكتروني للمؤلف هو gregory.vanderschueren[at]gmail.com