本篇文章與上一篇: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
也可關注“武散人”微信訂閱號,隨時接受文章推送。