《自拍教程53》Python_adb运行tcpdump工具


本篇文章与上一篇: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种方式
融合方式 具体效果
显露式(低端) 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
也可关注“武散人”微信订阅号,随时接受文章推送。


作者:zipython,发布于:2020/04/05
原文:https://www.cnblogs.com/zipython/p/12636608.html