《自拍教程53》Python adb運行tcpdump工具

本篇文章與上一篇:Python_adb運行shell腳本類似
上一篇主要的技術點是講shell等文本文件,"隱藏"在Python代碼裏;
本篇文章主要是講,如何將tcpdump這類二進制可執行文件, “隱藏”到Python代碼裏去。

Android手機具備在線功能的應用程序,如果出現App無法連接網絡,
或者網絡異常等問題,開發一般需要測試同學抓包; 還有比如Android手機
流媒體協議(HTTP,HTTP Live, RTSP)測試等,開發也經常需要測試人員抓包。
Android的一般用tcpdump命令行工具抓包,
可是,有的Android是閹割版的,很多命令行工具都未集成,比如tcpdump如果沒有集成,
則要考慮adb push tcpdump /system/bin下面去,
然後通過/system/bin/tcpdump -vv -s 0 -w /sdcard/tcp.pcap 來抓包。
執行tcpdump不難,難在“隱藏”tcpdump到Python代碼裏去,
爲什麼要“隱藏”,因爲我們只能將.py代碼文件, 編譯打包進.exe裏去,
任何其他的格式的非代碼文件都是無法編譯打包進去,
所以先將tcpdump這個二進制文件轉成.py文件, 這樣就可以將tcpdump編譯打包進.exe。


tcpdump工具與Python的互相存在的2種方式
融合方式 具體效果
顯露式(低端) tcpdump工具和Python腳本都是獨立的文件,tcpdump工具顯露在外
—catch_tcpdump.py
—tcpdump
隱藏式(高端) 將tcpdump工具以文本的形式隱藏在Python代碼中
—catch_tcpdump.py
—tcpdump.py

二進制文件轉文本文件

lib64.encode()函數,可以將二進制文件(.exe, .jpg, .mp4,.docx有後綴或者無後綴的等等二進制文件)轉成文本文件(由ASCII碼組成的人力能看懂的英文字符)。

# coding=utf-8

import base64

bin_hf = open('tcpdump', 'rb')  # 二進制(帶了b,代表binary模式)讀取方式
text_hf = open("tcpdump.txt", "wb")  # 二進制(帶了b,代表binary模式)寫入方式

base64.encode(bin_hf, text_hf)  # 先將tcpdump這個二進制文件轉成字符串變量

bin_hf.close()
text_hf.close()

將以上tcpdump.txt裏的所有文本,copy下來賦值給tcpdump_bin字符串變量,
放到一個tcpdump.py文件裏去(這個文件比較大824kb,請下載本案例的素材自行查閱)

同樣的,lib64.decode()函數,可以將文本文件轉成二進制文件。
上一篇課程我們知道,文本文件的內容是可以很簡單“隱藏”在Python代碼塊裏的,
也就是說通過lib64模塊 + tempfile模塊,可以無感轉換成二進制文件,
綜上二進制文件也可以很簡單地實現“隱藏”到Python代碼塊裏去。


Python批處理腳本形式

以上生成的tcpdump.py是一個自定義模塊,需要import進來,
記住批處理腳本的精髓:批量順序執行語句。

# coding=utf-8

import os
import base64
import tempfile
import tcpdump

# 第一步:tcpdump文本文件轉tcpdump二進制
signal_1, text_file = tempfile.mkstemp()  # 創建第一個臨時文件

with open(text_file, "w") as hf:
    hf.write(tcpdump.tcpdump_bin)
text_hf = open(text_file, "rb")  # 二進制(帶了b,代表binary模式)讀取方式

signal_2, bin_file = tempfile.mkstemp()  # 創建第一個臨時文件
bin_hf = open(bin_file, 'wb')  # 二進制(帶了b,代表binary模式)寫入方式
base64.decode(text_hf, bin_hf)  # 先將tcpdump這個二進制文件轉成字符串變量

bin_hf.close()  # 關閉句柄
text_hf.close()  # 關閉句柄
os.close(signal_1)  # 臨時文件清理
os.close(signal_2)  # 臨時文件清理
os.remove(text_file)  # 臨時文件清理
print(bin_file)

# 第二步:運行tcpdump並截取log
os.system("adb root")
os.system("adb remount")
os.system("adb wait-for-device")
os.system("adb push %s /system/bin/tcpdump" % bin_file)  # 推臨時文件推到終端設備
os.system("adb shell chmod 777 /system/bin/tcpdump")  # 賦值777
os.popen("adb shell \"nohup /system/bin/tcpdump -vv -s 0 -w /sdcard/tcp.pcap &\"")  # 獨立後臺無干擾執行,popen不阻塞

# 第三步:清理
os.remove(bin_file)  # 臨時文件清理

os.system("pause")

Python面向過程函數形式

面向過程函數的編程思維應該是這樣的:
你需要多少個功能(函數),才能做成這個事。
最好把功能(函數)都儘量封裝好,只暴露一定的參數接口即可。

