来自字符串的Python3 Scapy自定义有效载荷

时间:2020-06-29 16:05:21

标签: python-3.x network-programming scapy

简介

我正在使用python3和scapy修改并重新发送捕获的数据包。

问题

当我在Raw部分中发送修改后的有效负载时,消息的\ r和\ n部分不会被解释为特殊字符。而是将它们作为字符串包含在内,如下面的cmd和wirehark屏幕截图所示。

当前有效载荷

Cmd wrong payload screenshot Wireshark wrong payload screenshot

预期有效载荷

这是网络上捕获的正确数据包格式。 Wireshark correct payload description

wireshark中显示的数据包如下:

SIP / 2.0 486繁忙在这里 通过:SIP / 2.0 / UDP 192.168.1.5:5060;分支= z9hG4bK226016822;已接收= 192.168.1.5;端口= 5060 来自:sip:301@192.168.1.2; tag = 2032604445 至:sip:300@192.168.1.2; tag = as1b0290be 呼叫ID:338695025 CSeq:21邀请 伺服器:Asterisk PBX 16.10.0 允许:邀请,确认,取消,选项,再见,推荐,订阅,通知,信息,出版物,消息 支持:替换,计时器 X-Asterisk-Hangup原因:通话被拒 X-Asterisk-HangupCauseCode:21 内容长度:0

代码

这是到目前为止的代码:

from scapy.all import sniff, Ether, IP, UDP, sendp, ICMP, rdpcap,Raw
import scapy.fields
import re
import codecs
import argparse

def traffic_parser(packet):
    BUSY_1 = 'SIP/2.0 486 Busy Here'
    BUSY_2 = 'X-Asterisk-HangupCause: Call Rejected\\\\r\\\\nX-Asterisk-HangupCauseCode: 21'

    payload = packet[3].command()
    print(bytes(payload))

    header=re.findall("Ringing", payload)
    if header:
        
        eth_attributes={}
        eth_attributes['dst']=packet[0].dst
        eth_attributes['src']=packet[0].src
        eth_attributes['type']=packet[0].type
        
        eth = Ether_layer(eth_attributes)


        udp_attributes={}
        udp_attributes['sport']=packet[2].sport
        udp_attributes['dport']=packet[2].dport
        udp_attributes['len']=444
    
        udp = UDP_layer(udp_attributes)

        # Implement packet modification
        payload = payload.replace("SIP/2.0 180 Ringing", BUSY_1, 1)
        payload = re.sub("Contact\:.*>", BUSY_2, payload,1)
        payload = payload.replace("Raw(load=b\'", '', 1)
        payload = re.sub("\'\)$", '', payload, 1)

        for incr in range(1,5):
            ip_attributes={}
            ip_attributes['version']=packet[1].version
            ip_attributes['tos']=packet[1].tos
            ip_attributes['len']=464 
            ip_attributes['id']=0 #Zero is handled by scapy on send by default
            ip_attributes['flags']=packet[1].flags
            ip_attributes['frag']=packet[1].frag
            ip_attributes['ttl']=packet[1].ttl
            ip_attributes['proto']=packet[1].proto
            ip_attributes['src']=packet[1].src
            ip_attributes['dst']=packet[1].dst

            ip = IP_layer(ip_attributes)

            sendp(eth/ip/udp/Raw(load=payload))

            print(payload)
            print(Raw(load=payload))
            print("\n")

def Ether_layer(attributes):
    layer2=Ether()
    layer2.dst=attributes['dst']
    layer2.src=attributes['src']
    layer2.type=attributes['type']

    return layer2


def IP_layer(attributes):
    layer3=IP()
    layer3.version=attributes['version']
    layer3.tos=attributes['tos']
    layer3.len=attributes['len']
    layer3.id=attributes['id']
    layer3.flags=attributes['flags']
    layer3.frag=attributes['frag']
    layer3.ttl=attributes['ttl']
    layer3.proto=attributes['proto']
    layer3.src=attributes['src']
    layer3.dst=attributes['dst']

    return layer3


def UDP_layer(attributes):
    layer4=UDP()
    layer4.sport=attributes['sport']
    layer4.dport=attributes['dport']
    layer4.len=attributes['len']

    return layer4


parser = argparse.ArgumentParser(description="rtp replay script. Arguments: -i <interface> -f <sniff filter> -o <sniff outputfile> Interface defaults to 'eth0' and filter defaults to 'udp and port 5060'")
parser.add_argument('-i', "--interface", default="eth0", help="interface to use for sniffing")
parser.add_argument('-f', '--filter', default="udp and port 5060", help="filter to be used in scapy")
parser.add_argument('-o', "--outfile", help="output file (optional)")
parser.add_argument('-t', "--testfile", help="parse test file (optional)")
args=parser.parse_args()

if __name__ == '__main__':

    if args.testfile:
        packets = rdpcap(args.testfile)
        for packet in packets:
            traffic_parser(packet)
    else:
        sniff(iface=args.interface, prn=traffic_parser, filter="udp and port 5060", store=0)

Q

如何以所需的形式附加有效载荷?

编辑:

此pcap文件可用于测试。 pcap_file

指示性脚本执行: 须藤python byespam.py -t

2 个答案:

答案 0 :(得分:1)

要想将有效负载用作字符串,您需要将其转换为一个,并确保您具有正确的编码。

在您的情况下,您应该:

  1. 您只能从scapy.packet.Packet中获取Raw的 load 部分。
  2. load 部分编码为UTF-8,以便Python正确解释特殊字符。

以下是一些适用于您的案例的代码:

payload = packet[UDP].payload.load *
payload = payload.decode("utf-8")

然后您可以打印有效载荷,它将被“正确地”解释。

*我使用UDP是因为在您的脚本和pcapng文件中,您只有UDP数据包。如果有TCP数据包,则应使用payload = packet[TCP].payload.load

答案 1 :(得分:-1)

\r\n被解释为文字字符串,因为您已对其进行了转义

这是您的字符串:

>>> BUSY_2 = 'X-Asterisk-HangupCause: Call Rejected\\\\r\\\\nX-Asterisk-HangupCauseCode: 21'
>>> print(BUSY_2)
X-Asterisk-HangupCause: Call Rejected\\r\\nX-Asterisk-HangupCauseCode: 21

这里是相同的字符串,但没有转义:

>>> BUSY_2 = 'X-Asterisk-HangupCause: Call Rejected\r\nX-Asterisk-HangupCauseCode: 21'
>>> print(BUSY_2)
X-Asterisk-HangupCause: Call Rejected
X-Asterisk-HangupCauseCode: 21