#Summary AndroidNetMonitor is a system for passive monitoring, collection and analysis of fine-grained, large-scale packet measurements from Android devices.用於獲取流量來源的真實應用程式資訊,擷取手機發送和接收的封包簡要資訊(即來源IP、來源連接埠、目標IP、目標連接埠和傳輸層協定),並且根據socket記錄每個封包對應哪個手機app,這些資料都以檔案方式儲存在手機的SD卡上。
文件的每一行需要記錄的資訊包括:每個網路套接字的5元組資訊(即來源IP、來源連接埠、目標IP、目標連接埠和傳輸層協定)、記錄時間、應用程式名稱、已及對應事件(創建/銷毀套接字等)。
#Technology 1.將tcpdump,lsof重新編譯成適用於安卓的二進位(arm-linux-androideabi-g++)
2.用Adapter將Listview,CheckBox與List<Program(自訂類別)>綁定
3.並發運行抓取Socket與Packet,使用lsof +c 0 -i -F ctPnf 2>&1
與tcpdump -v -s -w pcap
指令
4.讀取與解析/proc/net/tcp, tcp6,udp,udp6
文件, 利用socket inode以及app的pid建立起五元組與應用名稱的取得與對應關係
#Implementation (1) app列表的取得利用PackageManager管理器,檢索所有的應用程式與數據,再用ActivityManager與PackagesInfo取得從上得到的所有app名稱以及pid,並且使用listview佈局展示出來。
(2) /proc/pid/fd檔的讀取和解析在安卓中,使用runTime.exec(cmd);可以在android裡運行cmd的命令,所以可以通過這個來獲取運行命令後的結果輸出. 因為/proc目錄的讀取與分析需要用到root權限,所以使用了runTime.exec(“su”);在安卓上提取root權限。 然後使用ls -l /proc/(pid)/fd > /sdcard/fdres
將資訊儲存到fdres這個檔案中,再使用cat /sdcard/fdres 提取資訊這個折衷的辦法。 在得到的資訊中,使用"socket:\S(\d+)\S"
;的正規表示式,把socket的所有inode標號都抽取出來,放到ArrayList中。
(3) /proc/net/tcp, tcp6,udp,udp6檔案的讀取與解析(或使用lsof +c 0 -i -F ctPnf 2>&1
指令) 抽象讀取tcp, tcp6,udp,udp6為PollData類,使用java自帶的Scanner類去分析讀取/proc/net/tcp等,得到的輸出如下
* sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid ...
* 0: 0100007F:13AD 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 ...
* 1: 00000000:15B3 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 ...
* 2: 0F02000A:15B3 0202000A:CE8A 01 00000000:00000000 00:00000000 00000000 0 ...
*
再使用由上得到的socket_inode在得到的資訊中找出對應的具體信息,轉換成10進制得到的具體socket信息如下:
1.
2. 46: 010310AC:9C4C 030310AC:1770 01
3. | | | | | |--> connection state
4. | | | | |------> remote TCP port number
5. | | | |-------------> remote IPv4 address
6. | | |--------------------> local TCP port number
7. | |---------------------------> local IPv4 address
8. |----------------------------------> number of entry
9. 00000150:00000000 01:00000019 00000000
10. | | | | |--> number of unrecovered RTO timeouts
11. | | | |----------> number of jiffies until timer expires
12. | | |----------------> timer_active (see below)
13. | |----------------------> receive-queue
14. |-------------------------------> transmit-queue
15. 1000 0 54165785 4 cd1e6040 25 4 27 3 -1
16. | | | | | | | | | |--> slow start size threshold,
17. | | | | | | | | | or -1 if the threshold
18. | | | | | | | | | is >= 0xFFFF
19. | | | | | | | | |----> sending congestion window
20. | | | | | | | |-------> (ack.quick<<1)|ack.pingpong
21. | | | | | | |---------> Predicted tick of soft clock
22. | | | | | | (delayed ACK control data)
23. | | | | | |------------> retransmit timeout
24. | | | | |------------------> location of socket in memory
25. | | | |-----------------------> socket reference count
26. | | |-----------------------------> inode
27. | |----------------------------------> unanswered 0-window probes
28. |---------------------------------------------> uid
(4) 五元組與應用程式名稱的取得和對應關係建立由(2),(3)所共有的socket inode以及app的pid建立起五元組與應用名稱的獲取和對應關係,將獲取到的資訊儲存到預設的目錄/sdcard/Android/data/com.xx的目錄下, 格式為
"The application name is, pid is, and socket is:"
"number_of_entry "+fields[i+0] + "n";
"local_IPv4_address "+fields[i+1] + "n";
"local_IPv4_address "+hexconvert.hexa2decIpAndPort(fields[i+1]) + "n";
"remote_IPv4_address "+fields[i+2] + "n";
"remote_IPv4_address "+hexconvert.hexa2decIpAndPort(fields[i+2]) + "n";
"connection_state" + fields[i+3] + "n";
"transmit_receive_queue"+ fields[i+4]+ "n";
"timer_active"+fields[i+5]+ "n";
"number_of_unrecovered_RTO_timeouts:"+fields[i+6]+ "n";
"uid: "+fields[i+7]+ "n";
"unanswered_0-window_probes: "+fields[i+8]+ "n";
"inode : "+fields[i+9]+ "n";
"socket_reference_count: "+fields[i+10]+ "n";
"location_of_socket_in_memory: "+fields[i+11]+ "n";
"retransmit_timeout: "+fields[i+12]+ "n";
"predicted_tick_of_soft_clock: "+ fields[i+13]+ "n";
"ack"+ fields[i+14]+ "n";
"sending_congestion_window: "+ fields[i+15]+ "n";
"slowstart: "+ fields[i+16]+ "nn";
(5)上傳至伺服器, 使用GT ProgramPython腳本解析