# coding=utf-8

import os
import base64
import tempfile
import tcpdump


def text_2_bin():
    '''tcpdump文本文件轉tcpdump二進制'''

    signal_1, text_file = tempfile.mkstemp()  # 創建第一個臨時文件
    with open(text_file, "w") as hf:
        hf.write(tcpdump.tcpdump_bin)
    text_hf = open(text_file, "rb")  # 二進制(帶了b,代表binary模式)讀取方式

    signal_2, bin_file = tempfile.mkstemp()  # 創建第一個臨時文件
    bin_hf = open(bin_file, 'wb')  # 二進制(帶了b,代表binary模式)寫入方式
    base64.decode(text_hf, bin_hf)  # 先將tcpdump這個二進制文件轉成字符串變量
    # 各種銷燬
    text_hf.close()
    bin_hf.close()
    os.close(signal_1)
    os.close(signal_2)
    os.remove(text_file)
    return bin_file


def catch_tcpdump(bin_file):
    '''運行tcpdump並截取log'''
    os.system("adb root")
    os.system("adb remount")
    os.system("adb wait-for-device")
    os.system("adb push %s /system/bin/tcpdump" % bin_file)  # 推臨時文件推到終端設備
    os.system("adb shell chmod 777 /system/bin/tcpdump")  # 賦值777
    os.popen("adb shell \"nohup /system/bin/tcpdump -vv -s 0 -w /sdcard/tcp.pcap &\"")  # 獨立後臺無干擾執行, popen不阻塞

bin_file = text_2_bin()
catch_tcpdump(bin_file)
os.remove(bin_file)  # 刪除臨時文件
os.system("pause")

Python面向對象類形式

面向對象類的編程思維應該是這樣的:
如果給你一個空白的世界,在這個世界裏你需要哪些種類的事物,
這些種類的事物都具備哪些共有的屬性與方法,
這些種類(類)的事物(對象),和其他種類(其他類)的事物(其他對象)有什麼關係。
儘量把這些類封裝好,只暴露對外的屬性(變量)和方法(函數)即可。

# coding=utf-8

import os
import base64
import tempfile
import tcpdump


class BinGenerator():
    def __init__(self, text):
        # 對外只暴露以下2個屬性即可
        self.text = text
        self.bin_file = None

    def text_2_bin(self):
        '''tcpdump文本文件轉tcpdump二進制'''

        signal_1, text_file = tempfile.mkstemp()  # 創建第一個臨時文件
        with open(text_file, "w") as hf:
            hf.write(self.text)
        text_hf = open(text_file, "rb")  # 二進制(帶了b,代表binary模式)讀取方式

        signal_2, self.bin_file = tempfile.mkstemp()  # 創建第一個臨時文件
        bin_hf = open(self.bin_file, 'wb')  # 二進制(帶了b,代表binary模式)寫入方式
        base64.decode(text_hf, bin_hf)  # 先將tcpdump這個二進制文件轉成字符串變

        # 各種銷燬
        text_hf.close()
        bin_hf.close()
        os.close(signal_1)
        os.close(signal_2)
        os.remove(text_file)
        return self.bin_file


def catch_tcpdump(bin_file):
    '''運行tcpdump並截取log'''
    os.system("adb root")
    os.system("adb remount")
    os.system("adb wait-for-device")
    os.system("adb push %s /system/bin/tcpdump" % bin_file)  # 推臨時文件推到終端設備
    os.system("adb shell chmod 777 /system/bin/tcpdump")  # 賦值777
    os.popen("adb shell \"nohup /system/bin/tcpdump -vv -s 0 -w /sdcard/tcp.pcap &\"")  # 獨立後臺無干擾執行,popen不阻塞


b_obj = BinGenerator(tcpdump.tcpdump_bin)
bin_file = b_obj.text_2_bin()
catch_tcpdump(bin_file)
os.remove(bin_file)  # 刪除臨時文件
os.system("pause")

本案例下載地址

跳轉至自拍教程官網下載


運行方式

確保Android設備通過USB線與電腦連接了,adb設備有效連接,
以上代碼的3種實現形式都可以直接運行,比如保存爲catch_tcpdump.py並放在桌面,
建議python catch_tcpdump.py運行,當然也可以雙擊運行。
本次我們也提供了已經編譯打包好了的catch_tcpdump.exe, 直接雙擊運行效果一樣。


顯露式與隱藏式的對比

隱藏式最後通過py2exe編譯打包後,只有一個catch_tcpdump.exe,
而顯露式還有額外的一個tcpdump文件必須附帶。


更多更好的原創文章,請訪問官方網站:www.zipython.com
自拍教程(自動化測試Python教程,武散人編著)
原文鏈接:https://www.zipython.com/#/detail?id=c68aae803360428f9ac87b1c99ff65da
也可關注“武散人”微信訂閱號,隨時接受文章推送。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章