Table of Contents
SCAPY - Testes de redes
Scapy é um software para manipulação de pacotes, ele pode montar pacotes para simular testes e envia-los pela rede. Isso é perfeito para testes de rede e troubleshooting. O Scapy roda encima da linguagem Python,
Para executar o Scapy digite apenas o comando scapy.
root@bumblee:~# scapy INFO: Cant import matplotlib. Wont be able to plot. INFO: Cant import PyX. Wont be able to use psdump() or pdfdump(). WARNING: No route found for IPv6 destination :: (no default route?) INFO: Cant import python ecdsa lib. Disabled certificate manipulation tools Welcome to Scapy (2.3.3) >>>
O Scapy pode ser executado em dois modos: interativo, módulo ou script.
Scapy - Modo interativo
No modo interativo podemos executar comandos básicos
LSC
>>> lsc() arpcachepoison : Poison targets cache with (your MAC,victims IP) couple arping : Send ARP who-has requests to determine which hosts are up bind_layers : Bind 2 layers on some specific fields values bridge_and_sniff : Forward traffic between two interfaces and sniff packets exchanged 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 : defrag(plist) -> plist defragmented as much as possible dyndns_add : Send a DNS add message to a nameserver for "name" to have a new "rdata" dyndns_del : Send a DNS delete message to a nameserver for "name" etherleak : Exploit Etherleak flaw fletcher16_checkbytes: Calculates the Fletcher-16 checkbytes returned as 2 byte binary-string. fletcher16_checksum : Calculates Fletcher-16 checksum of the given buffer. fragment : Fragment a big IP datagram fuzz : Transform a layer into a fuzzy layer by replacing some default values by random objects getmacbyip : Return MAC address corresponding to a given IP address hexdiff : Show differences between 2 binary strings hexdump : -- hexedit : -- is_promisc : Try to guess if target is in Promisc mode. The target is provided by its ip. linehexdump : -- ls : List available layers, or infos on a given layer class or name promiscping : Send ARP who-has requests to determine which hosts are in promiscuous mode rdpcap : Read a pcap or pcapng file and return a packet list send : Send packets at layer 3 sendp : Send packets at layer 2 sendpfast : Send packets at layer 2 using tcpreplay for performance sniff : Sniff packets split_layers : Split 2 layers previously bound sr : Send and receive packets at layer 3 sr1 : Send packets at layer 3 and return only the first answer srbt : send and receive using a bluetooth socket srbt1 : send and receive 1 packet using a bluetooth socket srflood : Flood and receive packets at layer 3 srloop : Send a packet at layer 3 in loop and print the answer each time srp : Send and receive packets at layer 2 srp1 : Send and receive packets at layer 2 and return only the first answer srpflood : Flood and receive packets at layer 2 srploop : Send a packet at layer 2 in loop and print the answer each time traceroute : Instant TCP traceroute tshark : Sniff packets and print them calling pkt.show(), a bit like text wireshark wireshark : Run wireshark on a list of packets wrpcap : Write a list of packets to a pcap file >>>
Todos os comando acima são utilizados para enviar pacotes, traceroute, sniffer, etc.
Comando sniff()
Vamos utilizar o comando sniff para coletar pacotes ICMP
>>> sniff(1, filter='icmp', prn=Packet.show) ###[ Ethernet ]### dst= 00:e0:4c:51:3c:82 src= b0:25:aa:29:71:89 type= IPv4 ###[ IP ]### version= 4L ihl= 5L tos= 0x0 len= 60 id= 65316 flags= frag= 0L ttl= 128 proto= icmp chksum= 0xa4f4 src= 192.168.10.173 dst= 192.168.10.170 \options\ ###[ ICMP ]### type= echo-request code= 0 chksum= 0x47a3 id= 0x1 seq= 0x5b8 ###[ Raw ]### load= 'abcdefghijklmnopqrstuvwabcdefghi' <Sniffed: TCP:0 UDP:0 ICMP:1 Other:0> >>>
sniff(1, filter='icmp', prn=Packet.show)
- sniff - Comando para snifar
- 1 - Quantidade de pacotes que combinar com o parametro filter
- filter='icmp' - O filtro e para combinar pacotes do protocolo ICMP
- prn=Packet.show - Mostrar o pacote combinado
Quando você executar o comando sniff ele ficará esperando até surgir o pacote ICMP na placa rede. Isso pode ser gerado com um comando ping. Repare cada camada do pacote.
LS
O comando ls, mostra os protocolos suportados.
>>> ls() AH : <member 'name' of 'Packet' objects> ARP : <member 'name' of 'Packet' objects> ASN1P_INTEGER : <member 'name' of 'Packet' objects> ASN1P_OID : <member 'name' of 'Packet' objects> ASN1P_PRIVSEQ : <member 'name' of 'Packet' objects> ASN1_Packet : <member 'name' of 'Packet' objects> ATT_Error_Response : <member 'name' of 'Packet' objects> ATT_Exchange_MTU_Request : <member 'name' of 'Packet' objects> ATT_Exchange_MTU_Response : <member 'name' of 'Packet' objects> ATT_Find_By_Type_Value_Request : <member 'name' of 'Packet' objects> ATT_Find_By_Type_Value_Response : <member 'name' of 'Packet' objects> ATT_Find_Information_Request : <member 'name' of 'Packet' objects> ATT_Find_Information_Response : <member 'name' of 'Packet' objects> ATT_Handle_Value_Notification : <member 'name' of 'Packet' objects> ATT_Hdr : <member 'name' of 'Packet' objects> ATT_Read_By_Group_Type_Request : <member 'name' of 'Packet' objects> ATT_Read_By_Group_Type_Response : <member 'name' of 'Packet' objects> .....
Mostra as informações do payload IP e TCP.
>>> ls(IP) version : BitField (4 bits) = (4) ihl : BitField (4 bits) = (None) tos : XByteField = (0) len : ShortField = (None) id : ShortField = (1) flags : FlagsField (3 bits) = (0) frag : BitField (13 bits) = (0) ttl : ByteField = (64) proto : ByteEnumField = (0) chksum : XShortField = (None) src : SourceIPField (Emph) = (None) dst : DestIPField (Emph) = (None) options : PacketListField = ([]) >>> ls(TCP) sport : ShortEnumField = (20) dport : ShortEnumField = (80) seq : IntField = (0) ack : IntField = (0) dataofs : BitField (4 bits) = (None) reserved : BitField (3 bits) = (0) flags : FlagsField (9 bits) = (2) window : ShortField = (8192) chksum : XShortField = (None) urgptr : ShortField = (0) options : TCPOptionsField = ({}) >>>
Método summary
Todo o Scapy e orientado ao objeto, com isso temos métodos um dos métodos que é um dos mais importante é o método summary. O método nos da uma versão resumida do pacote.
>>> pkts = sniff(count=2, filter='icmp') >>> pkts.summary() Ether / IP / ICMP 192.168.10.173 > 192.168.10.170 echo-request 0 / Raw Ether / IP / ICMP 192.168.10.170 > 192.168.10.173 echo-reply 0 / Raw >>>
Método show e show2
O método show permite visualizar campos especificos do pacote.
>>> pkts[0].show() ###[ Ethernet ]### dst= 00:e0:4c:51:3c:82 src= b0:25:aa:29:71:89 type= IPv4 ###[ IP ]### version= 4L ihl= 5L tos= 0x0 len= 60 id= 47392 flags= frag= 0L ttl= 128 proto= icmp chksum= 0xeaf8 src= 192.168.10.173 dst= 192.168.10.170 \options\ ###[ ICMP ]### type= echo-request code= 0 chksum= 0x4793 id= 0x1 seq= 0x5c8 ###[ Raw ]### load= 'abcdefghijklmnopqrstuvwabcdefghi' >>> pkts[1].show() ###[ Ethernet ]### dst= b0:25:aa:29:71:89 src= 00:e0:4c:51:3c:82 type= IPv4 ###[ IP ]### version= 4L ihl= 5L tos= 0x0 len= 60 id= 2778 flags= frag= 0L ttl= 64 proto= icmp chksum= 0xd93f src= 192.168.10.170 dst= 192.168.10.173 \options\ ###[ ICMP ]### type= echo-reply code= 0 chksum= 0x4f93 id= 0x1 seq= 0x5c8 ###[ Raw ]### load= 'abcdefghijklmnopqrstuvwabcdefghi' >>>
A diferença do método show2 para o método show é que alguns campos são calculados apenas quando o pacote é enviado para a rede. Então o método show2 permite ver estes campos calculados.
Comando wrpcap e rdpcap
Com o Scapy é possível capturar pacotes e salvar em um arquivo pcap para ser analisado posteriormente.
>>> pkts <Sniffed: TCP:0 UDP:0 ICMP:2 Other:0> >>> pkts.summary() Ether / IP / ICMP 192.168.10.173 > 192.168.10.170 echo-request 0 / Raw Ether / IP / ICMP 192.168.10.170 > 192.168.10.173 echo-reply 0 / Raw >>> wrpcap('captura_icmp.pcap', pkts, sync=True) >>> rdpcap('captura_icmp.pcap') <captura_icmp.pcap: TCP:0 UDP:0 ICMP:2 Other:0> >>>
Criando pacotes
Vamos criar um pacotes mas é possível coletar um pacote e mostrar os comandos para recria-lós. Por exemplo a variavel pkts capturado anteriormente podemos ver os comandos para recriar o pacote.
>>> pkts[0].command() "Ether(src='b0:25:aa:29:71:89', dst='00:e0:4c:51:3c:82', type=2048)/IP(frag=0L, src='192.168.10.173', proto=1, tos=0, dst='192.168.10.170', chksum=60152, len=60, options=[], version=4L, flags=0L, ihl=5L, ttl=128, id=47392)/ICMP(gw=None, code=0, ts_ori=None, addr_mask=None, seq=1480, nexthopmtu=None, ptr=None, unused=None, ts_rx=None, length=None, chksum=18323, reserved=None, ts_tx=None, type=8, id=1)/Raw(load='abcdefghijklmnopqrstuvwabcdefghi')" >>> >>> >>> >>> >>> icmp=Ether(src='b0:25:aa:29:71:89', dst='00:e0:4c:51:3c:82', type=2048)/IP(frag=0L, src='192.168.10.173', proto=1, tos=0, dst='192.168.10.170', chksum=60152, len=60, options=[], version=4L, flags=0L, ihl=5L, ttl=128, id=47392)/ICMP(gw=None, code=0, ts_ori=None, addr_mask=None, seq=1480, nexthopmtu=None, ptr=None, unused=None, ts_rx=None, length=None, chksum=18323, reserved=None, ts_tx=None, type=8, id=1)/Raw(load='abcdefghijklmnopqrstuvwabcdefghi') >>> icmp.show() ###[ Ethernet ]### dst= 00:e0:4c:51:3c:82 src= b0:25:aa:29:71:89 type= IPv4 ###[ IP ]### version= 4L ihl= 5L tos= 0x0 len= 60 id= 47392 flags= frag= 0L ttl= 128 proto= icmp chksum= 0xeaf8 src= 192.168.10.173 dst= 192.168.10.170 \options\ ###[ ICMP ]### type= echo-request code= 0 chksum= 0x4793 id= 0x1 seq= 0x5c8 ###[ Raw ]### load= 'abcdefghijklmnopqrstuvwabcdefghi' >>>
Vamos criar um pacote do tipo TCP com o nome da variavel tcp.
>>> tcp = IP() / TCP() >>> tcp.show2() ###[ IP ]### version= 4L ihl= 5L tos= 0x0 len= 40 id= 1 flags= frag= 0L ttl= 64 proto= tcp chksum= 0x7ccd src= 127.0.0.1 dst= 127.0.0.1 \options\ ###[ TCP ]### sport= ftp_data dport= http seq= 0 ack= 0 dataofs= 5L reserved= 0L flags= S window= 8192 chksum= 0x917c urgptr= 0 options= {} >>>
É possivel gerar alguns valores aleatorios.
tcp[TCP].seq = RandInt()
Enviando pacotes
Para enviar pacotes utilizamos os comandos
- send - Envia o pacote na camada 3.
- sendp - Envia o pacote na camada 2.
- sr - Envia e recebe pacotes na camada 3.
- sr1 - Envia e recebe pacotes na camada 3 e retorna apenas o primeiro pacote.
Possue outros comandos, utilize o comando lsc() para verificar.
Exemplo de pacote na porta de destino 500 udp
udp = Ether()/IP()/UDP() udp[Ether].dst = "00:1a:3f:79:f2:37" udp[Ether].src = "00:e0:4c:51:3c:82" udp[IP].dst = "192.168.10.173" udp[IP].src = "192.168.10.170" udp[UDP].sport = 1000 udp[UDP].dport = 500
Recebendo pacotes
A função para receber os pacotes utilize o comando srp().
Mais exemplos https://thepacketgeek.com/scapy-p-04-looking-at-packets/