packets manipulation in Python
developed by Philippe Biondi, since 2003
native support on Linux, macOS & *BSD
libpcap
& npcap.dll
Python3 compatible since 2018
PyPI downloads
GiHub
Python versions
It is as simple as cloning the git repository:
git clone --depth 1 https://github.com/secdev/scapy
cd scapy
sudo ./run_scapy
aSPY//YASa
apyyyyCY//////////YCa |
sY//////YSpcs scpCY//Pp | Welcome to Scapy
ayp ayyyyyyySCP//Pp syY//C | Version 2.4.3
AYAsAYYYYYYYY///Ps cY//S |
pCCCCY//p cSSps y//Y | https://github.com/secdev/scapy
SPPPP///a pP///AC//Y |
A//A cyP////C | Have fun!
p///Ac sC///a |
P////YCpc A//A | We are in France, we say Skappee.
scccccp///pSP///p p//Y | OK? Merci.
sY/////////y caa S//P | -- Sebastien Chabal
cayCyayP//Ya pY/Ya |
sY/PsY////YCc aC//Yp
sc sccaCY//PCypaapyCP//YSs
spCPY//////YPSps
ccaacs
using IPython 7.6.1
>>>
I will escort you in the discovery of most Scapy features:
/
operator is used to stack packetspacket = IP() / TCP()
Ether() / packet
<Ether type=IPv4 |<IP frag=0 proto=tcp |<TCP |>>>
ls()
function list packets fields>>> ls(IP, verbose=True)
version : BitField (4 bits) = (4)
ihl : BitField (4 bits) = (None)
tos : XByteField = (0)
len : ShortField = (None)
id : ShortField = (1)
flags : FlagsField (3 bits) = (<Flag 0 ()>)
MF, DF, evil
frag : BitField (13 bits) = (0)
ttl : ByteField = (64)
proto : ByteEnumField = (0)
chksum : XShortField = (None)
src : SourceIPField = (None)
dst : DestIPField = (None)
options : PacketListField = ([])
p = Ether() / IP(dst="www.secdev.org") / TCP(flags="F")
p.summary()
"Ether / IP / TCP 192.168.42.18:ftp_data > Net('www.secdev.org'):http F"
print(p.dst) # first layer with a dst field, i.e. Ether
print(p[IP].src) # explicit access to the IP layer src field
# sprintf() supports Scapy own formats strings
print(p.sprintf("%Ether.src% > %Ether.dst%\n%IP.src% > %IP.dst%"))
b8:26:6c:5f:4e:ee 192.168.42.18 b8:e8:56:45:8c:e6 > b8:26:6c:5f:4e:ee 192.168.42.18 > Net('www.secdev.org')
[p for p in IP(ttl=(1, 5)) / ICMP()] # a sequence of values from 1 to 5
[<IP frag=0 ttl=1 proto=icmp |<ICMP |>>, <IP frag=0 ttl=2 proto=icmp |<ICMP |>>, <IP frag=0 ttl=3 proto=icmp |<ICMP |>>, <IP frag=0 ttl=4 proto=icmp |<ICMP |>>, <IP frag=0 ttl=5 proto=icmp |<ICMP |>>]
[p for p in IP() / TCP(dport=[22, 80, 443])] # specific values
[<IP frag=0 proto=tcp |<TCP dport=ssh |>>, <IP frag=0 proto=tcp |<TCP dport=http |>>, <IP frag=0 proto=tcp |<TCP dport=https |>>]
sr1()
function sends a packet and returns a replyr = sr1(IP(dst="8.8.8.8") / UDP() / DNS(qd=DNSQR()))
r[DNS].an
Begin emission: Finished sending 1 packets. Received 2 packets, got 1 answers, remaining 0 packets
<DNSRR rrname='www.example.com.' type=A rclass=IN ttl=5868 rdlen=None rdata=93.184.216.34 |>
srp()
function sends a list of frames and returns two variables:r
a list of queries and matched answersu
a list of unanswered packetsr, u = srp(Ether() / IP(dst="8.8.8.8", ttl=(5, 10)) / UDP() / DNS(qd=DNSQR(qname="www.example.com")))
r, u
Begin emission: Finished sending 6 packets. Received 12 packets, got 6 answers, remaining 0 packets
(<Results: TCP:0 UDP:2 ICMP:4 Other:0>, <Unanswered: TCP:0 UDP:0 ICMP:0 Other:0>)
# Access the first tuple
print(r[0][0].summary()) # sent packet
print(r[0][1].summary()) # received packet
# Scapy received an ICMP time-exceeded
r[0][1][ICMP]
Ether / IP / UDP / DNS Qry "b'www.example.com'" Ether / IP / ICMP / IPerror / UDPerror / DNS Qry "b'www.example.com.'" / Padding
<ICMP type=time-exceeded code=ttl-zero-during-transit chksum=0xeff3 reserved=0 length=17 unused=None |<IPerror version=4 ihl=5 tos=0x0 len=61 id=1 flags= frag=0 ttl=1 proto=udp chksum=0xbee5 src=192.168.42.18 dst=8.8.8.8 |<UDPerror sport=domain dport=domain len=41 chksum=0xba0b |<DNS id=0 qr=0 opcode=QUERY aa=0 tc=0 rd=1 ra=0 z=0 ad=0 cd=0 rcode=ok qdcount=1 ancount=0 nscount=0 arcount=0 qd=<DNSQR qname='www.example.com.' qtype=A qclass=IN |> an=None ns=None ar=None |<Padding load='\x00\x00\x00\x00\x00\x00\x00' |>>>>>
PCAP
filewrpcap("scapy.pcap", r)
pcap_p = rdpcap("scapy.pcap")
pcap_p[0]
<Ether dst=b8:26:6c:5f:4e:ee src=b8:e8:56:45:8c:e6 type=IPv4 |<IP version=4 ihl=5 tos=0x0 len=61 id=1 flags= frag=0 ttl=5 proto=udp chksum=0xbae5 src=192.168.42.18 dst=8.8.8.8 |<UDP sport=domain dport=domain len=41 chksum=0xba0b |<DNS id=0 qr=0 opcode=QUERY aa=0 tc=0 rd=1 ra=0 z=0 ad=0 cd=0 rcode=ok qdcount=1 ancount=0 nscount=0 arcount=0 qd=<DNSQR qname='www.example.com.' qtype=A qclass=IN |> an=None ns=None ar=None |>>>>
command()
method gives the Python statement that will build the same objectpcap_p[0].command()
"Ether(dst='b8:26:6c:5f:4e:ee', src='b8:e8:56:45:8c:e6', type=2048)/IP(version=4, ihl=5, tos=0, len=61, id=1, flags=0, frag=0, ttl=5, proto=17, chksum=47845, src='192.168.42.18', dst='8.8.8.8')/UDP(sport=53, dport=53, len=41, chksum=47627)/DNS(length=None, id=0, qr=0, opcode=0, aa=0, tc=0, rd=1, ra=0, z=0, ad=0, cd=0, rcode=0, qdcount=1, ancount=0, nscount=0, arcount=0, qd=DNSQR(qname=b'www.example.com.', qtype=1, qclass=1), an=None, ns=None, ar=None)"
sniff()
function captures packets s = sniff(count=2)
s
<Sniffed: TCP:2 UDP:0 ICMP:0 Other:0>
sniff(count=2, prn=lambda p: p.summary())
Ether / IPv6 / ICMPv6ND_NS / ICMPv6 Neighbor Discovery Option - Source Link-Layer Address b8:e8:56:45:8c:e6 Ether / IPv6 / ICMPv6 Neighbor Discovery - Neighbor Advertisement (tgt: fe80::ba26:6cff:fe5f:4eee)
<Sniffed: TCP:0 UDP:0 ICMP:0 Other:2>
sniff(offline=IP(dst="8.8.8.8/24") / UDP(), filter="udp and dst host 8.8.8.8")
<Sniffed: TCP:0 UDP:1 ICMP:0 Other:0>
lsc()
function lists available commands >>> lsc()
IPID_count : Identify IP id values classes in a list of packets
arpcachepoison : Poison target's cache with (your MAC,victim's IP) couple
arping : Send ARP who-has requests to determine which hosts are up
arpleak : Exploit ARP leak flaws, like NetBSD-SA2017-002.
bind_layers : Bind 2 layers on some specific fields' values.
bridge_and_sniff : Forward traffic between interfaces if1 and if2, sniff and return
chexdump : Build a per byte hexadecimal representation
computeNIGroupAddr : Compute the NI group Address. Can take a FQDN as input parameter
corrupt_bits : Flip a given percentage or number of bits from a string
corrupt_bytes : Corrupt a given percentage or number of bytes from a string
defrag : defrag(plist) -> ([not fragmented], [defragmented],
defragment : defragment(plist) -> plist defragmented as much as possible
dhcp_request : Send a DHCP discover request and return the answer
[..]
# Send ARP who-has requests to determine which hosts are up
arping("192.168.42.0/24")
Begin emission: Finished sending 256 packets. Received 6 packets, got 5 answers, remaining 251 packets b8:26:6c:5f:4e:ee 192.168.42.1 54:64:d9:79:4e:00 192.168.42.3 70:ee:50:14:d7:70 192.168.42.29 24:5e:be:22:47:7f 192.168.42.42 38:de:ad:1f:b2:38 192.168.42.20
(<ARPing: TCP:0 UDP:0 ICMP:0 Other:5>, <Unanswered: TCP:0 UDP:0 ICMP:0 Other:251>)
help()
function describes commands behaviors and arguments>>> help(traceroute)
Help on function traceroute in module scapy.layers.inet:
traceroute(target, dport=80, minttl=1, maxttl=30, sport=<RandShort>, l4=None, filter=None, timeout=2, verbose=None, **kargs)
Instant TCP traceroute
:param target: hostnames or IP addresses
:param dport: TCP destination port (default is 80)
:param minttl: minimum TTL (default is 1)
:param maxttl: maximum TTL (default is 30)
:param sport: TCP source port (default is random)
:param l4: use a Scapy packet instead of TCP
:param filter: BPF filter applied to received packets
:param timeout: time to wait for answers (default is 2s)
:param verbose: detailed output
:return: an TracerouteResult, and a list of unanswered packets
srloop()
, send 100 packets to 8.8.8.8 and 8.8.4.4multiplot()
method can be used to display IP ID valuesans, unans = srloop(IP(dst=["8.8.8.8", "1.1.1.1"]) / ICMP(), inter=.1, timeout=.1, count=80, verbose=False)
%matplotlib inline
ans.multiplot(lambda x, y: (y[IP].src, (y.time, y[IP].id)), plot_xy=True)
[[<matplotlib.lines.Line2D at 0x11ab19a50>], [<matplotlib.lines.Line2D at 0x11ab0ff50>]]
raw()
function builds a packet, as sent on the networkpkt = IP() / UDP() / DNS(qd=DNSQR())
repr(raw(pkt))
"b'E\\x00\\x00=\\x00\\x01\\x00\\x00@\\x11|\\xad\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x005\\x005\\x00)\\xb6\\xd3\\x00\\x00\\x01\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x03www\\x07example\\x03com\\x00\\x00\\x01\\x00\\x01'"
This representation being complicated, Scapy can:
hexdump
of the contenthexdump(pkt)
0000 45 00 00 3D 00 01 00 00 40 11 7C AD 7F 00 00 01 E..=....@.|..... 0010 7F 00 00 01 00 35 00 35 00 29 B6 D3 00 00 01 00 .....5.5.)...... 0020 00 01 00 00 00 00 00 00 03 77 77 77 07 65 78 61 .........www.exa 0030 6D 70 6C 65 03 63 6F 6D 00 00 01 00 01 mple.com.....
pkt.show()
###[ IP ]### version = 4 ihl = None tos = 0x0 len = None id = 1 flags = frag = 0 ttl = 64 proto = udp chksum = None src = 127.0.0.1 dst = 127.0.0.1 \options \ ###[ UDP ]### sport = domain dport = domain len = None chksum = None ###[ DNS ]### id = 0 qr = 0 opcode = QUERY aa = 0 tc = 0 rd = 1 ra = 0 z = 0 ad = 0 cd = 0 rcode = ok qdcount = 1 ancount = 0 nscount = 0 arcount = 0 \qd \ |###[ DNS Question Record ]### | qname = 'www.example.com' | qtype = A | qclass = IN an = None ns = None ar = None
pkt.canvas_dump()
The traceroute()
functions calls sr(IP(ttl=(1,15))
and create the TracerouteResult
object
ans, unans = traceroute('www.secdev.org', maxttl=15)
Begin emission: Finished sending 15 packets. Received 20 packets, got 14 answers, remaining 1 packets 217.25.178.5:tcp80 1 192.168.42.1 11 3 193.253.82.102 11 4 193.252.159.153 11 5 193.252.137.78 11 6 130.117.15.233 11 7 154.25.7.150 11 8 154.25.4.254 11 9 149.6.166.166 11 10 217.25.178.5 SA 11 217.25.178.5 SA 12 217.25.178.5 SA 13 217.25.178.5 SA 14 217.25.178.5 SA 15 217.25.178.5 SA
%matplotlib inline
ans.world_trace()
[[<matplotlib.lines.Line2D at 0x7fb432ee41d0>]]
The make_table()
method provides a compact results representation, useful for a basic port scanner
targets = ["scanme.nmap.org", "nmap.org"]
ans = sr(IP(dst=targets) / TCP(dport=[22, 80, 443, 31337]), timeout=3, verbose=False)[0]
ans.extend(sr(IP(dst=targets) / UDP() / DNS(qd=DNSQR()), timeout=3, verbose=False)[0])
ans.make_table(lambda x, y: (x[IP].dst,
x.sprintf('%IP.proto%/{TCP:%r,TCP.dport%}{UDP:%r,UDP.dport%}'),
y.sprintf('{TCP:%TCP.flags%}{ICMP:%ICMP.type%}')))
45.33.32.156 45.33.49.119 tcp/22 SA SA tcp/31337 SA RA tcp/443 RA SA tcp/80 SA SA udp/53 dest-unreach -
Scapy can be used to build your own tools like ping6.py
:
import argparse
from scapy.all import *
parser = argparse.ArgumentParser(description="A simple ping6")
parser.add_argument("ipv6_host", help="An IPv6 address")
args = parser.parse_args()
print(sr1(IPv6(dst=args.ipv6_host) / ICMPv6EchoRequest(), verbose=0).summary())
sudo python ping6.py www.kame.net
IPv6 / ICMPv6 Echo Reply (id: 0x0 seq: 0x0)
To add new protocols, create an object:
Packet
fields_desc
variableclass DNSTCP(Packet):
name = "DNS over TCP"
fields_desc = [ FieldLenField("len", None, fmt="!H", length_of="dns"),
PacketLenField("dns", 0, DNS, length_from=lambda p: p.len)]
# This method tells Scapy to decode the payload with DNSTCP
def guess_payload_class(self, payload):
return DNSTCP
This new protocol can be directly used to build and parse a packet
DNSTCP(raw(DNSTCP(dns=DNS())))
<DNSTCP len=12 dns=<DNS id=0 qr=0 opcode=QUERY aa=0 tc=0 rd=1 ra=0 z=0 ad=0 cd=0 rcode=ok qdcount=0 ancount=0 nscount=0 arcount=0 |> |>
The StreamSocket
object allows Scapy to use a TCP socket
import socket
from scapy.all import *
sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # create a TCP socket
sck.connect(("8.8.8.8", 53)) # connect to 8.8.8.8 on 53/TCP
# Create a StreamSocket and define the default class
ssck = StreamSocket(sck)
ssck.basecls = DNSTCP
# Send the DNS query
ssck.sr1(DNSTCP(dns=DNS(qd=DNSQR(qname="www.example.com"))))
Begin emission: Finished sending 1 packets. Received 1 packets, got 1 answers, remaining 0 packets
<DNSTCP len=49 dns=<DNS id=0 qr=1 opcode=QUERY aa=0 tc=0 rd=1 ra=1 z=0 ad=0 cd=0 rcode=ok qdcount=1 ancount=1 nscount=0 arcount=0 qd=<DNSQR qname='www.example.com.' qtype=A qclass=IN |> an=<DNSRR rrname='www.example.com.' type=A rclass=IN ttl=5713 rdlen=None rdata=93.184.216.34 |> ns=None ar=None |> |>
Scapy can wait for a query, then send an answer with the AnsweringMachine
object.
Two methods are mandatory:
is_request()
: returns True
if the packet is the expected querymake_reply()
: returns the packet that will be sent by ScapyNote: in the following example, the Wi-Fi interface must be put in monitor mode
from scapy.all import *
# Specify the Wi-Fi interface
conf.iface = "mon0"
# Create the Answering Machine
class ProbeRequest_am(AnsweringMachine):
function_name = "pram"
mac = "00:11:22:33:44:55"
def is_request(self, pkt):
return Dot11ProbeReq in pkt
def make_reply(self, req):
rep = RadioTap()
# Note: depending on your Wi-Fi card, you might need something else than RadioTap()
rep /= Dot11(addr1=req.addr2, addr2=self.mac, addr3=self.mac, ID=RandShort(), SC=RandShort())
rep /= Dot11ProbeResp(cap="ESS", timestamp=int(time.time())
rep /= Dot11Elt(ID="SSID", info="Scapy !")
rep /= Dot11Elt(ID="Rates", info='\x82\x84\x0b\x16\x96')
rep /= Dot11Elt(ID="DSset", info=orb(10))
return rep
# Start the answering machine
#ProbeRequest_am()() # uncomment to test
sr1(IPv6() / ICMPv6ND_RS())
Begin emission: Finished sending 1 packets. Received 2 packets, got 1 answers, remaining 0 packets
<IPv6 version=6 tc=192 fl=0 plen=104 nh=ICMPv6 hlim=255 src=fe80::ba26:6cff:fe5f:4eee dst=ff02::1 |<ICMPv6ND_RA type=Router Advertisement code=0 cksum=0x4199 chlim=64 M=0 O=1 H=0 prf=High P=0 res=0 routerlifetime=600 reachabletime=0 retranstimer=0 |<ICMPv6NDOptPrefixInfo type=3 len=4 prefixlen=64 L=1 A=1 R=0 res1=0 validlifetime=0x708 preferredlifetime=0x258 res2=0x0 prefix=2a01:cb08:229:3700:: |<ICMPv6NDOptRDNSS type=25 len=3 res=0 lifetime=600 dns=[ fe80::ba26:6cff:fe5f:4eee ] |<ICMPv6NDOptDNSSL type=31 len=2 res=0 lifetime=600 searchlist=['home.'] |<ICMPv6NDOptMTU type=5 len=1 res=0x0 mtu=1500 |<ICMPv6NDOptSrcLLAddr type=1 len=1 lladdr=b8:26:6c:5f:4e:ee |>>>>>>>
a,u = sr(IPv6(dst="ff02::1") / ICMPv6EchoRequest(), multi=1, timeout=1)
a.make_table(lambda t: (t[0][IPv6].dst, t[1][IPv6].src, in6_addrtovendor(t[1][IPv6].src)))
Begin emission: Finished sending 1 packets. Received 6 packets, got 0 answers, remaining 1 packets
load_layer("tls")
cert_blackhat = Cert(pem2der(open("files/blackhat.com.pem", "rb").read())) # assuming you d/l the certificate
cert_blackhat
[X.509 Cert. Subject:/OU=PositiveSSL Multi-Domain/CN=ssl764995.cloudflaressl.com, Issuer:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO ECC Domain Validation Secure Server CA 2]
print(cert_blackhat.isSelfSigned()) # check if it is self signed
print(cert_blackhat.subject) # display the subject
print(cert_blackhat.remainingDays()) # compute the number of days until expiration
False {'organizationUnitName': 'PositiveSSL Multi-Domain', 'commonName': 'ssl764995.cloudflaressl.com'} 156.39600694444445
[e for e in cert_blackhat.tbsCertificate.extensions if e.extnID == "2.5.29.17"]
[<X509_Extension extnID=<ASN1_OID['subjectAltName']> critical=None extnValue=<X509_ExtSubjectAltName subjectAltName=[<X509_GeneralName generalName=<X509_DNSName dNSName=<ASN1_IA5_STRING[b'ssl764995.cloudflaressl.com']> |> |>, <X509_GeneralName generalName=<X509_DNSName dNSName=<ASN1_IA5_STRING[b'*.blackhat.com']> |> |>, <X509_GeneralName generalName=<X509_DNSName dNSName=<ASN1_IA5_STRING[b'blackhat.com']> |> |>] |> |>]
# Verify issuers signatures
cert_comodo = Cert(pem2der(open("files/comodo.pem", "rb").read())) # assuming you d/l the certificate
print(cert_blackhat.isIssuerCert(cert_comodo)) # check the signature
True
cert_blackhat.tbsCertificate.serialNumber.val = 0x42 # Change a value
private_key = PrivKeyRSA("files/private_key.pem") # Load a private key
new_cert_blackhat = private_key.resignCert(cert_blackhat) # Do a new signature
print(hex(new_cert_blackhat.tbsCertificate.serialNumber.val)) # Print the value
print(private_key.verifyCert(new_cert_blackhat)) # Verify the signature
0x42 True
load_layer("http")
req = HTTP() / HTTPRequest(
Accept_Encoding=b'gzip, deflate',
Cache_Control=b'no-cache',
Pragma=b'no-cache',
Connection=b'keep-alive',
Host=b'www.secdev.org',
)
t = TCP_client.tcplink(HTTP, "www.secdev.org", 80)
r = t.sr1(req, timeout=3)
Begin emission: Finished sending 1 packets. Received 1 packets, got 1 answers, remaining 0 packets
r[HTTPResponse].show()
###[ HTTP Response ]### Http_Version= 'HTTP/1.1' Status_Code= '200' Reason_Phrase= 'OK' Accept_Patch= None Accept_Ranges= 'bytes' Access_Control_Allow_Credentials= None Access_Control_Allow_Headers= None Access_Control_Allow_Methods= None Access_Control_Allow_Origin= None Access_Control_Expose_Headers= None Access_Control_Max_Age= None Age = None Allow = None Alt_Svc = None Cache_Control= None Connection= 'Keep-Alive' Content_Disposition= None Content_Encoding= 'gzip' Content_Language= None Content_Length= '5351' Content_Location= None Content_MD5= None Content_Range= None Content_Security_Policy= None Content_Type= 'text/html' Date = 'Thu, 25 Jul 2019 13:00:35 GMT' Delta_Base= None ETag = '"300a-56be3867f3785-gzip"' Expires = None IM = None Keep_Alive= 'timeout=5, max=100' Last_Modified= 'Fri, 11 May 2018 00:50:41 GMT' Link = None Location = None P3P = None Permanent = None Permanent = None Pragma = None Proxy_Authenticate= None Public_Key_Pins= None Refresh = None Retry_After= None Server = 'Apache' Set_Cookie= None Status = None Strict_Transport_Security= None Timing_Allow_Origin= None Tk = None Trailer = None Transfer_Encoding= None Upgrade = None Vary = 'Accept-Encoding' Via = '1.1 www.secdev.org' WWW_Authenticate= None Warning = None X_Content_Duration= None X_Content_Security_Policy= None X_Content_Type_Options= None X_Correlation_ID= None X_Frame_Options= None X_Powered_By= None X_Request_ID= None X_UA_Compatible= None X_WebKit_CSP= None X_XSS_Protection= None Unknown_Headers= None ###[ Raw ]### load = '<html>\n<head>\n<title>SecDev.org</title>\n</head>\n<body>\n<!--\n<a href="http://www.miscmag.com"><img border=0 height="100" src="misc_noir.png"></a>\n-->\n<H1>secdev</H1>\n\n\n\n\n<H4>Me</H4>\n<ul>\n<li> mail: phil<b></b>@<i></i>secdev<i></i>.<b></b>org</li>\n<li> <a href="phil.asc">PGP Key</a></li>\n<li> <a href="http://www.oreilly.com/catalog/9780596009632/"><img style="vertical-align:middle" height="30" border=0 alt="[Security Power Tools cover]" src="images/security_power_tools-cover.gif"> Security Power Tools</a> was out in August 2007.\n I wrote a complete chapter on <a href="projects/scapy/">Scapy</a> and one on shellcodes.</li>\n<form action="https://www.paypal.com/cgi-bin/webscr" method="post">\n<li> If you like what I do, you can \n<input type="hidden" name="cmd" value="_s-xclick">\n<input type="hidden" name="encrypted" value="-----BEGIN PKCS7-----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-----END PKCS7-----\n">\n<input style="vertical-align:middle" type="image" src="https://www.paypal.com/en_US/i/btn/btn_donate_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!">\n<img alt="" border="0" src="https://www.paypal.com/fr_FR/i/scr/pixel.gif" width="1" height="1">\n</form></li>\n</ul>\n\n\n\n<H4>Conferences</H4>\n<ul>\n<li><a href="http://www.osdem.org">OSDEM</a> : <a href="conf/osdem.pdf">Kernel security (Slides for OSDEM, Feb 2001)</a></li>\n<li><a href="http://www.fosdem.org">FOSDEM</a> : <a href="conf/ksecurity_en.pdf">Kernel security (Slides for FOSDEM, Feb 2002)</a></li>\n<li><a href="http://www.openweekend.cz/">OpenWeekend</a> : <a href="conf/ksec_openweekend.pdf">Slides</a> \n<li><a href="http://lsm.abul.org">LSM (RMLL)</a> : <a href="conf/ksec_lsm.pdf">Kernel security (Slides for LSM, July 2002)</a></li>\n<li><a href="http://www.defcon.org">DefCon X</a> : <a href="conf/ksec_defcon.pdf">Kernel security (Slides for DefCon 10, August 2002)</a></li>\n<li><a href="http://www.fosdem.org">FOSDEM 2003</a> : <a href="conf/libqsearch.pdf">presentation of libqsearch (Slides for FOSDEM, Feb 2003)</a></li>\n<li><a href="http://www.rencontresmondiales.org">LSM 2003</a> : <a href="conf/scapy_lsm2003.pdf">presentation of Scapy</a> and <a href="conf/shellforge_lsm2003.pdf">presentation of shellforge</a></li>\n<li><a href="http://www.linux-kongress.org">10th Linux Kongress</a> : <a href="conf/ksec_kongress03.pdf">presentation of Kernel Level Security (again)</a> (<a href="conf/ksec_article_kongress03.pdf">article for proceedings</a>)</li>\n<li><a href="http://www.cansecwest.com">CanSecWest/core04</a> : <a href="conf/shellforgeG2_csw04.pdf">Shellforge G2: shellcodes for everybody and every platform</a></li>\n<li><a href="http://www.syscan.org">SyScAN 04</a> : <a href="conf/shellcodes_syscan04.pdf">About UNIX Shellcodes</a></li>\n<li><a href="http://www.cansecwest.com">CanSecWest/core05</a> : <a href="conf/scapy_csw05.pdf">Packet generation and network based attacks with Scapy</a></li>\n<li><a href="http://lsm.abul.org">LSM (RMLL) 2005</a> : <a href="conf/shellforge_lsm2005.pdf">ShellForge</a></li>\n<li><a href="http://www.t2.fi/english/">T2\'2005</a> : <a href="conf/scapy_T2.pdf">Scapy: explore the net with new eyes</a> (<a href="conf/scapy_T2.handout.pdf">printable version</a>)</li>\n<li><a href="http://lufgi4.informatik.rwth-aachen.de/courses/show/1">Summerschool Applied IT Security 2005</a> : <a href="conf/scapy_Aachen.pdf">Network packet manipulation with Scapy</a></li>\n<li><a href="http://hack.lu">Hack.lu 2005</a> conference and workshop : <a href="conf/scapy_hack.lu.pdf">Network packet manipulation with Scapy</a> (<a href="conf/scapy_hack.lu.handout.pdf">printable version</a>)</li>\n<li><a href="http://pacsec.jp">PacSec/core05</a> : <a href="conf/scapy_pacsec05.pdf">Network packet forgery with Scapy</a> (<a href="conf/scapy_pacsec05.handout.pdf">printable version</a>)</li>\n<li><a href="http://www.blackhat.com">BlackHat Europe 06</a> : <a href="conf/skype_BHEU06.pdf">Silver Needle in the Skype</a> (<a href="conf/skype_BHEU06.handout.pdf">printable version</a>)</li>\n<li><a href="http://www.hackinthebox.org">Hack In The Box 2006</a> : <a href="conf/scapy-IPv6_HITB06.pdf">Scapy and IPv6 networking</a> <!--(<a href="conf/scapy-IPv6_HITB06.handout.pdf">printable version</a>)--></li>\n<li><a href="http://www.cansecwest.com">CanSecWest/core07</a> : <a href="conf/IPv6_RH_security-csw07.pdf">Ipv6 Routing Headers Security</a> (tools demonstrated: <a href="/projects/rtgraph3d">RT Graph 3D</a> and <a href="/projects/ipv6world">IPv6World</a>) (<a href="http://www.natisbad.org">summary of issues and fixes triggered</a>)</li>\n</ul>\n\n<H4>Projects/programs</H4>\n<ul>\n<li><a href="https://scapy.net/">Scapy</a>: a powerful network discovery tool.\n<li><a href="projects/rtgraph3d/">RTGraph3D</a>: make 3D graphs in realtime\n<li><a href="projects/ipv6world/">IPv6 world</a>: 3D IPv6 backbone explorer\n<li><a href="projects/etherpuppet/">EtherPuppet</a> : clone an Ethernet interface through TCP (even work on my Linksys WRT54G)\n<li><a href="projects/net2pcap/">net2pcap</a> : auditable daemon (less than 300 lines) to dump traffic to a pcap file.\n<li><a href="projects/pcapdispatcher/">PCAPdispatcher</a>: small program to dispatch a big pcap file into many others by their type or connection.\n<li><a href="projects/shellforge/">ShellForge</a>: write your shellcodes in C, ShellForge will convert them. (Inspired from Stealth\'s <a href="http://www.team-teso.net/releases/hellkit-1.2.tar.gz">Hellkit</a>).\n<li><a href="projects/tuntap_udp/">tunproxy</a> : a demonstration tunneling program over UDP using tun/tap (and his C clone)\n<li><a href="python/eapy.py">eapy</a>: a simplistic 802.1X EAP authentication client (MD5 challenges only, use PF_PACKET --> Linux only)\n<li><a href="python/bfi.py">bfy</a>: a little BrainFuck interpreter (BrainFuck <em>Hello world</em> program <a href="python/hello.bf">included!</a>)\n<li><a href="python/asm2graph.py">asm2graph</a> and <a href="python/bin2graph.py">bin2graph</a> : 2 small experiments to convert a binary program to a graph. (Use GraphViz). <br>\nTechnical solutions are very close to Silvio\'s <a href="http://www.big.net.au/~silvio/coding/graphing/">flowgraph</a>, which I did not know at this time.\n<li><a href="python/arpyspoof.py">arpyspoof</a>: a clone of <a href="http://monkey.org/~dugsong/dsniff/">arpspoof</a>. See links on <a href="http://sid.rstack.org/arp-sk/">arp-sk page</a> for more informations or tools about ARP cache poisonning.\n<li><a href="python/etherleak.py">etherleak.py</a> : a simple etherleak tester.\n<li><a href="python/">All python scripts</a>\n<li><a href="projects/experiments/">experiments</a>\n</ul>\n\n<H4>Linux Kernel Patches</H4>\n<ul>\n<li><a href="projects/sfswap/">SYN/FIN swap patch</a> : swap SYN and FIN flags in TCP headers to/from a given peer\n<li><a href="patches/icmpleak.patch">ICMP Leak patch for 2.0.39</a> to fix <a href="adv/CARTSA-20030314-icmpleak.txt">ICMP Leak bug</a>\n<li><a href="http://www.lids.org">LIDS homepage</a>\n<li><a href="lids_specifs/index.html">LIDS 0.0 specif. rev0.2</a>\n (<a href="lids_specifs.ps.gz">lids_specif.ps.gz</a>)\n<li><a href="patches/">all patches</a>\n</ul>\n\n\n<H4>Intrusion detection</H4>\n<ul>\n<li><a href="ids.ps.gz">Rapport</a> (et aussi en <a href="ids.pdf">PDF</a>)</li>\n<li><a href="idsbiblio">La biblio</a></li>\n</ul>\n\n<H4>Nmap</H4>\n<ul>\n<li><a href="nmap/">Some nmap hacks</a></li>\n</ul>\n\n<H4>Quick search experiments</H4>\n<ul>\n<li><a href="quicksearch/essai.ps">A postscript</a></li>\n<li><a href="python/">Implementations in python</a></li>\n<li><a href="libqsearch.html">libqsearch project</a></li>\n</ul>\n\n<H4>World domination</H4>\n<ul>\n<li><a href="python/searchbot">Search bot, sketch 1</a></li>\n</ul>\n\n<H4>Sharp Zaurus</H4>\n<ul>\n<li><a href=zaurus/zethereal.html>Ethereal on a Sharp Zaurus</a></li>\n<li><a href=zaurus/crosscompile.html>Example for setting up a cross compilation tool chain</a>\n</ul>\n\n<h3>If you trust me, you can trust my website</h3>\n<pre>\n-----BEGIN PGP SIGNED MESSAGE-----\nHash: SHA1\n\nIssuer: C=FR, ST=IdF, L=Paris, O=secdev.org, OU=secdev.org, CN=*.secdev.org\nSHA1 Fingerprint=EA:EE:C0:3F:53:B8:C8:AD:6A:05:24:32:85:F4:54:8D:87:21:34:7D\nMD5 Fingerprint=0D:07:6B:00:E7:86:C6:3C:B8:55:EB:02:6A:FC:E0:9C\n-----BEGIN PGP SIGNATURE-----\nVersion: GnuPG v1.4.6 (GNU/Linux)\n\niD8DBQFIMfI3Xuj/Xz2aQ+IRAmKbAKC25LEoT753HUqMfqNLyh0/LikftwCfbDlv\nJu6Rwb59JxlZIR+J6TKwE78=\n=wexP\n-----END PGP SIGNATURE-----\n</pre>\n\n<center><small>\n<!--Creative Commons License--><a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/2.5/"><img alt="Creative Commons License" style="border-width: 0" src="images/by-nc-sa.png"/></a><br/>Except where explicitely said otherwise, work on this site is licensed under GPLv2 for code and under a<br><a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/2.5/">Creative Commons Attribution-NonCommercial-ShareAlike 2.5 License</a> for the remaining.\n<!--/Creative Commons License-->\n<!-- <rdf:RDF xmlns="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">\n\t<Work rdf:about="">\n\t\t<license rdf:resource="http://creativecommons.org/licenses/by-nc-sa/2.5/" />\n\t</Work>\n\t<License rdf:about="http://creativecommons.org/licenses/by-nc-sa/2.5/"><permits rdf:resource="http://web.resource.org/cc/Reproduction"/><permits rdf:resource="http://web.resource.org/cc/Distribution"/><requires rdf:resource="http://web.resource.org/cc/Notice"/><requires rdf:resource="http://web.resource.org/cc/Attribution"/><prohibits rdf:resource="http://web.resource.org/cc/CommercialUse"/><permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/><requires rdf:resource="http://web.resource.org/cc/ShareAlike"/></License></rdf:RDF> -->\n</small></center>\n\n\n<a href="totoyoyo.html"><font color=#ffffff>SP4N\\TR4P, d0n`t f01l0\\N!</font></a>\n</body>\n</html>\n'
load_layer("tls")
s = sniff(filter="port 443", count=100) # sniff packets on port 443
ch_list = [p for p in s if TLSClientHello in p] # filter Client Hello messages
ch_list[0][TLSClientHello].show() # display the first message
###[ TLS Handshake - Client Hello ]### msgtype = client_hello msglen = 508 version = TLS 1.2 gmt_unix_time= Sat, 10 Oct 2026 00:01:56 +0100 (1791590516) random_bytes= f8f3159aa9f5bde32af8db592a160d3100fbee52581db2579fde7767 sidlen = 32 sid = '\xc4\x8d\r\x81yl\x81\x1b\xc4\xb9vY\x83{V\xaf\xd9\xef\xfc--(\x16h\xc0\xdd\x8f\xe6\x85c\xdaA' cipherslen= 36 ciphers = [TLS_AES_128_GCM_SHA256, TLS_CHACHA20_POLY1305_SHA256, TLS_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_3DES_EDE_CBC_SHA] complen = 1 comp = null extlen = 399 \ext \ |###[ TLS Extension - Server Name ]### | type = server_name | len = 21 | servernameslen= 19 | servernames= [b'my.geekstory.net'] |###[ TLS Extension - Extended Master Secret ]### | type = extended_master_secret | len = 0 |###[ TLS Extension - Renegotiation Indication ]### | type = renegotiation_info | len = 1 | reneg_conn_len= 0 | renegotiated_connection= '' |###[ TLS Extension - Supported Groups ]### | type = supported_groups | len = 14 | groupslen = 12 | groups = [x25519, secp256r1, secp384r1, secp521r1, ffdhe2048, ffdhe3072] |###[ TLS Extension - Supported Point Format ]### | type = ec_point_formats | len = 2 | ecpllen = 1 | ecpl = [uncompressed] |###[ TLS Extension - Session Ticket ]### | type = session_ticket | len = 0 | ticket = '' |###[ TLS Extension - Application Layer Protocol Negotiation ]### | type = alpn | len = 14 | protocolslen= 12 | protocols = [b'h2, http/1.1'] |###[ TLS Extension - Certificate Status Request ]### | type = status_request | len = 5 | stype = ocsp | \req \ | |###[ OCSPStatusRequest structure ]### | | respidlen = 0 | | \respid \ | | reqextlen = 0 | | reqext = '' |###[ TLS Extension - Key Share (for ClientHello) ]### | type = key_share | len = 107 | client_shares_len= 105 | \client_shares\ | |###[ Key Share Entry ]### | | group = x25519 | | kxlen = 32 | | key_exchange= '\xa8~\xa6\xe91\xd3\x86\xccV\x7fb\xf9\xca\xc4R\xd7\x7f\xc7\xf1E8\x06\x9c\xc7Q\x08D\xe4\xa4\xe0\x1b*' | |###[ Key Share Entry ]### | | group = secp256r1 | | kxlen = 65 | | key_exchange= '\x04\xfa\x91Y$\x9e\x06\xa36cZ\xd3\xaf\xbd\x94b\xee-JF>\x13\x9d\xd9\xef\x8f\xbc\x13\x00+\xc7,k\xe1\xee\xd0\x15(\xe5\xdf\x97\xdc\xc5\x80\x1crh\xfc}\x1e\xeeL\xd9pQ\xff\xf2\x11J\x0b\xddf_wq' |###[ TLS Extension - Supported Versions (for ClientHello) ]### | type = supported_versions | len = 9 | versionslen= 8 | versions = [TLS 1.3, TLS 1.2, TLS 1.1, TLS 1.0] |###[ TLS Extension - Signature Algorithms ]### | type = signature_algorithms | len = 24 | sig_algs_len= 22 | sig_algs = [sha256+ecdsa, sha384+ecdsa, sha512+ecdsa, sha256+rsaepss, sha384+rsaepss, sha512+rsaepss, sha256+rsa, sha384+rsa, sha512+rsa, sha1+ecdsa, sha1+rsa] |###[ TLS Extension - PSK Key Exchange Modes ]### | type = psk_key_exchange_modes | len = 2 | kxmodeslen= 1 | kxmodes = [psk_dhe_ke] |###[ TLS Extension - Record Size Limit ]### | type = record_size_limit | len = 2 | record_size_limit= 16385 |###[ TLS Extension - Padding ]### | type = padding | len = 142 | padding = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
Wi-Fi & Bluetooth
IPv6
Audits & Attacks