本篇文章与上一篇:Python_adb运行shell脚本类似,
上一篇主要的技术点是讲shell等文本文件,"隐藏"在Python代码里;
本篇文章主要是讲,如何将tcpdump这类二进制可执行文件, “隐藏”到Python代码里去。
::: story 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种方式
table.dataframe {
font-family: verdana,arial,sans-serif;
font-size:13px;
color:#333333;
border-width: 1px;
border-color: #999999;
border-collapse: collapse;
width:80%;
}
table.dataframe th {
background-color:#c3dde0;
border-width: 1px;
padding: 8px;
border-style: solid;
border-color: #a9c6c9;
text-align:center;
}
table.dataframe tr {
background-color:whit;
}
table.dataframe td {
border-width: 1px;
padding: 8px;
border-style: solid;
border-color: #a9c6c9;
text-align:left;
}
融合方式 | 具体效果 |
---|---|
显露式(低端) | 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
也可关注“武散人”微信订阅号,随时接受文章推送。
原文地址:https://www.cnblogs.com/zipython/p/12636608.html