scapyppp

How to send packet through ppp link by Scapy


I'm trying to send packets through ppp link (created by wvdial connecting a 3g modem) but failing so far. Here is my 'ip addr' printout:

22: ppp0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 3
    link/ppp
    inet 10.40.43.62 peer 10.64.64.64/32 scope global ppp0
       valid_lft forever preferred_lft forever*

And this is how i'm trying to send by Scapy:

[root@server1 ~]# scapy
INFO: Can't import matplotlib. Won't be able to plot.
INFO: Can't import PyX. Won't be able to use psdump() or pdfdump().
WARNING: No route found for IPv6 destination :: (no default route?)
INFO: Can't import python ecdsa lib. Disabled certificate manipulation tools
Welcome to Scapy (2.3.3)
>>> pkt=PPP()/IP(src="10.40.43.62", dst="8.8.8.8")/ICMP()/"1234567890"
>>> pkt.show()
###[ PPP Link Layer ]###
  proto= Internet Protocol version 4
###[ IP ]###
     version= 4
     ihl= None
     tos= 0x0
     len= None
     id= 1
     flags=
     frag= 0
     ttl= 64
     proto= icmp
     chksum= None
     src= 10.40.43.62
     dst= 8.8.8.8
     \options\
###[ ICMP ]###
        type= echo-request
        code= 0
        chksum= None
        id= 0x0
        seq= 0x0
###[ Raw ]###
           load= '1234567890'

>>> sendp(pkt, iface="ppp0")
.
Sent 1 packets.
>>> quit()

packet capture is showing Ethernet layer is getting added:

[root@server1 ~]# tshark -V -i ppp0 
Running as user "root" and group "root". This could be dangerous. Capturing on 'ppp0' Frame 1: 56 bytes on wire (448 bits), 56 bytes captured (448 bits) on interface 0
    Interface id: 0
    Encapsulation type: Linux cooked-mode capture (25)
    Arrival Time: Jan 29, 2018 10:54:20.793541000 BDT
    [Time shift for this packet: 0.000000000 seconds]
    Epoch Time: 1517201660.793541000 seconds
    [Time delta from previous captured frame: 0.000000000 seconds]
    [Time delta from previous displayed frame: 0.000000000 seconds]
    [Time since reference or first frame: 0.000000000 seconds]
    Frame Number: 1
    Frame Length: 56 bytes (448 bits)
    Capture Length: 56 bytes (448 bits)
    [Frame is marked: False]
    [Frame is ignored: False]
    [Protocols in frame: sll:eth:data] Linux cooked capture
    Packet type: Sent by us (4)
    Link-layer address type: 512
    Link-layer address length: 0
    Protocol: Ethernet (0x0003) Ethernet II, Src: EquipTra_00:40:01 (00:01:00:00:40:01), Dst: Semptian_00:00:26 (00:21:45:00:00:26)
    Destination: Semptian_00:00:26 (00:21:45:00:00:26)
        Address: Semptian_00:00:26 (00:21:45:00:00:26)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Source: EquipTra_00:40:01 (00:01:00:00:40:01)
        Address: EquipTra_00:40:01 (00:01:00:00:40:01)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Type: Unknown (0x3561) Data (26 bytes)

0000  0a 28 2b 3e 08 08 08 08 08 00 ed fa 00 00 00 00   .(+>............ 0010  31 32 33 34 35 36 37 38 39 30                   1234567890
    Data: 0a282b3e080808080800edfa000000003132333435363738...
    [Length: 26]

is send/sendp/sr are right command for this, what i am missing here? i can send ping through the ppp interface and in the packet capture it shows as ppp link layer.

this is the packet capture of scapy crafted packet and normal ICMP packet from ping tool

Normal:

12 <packet>
  <proto name="geninfo" pos="0" showname="General information" size="100">
    <field name="num" pos="0" show="13" showname="Number" value="d" size="100"/>
    <field name="len" pos="0" show="100" showname="Frame Length" value="64" size="100"/>
    <field name="caplen" pos="0" show="100" showname="Captured Length" value="64" size="100"/>
    <field name="timestamp" pos="0" show="Jan 31, 2018 00:47:08.960176000 BDT" showname="Captured Time" value="1517338028.960176000" size="100"/>
  </proto>
  <proto name="frame" showname="Frame 13: 100 bytes on wire (800 bits), 100 bytes captured (800 bits) on interface 0" size="100" pos="0">
    <field name="frame.interface_id" showname="Interface id: 0" size="0" pos="0" show="0"/>
    <field name="frame.encap_type" showname="Encapsulation type: Linux cooked-mode capture (25)" size="0" pos="0" show="25"/>
    <field name="frame.time" showname="Arrival Time: Jan 31, 2018 00:47:08.960176000 BDT" size="0" pos="0" show="Jan 31, 2018 00:47:08.960176000"/>
    <field name="frame.offset_shift" showname="Time shift for this packet: 0.000000000 seconds" size="0" pos="0" show="0.000000000"/>
    <field name="frame.time_epoch" showname="Epoch Time: 1517338028.960176000 seconds" size="0" pos="0" show="1517338028.960176000"/>
    <field name="frame.time_delta" showname="Time delta from previous captured frame: 50.679499000 seconds" size="0" pos="0" show="50.679499000"/>
    <field name="frame.time_delta_displayed" showname="Time delta from previous displayed frame: 50.679499000 seconds" size="0" pos="0" show="50.679499000"/>
    <field name="frame.time_relative" showname="Time since reference or first frame: 196.152414000 seconds" size="0" pos="0" show="196.152414000"/>
    <field name="frame.number" showname="Frame Number: 13" size="0" pos="0" show="13"/>
    <field name="frame.len" showname="Frame Length: 100 bytes (800 bits)" size="0" pos="0" show="100"/>
    <field name="frame.cap_len" showname="Capture Length: 100 bytes (800 bits)" size="0" pos="0" show="100"/>
    <field name="frame.marked" showname="Frame is marked: False" size="0" pos="0" show="0"/>
    <field name="frame.ignored" showname="Frame is ignored: False" size="0" pos="0" show="0"/>
    <field name="frame.protocols" showname="Protocols in frame: sll:ip:icmp:data" size="0" pos="0" show="sll:ip:icmp:data"/>
  </proto>
  <proto name="sll" showname="Linux cooked capture" size="16" pos="0">
    <field name="sll.pkttype" showname="Packet type: Sent by us (4)" size="2" pos="0" show="4" value="0004"/>
    <field name="sll.hatype" showname="Link-layer address type: 512" size="2" pos="2" show="512" value="0200"/>
    <field name="sll.halen" showname="Link-layer address length: 0" size="2" pos="4" show="0" value="0000"/>
    <field name="sll.etype" showname="Protocol: IP (0x0800)" size="2" pos="14" show="0x0800" value="0800"/>
  </proto>
  <proto name="ip" showname="Internet Protocol Version 4, Src: 10.93.65.103 (10.93.65.103), Dst: 8.8.8.8 (8.8.8.8)" size="20" pos="16">
    <field name="ip.version" showname="Version: 4" size="1" pos="16" show="4" value="45"/>
    <field name="ip.hdr_len" showname="Header length: 20 bytes" size="1" pos="16" show="20" value="45"/>
    <field name="ip.dsfield" showname="Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00: Not-ECT (Not ECN-Capable Transport))" size="1" pos="17" show="0" value="00">
      <field name="ip.dsfield.dscp" showname="0000 00.. = Differentiated Services Codepoint: Default (0x00)" size="1" pos="17" show="0x00" value="0" unmaskedvalue="00"/>
      <field name="ip.dsfield.ecn" showname=".... ..00 = Explicit Congestion Notification: Not-ECT (Not ECN-Capable Transport) (0x00)" size="1" pos="17" show="0x00" value="0" unmaskedvalue="00"/>
    </field>
    <field name="ip.len" showname="Total Length: 84" size="2" pos="18" show="84" value="0054"/>
    <field name="ip.id" showname="Identification: 0x0ea5 (3749)" size="2" pos="20" show="0x0ea5" value="0ea5"/>
    <field name="ip.flags" showname="Flags: 0x02 (Don&apos;t Fragment)" size="1" pos="22" show="0x02" value="40">
      <field name="ip.flags.rb" showname="0... .... = Reserved bit: Not set" size="1" pos="22" show="0" value="40"/>
      <field name="ip.flags.df" showname=".1.. .... = Don&apos;t fragment: Set" size="1" pos="22" show="1" value="40"/>
      <field name="ip.flags.mf" showname="..0. .... = More fragments: Not set" size="1" pos="22" show="0" value="40"/>
    </field>
    <field name="ip.frag_offset" showname="Fragment offset: 0" size="2" pos="22" show="0" value="4000"/>
    <field name="ip.ttl" showname="Time to live: 64" size="1" pos="24" show="64" value="40"/>
    <field name="ip.proto" showname="Protocol: ICMP (1)" size="1" pos="25" show="1" value="01"/>
    <field name="ip.checksum" showname="Header checksum: 0xd030 [correct]" size="2" pos="26" show="0xd030" value="d030">
      <field name="ip.checksum_good" showname="Good: True" size="2" pos="26" show="1" value="d030"/>
      <field name="ip.checksum_bad" showname="Bad: False" size="2" pos="26" show="0" value="d030"/>
    </field>
    <field name="ip.src" showname="Source: 10.93.65.103 (10.93.65.103)" size="4" pos="28" show="10.93.65.103" value="0a5d4167"/>
    <field name="ip.addr" showname="Source or Destination Address: 10.93.65.103 (10.93.65.103)" hide="yes" size="4" pos="28" show="10.93.65.103" value="0a5d4167"/>
    <field name="ip.src_host" showname="Source Host: 10.93.65.103" hide="yes" size="4" pos="28" show="10.93.65.103" value="0a5d4167"/>
    <field name="ip.host" showname="Source or Destination Host: 10.93.65.103" hide="yes" size="4" pos="28" show="10.93.65.103" value="0a5d4167"/>
    <field name="ip.dst" showname="Destination: 8.8.8.8 (8.8.8.8)" size="4" pos="32" show="8.8.8.8" value="08080808"/>
    <field name="ip.addr" showname="Source or Destination Address: 8.8.8.8 (8.8.8.8)" hide="yes" size="4" pos="32" show="8.8.8.8" value="08080808"/>
    <field name="ip.dst_host" showname="Destination Host: 8.8.8.8" hide="yes" size="4" pos="32" show="8.8.8.8" value="08080808"/>
    <field name="ip.host" showname="Source or Destination Host: 8.8.8.8" hide="yes" size="4" pos="32" show="8.8.8.8" value="08080808"/>
  </proto>
  <proto name="icmp" showname="Internet Control Message Protocol" size="64" pos="36">
    <field name="icmp.type" showname="Type: 8 (Echo (ping) request)" size="1" pos="36" show="8" value="08"/>
    <field name="icmp.code" showname="Code: 0" size="1" pos="37" show="0" value="00"/>
    <field name="icmp.checksum" showname="Checksum: 0x5b93 [correct]" size="2" pos="38" show="0x5b93" value="5b93"/>
    <field name="icmp.checksum_bad" showname="Bad Checksum: False" hide="yes" size="2" pos="38" show="0" value="5b93"/>
    <field name="icmp.ident" showname="Identifier (BE): 4058 (0x0fda)" size="2" pos="40" show="4058" value="0fda"/>
    <field name="icmp.ident" showname="Identifier (LE): 55823 (0xda0f)" size="2" pos="40" show="55823" value="0fda"/>
    <field name="icmp.seq" showname="Sequence number (BE): 1 (0x0001)" size="2" pos="42" show="1" value="0001"/>
    <field name="icmp.seq_le" showname="Sequence number (LE): 256 (0x0100)" size="2" pos="42" show="256" value="0001"/>
    <field name="icmp.data_time" showname="Timestamp from icmp data: Jan 31, 2018 00:47:08.000000000 BDT" size="8" pos="44" show="Jan 31, 2018 00:47:08.000000000" value="acbd705a00000000"/>
    <field name="icmp.data_time_relative" showname="Timestamp from icmp data (relative): 0.960176000 seconds" size="8" pos="44" show="0.960176000" value="acbd705a00000000"/>
    <field name="data" value="a2a60e0000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637">
      <field name="data.data" showname="Data: a2a60e0000000000101112131415161718191a1b1c1d1e1f..." size="48" pos="52" show="a2:a6:0e:00:00:00:00:00:10:11:12:13:14:15:16:17:18:19:1a:1b:1c:1d:1e:1f:20:21:22:23:24:25:26:27:28:29:2a:2b:2c:2d:2e:2f:30:31:32:33:34:35:36:37" value="a2a60e0000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637"/>
      <field name="data.len" showname="Length: 48" size="0" pos="52" show="48"/>
    </field>
  </proto>
</packet>

Scapy Crafted:

9 <packet>
  <proto name="geninfo" pos="0" showname="General information" size="54">
    <field name="num" pos="0" show="10" showname="Number" value="a" size="54"/>
    <field name="len" pos="0" show="54" showname="Frame Length" value="36" size="54"/>
    <field name="caplen" pos="0" show="54" showname="Captured Length" value="36" size="54"/>
    <field name="timestamp" pos="0" show="Jan 31, 2018 00:45:47.650839000 BDT" showname="Captured Time" value="1517337947.650839000" size="54"/>
  </proto>
  <proto name="frame" showname="Frame 10: 54 bytes on wire (432 bits), 54 bytes captured (432 bits) on interface 0" size="54" pos="0">
    <field name="frame.interface_id" showname="Interface id: 0" size="0" pos="0" show="0"/>
    <field name="frame.encap_type" showname="Encapsulation type: Linux cooked-mode capture (25)" size="0" pos="0" show="25"/>
    <field name="frame.time" showname="Arrival Time: Jan 31, 2018 00:45:47.650839000 BDT" size="0" pos="0" show="Jan 31, 2018 00:45:47.650839000"/>
    <field name="frame.offset_shift" showname="Time shift for this packet: 0.000000000 seconds" size="0" pos="0" show="0.000000000"/>
    <field name="frame.time_epoch" showname="Epoch Time: 1517337947.650839000 seconds" size="0" pos="0" show="1517337947.650839000"/>
    <field name="frame.time_delta" showname="Time delta from previous captured frame: 41.557182000 seconds" size="0" pos="0" show="41.557182000"/>
    <field name="frame.time_delta_displayed" showname="Time delta from previous displayed frame: 41.557182000 seconds" size="0" pos="0" show="41.557182000"/>
    <field name="frame.time_relative" showname="Time since reference or first frame: 114.843077000 seconds" size="0" pos="0" show="114.843077000"/>
    <field name="frame.number" showname="Frame Number: 10" size="0" pos="0" show="10"/>
    <field name="frame.len" showname="Frame Length: 54 bytes (432 bits)" size="0" pos="0" show="54"/>
    <field name="frame.cap_len" showname="Capture Length: 54 bytes (432 bits)" size="0" pos="0" show="54"/>
    <field name="frame.marked" showname="Frame is marked: False" size="0" pos="0" show="0"/>
    <field name="frame.ignored" showname="Frame is ignored: False" size="0" pos="0" show="0"/>
    <field name="frame.protocols" showname="Protocols in frame: sll:data" size="0" pos="0" show="sll:data"/>
  </proto>
  <proto name="sll" showname="Linux cooked capture" size="16" pos="0">
    <field name="sll.pkttype" showname="Packet type: Sent by us (4)" size="2" pos="0" show="4" value="0004"/>
    <field name="sll.hatype" showname="Link-layer address type: 512" size="2" pos="2" show="512" value="0200"/>
    <field name="sll.halen" showname="Link-layer address length: 0" size="2" pos="4" show="0" value="0000"/>
    <field name="sll.ltype" showname="Protocol: Unknown (0x0000)" size="2" pos="14" show="0x0000" value="0000"/>
  </proto>
  <proto name="fake-field-wrapper">
    <field name="data" value="0021450000240001000040011f050a5d4167080808080800272b000000003132333435363738">
      <field name="data.data" showname="Data: 0021450000240001000040011f050a5d4167080808080800..." size="38" pos="16" show="00:21:45:00:00:24:00:01:00:00:40:01:1f:05:0a:5d:41:67:08:08:08:08:08:00:27:2b:00:00:00:00:31:32:33:34:35:36:37:38" value="0021450000240001000040011f050a5d4167080808080800272b000000003132333435363738"/>
      <field name="data.len" showname="Length: 38" size="0" pos="16" show="38"/>
  </field>
</proto>
</packet>

Solution

  • You should first capture a packet with both Scapy and tshark and see how they look like. Then, try to mimic this packet, send it back (at first, you can try to send the exact packet as you received it) and see how tshark sees it.

    An option if that fails is to leave the PPP layer to the host's network stack and use sr(IP()[...]) rather than srp(PPP()/IP()) and see if that works. For that, you need to check that the route to your IP destination uses the PPP interface (use conf.route.route("[IP address]") to be sure).

    Regarding why sendp does not work, I think this might be a bug in Scapy. If you are using Linux, could you get the current development version, apply the following patch and try again?

    diff --git a/scapy/arch/linux.py b/scapy/arch/linux.py
    index b451fd15..4ad3c82f 100644
    --- a/scapy/arch/linux.py
    +++ b/scapy/arch/linux.py
    @@ -491,7 +491,7 @@ class L3PacketSocket(SuperSocket):
    
     class L2Socket(SuperSocket):
         desc = "read/write packets at layer 2 using Linux PF_PACKET sockets"
    -    def __init__(self, iface=None, type=ETH_P_ALL, promisc=None, filter=None, nofilter=0):
    +    def __init__(self, iface=None, type=0, promisc=None, filter=None, nofilter=0):
             self.iface = conf.iface if iface is None else iface
             self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
             self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 0)
    @@ -555,7 +555,7 @@ class L2Socket(SuperSocket):
    
     class L2ListenSocket(SuperSocket):
         desc = "read packets at layer 2 using Linux PF_PACKET sockets"
    -    def __init__(self, iface = None, type = ETH_P_ALL, promisc=None, filter=None, nofilter=0):
    +    def __init__(self, iface=None, type=0, promisc=None, filter=None, nofilter=0):
             self.type = type
             self.outs = None
             self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))