Categorías
Hacking Networking Programacion

Manipulación de Paquetes utilizando SCAPY – Conceptos Básicos sobre Scapy – Parte II

Como se ha mencionado anteriormente, una de las características más llamativas en Scapy es su alto nivel de personalización y la capacidad de conformar fácilmente conjuntos de paquetes que pueden ser enviados en cadena a un destino(s) determinado(s). Siguiendo por esa linea, se encuentran algunas funciones y opciones de uso que pueden ser bastante cómodas y útiles a la hora de manejar conjuntos de paquetes en Scapy.

En primer lugar, los conjuntos de paquetes en Scapy pueden ser creados y almacenados de la siguiente forma:

>>>layer = Ether()/IP(src=»192.168.1.33″, dst=»192.168.1.1″)/TCP(sport=22,dport=22)

Se aprecian dos cosas, en primer lugar el paquete esta conformado por varios paquetes que respetan la estructura por capas del modelo TCP/IP partiendo de los paquetes que corresponden a las capas más bajas, hasta las más altas (desde las capas de enlace hasta la capa de sesión), por otro lado, como el paquete IP contiene las cabeceras correspondientes a la dirección IP de origen y destino del paquete y el paquete TCP contiene los puertos de origen y destino, toda esta información es almacenada en una variable que controla todos estos paquetes como si se tratase de uno solo, de hecho, como se ha mencionado anteriormente, los valores de los atributos de las capas más bajas, son heredados posteriormente por las capas más altas. Con “layer” se pueden realizar las mismas operaciones que se llevan a cabo con cualquier paquete.

>>> ls(layer)

dst : DestMACField = ’64:68:0c:45:71:88′ (None)

src : SourceMACField = ’54:42:49:fa:c1:0d’ (None)

type : XShortEnumField = 2048 (0)

version : BitField = 4 (4)

ihl : BitField = None (None)

tos : XByteField = 0 (0)

len : ShortField = None (None)

id : ShortField = 1 (1)

flags : FlagsField = 0 (0)

frag : BitField = 0 (0)

ttl : ByteField = 64 (64)

proto : ByteEnumField = 6 (0)

chksum : XShortField = None (None)

src : Emph = ‘192.168.1.33’ (None)

dst : Emph = ‘192.168.1.1’ (‘127.0.0.1’)

options : PacketListField = [] ([])

sport : ShortEnumField = 22 (20)

dport : ShortEnumField = 22 (80)

seq : IntField = 0 (0)

ack : IntField = 0 (0)

dataofs : BitField = None (None)

reserved : BitField = 0 (0)

flags : FlagsField = 2 (2)

window : ShortField = 8192 (8192)

chksum : XShortField = None (None)

urgptr : ShortField = 0 (0)

options : TCPOptionsField = {} ({})

>>>del(layer.ttl)

>>> layer.ttl=128

>>> ls(layer.ttl)

Además de componer paquetes, es posible incluir payloads como paquetes RAW, por ejemplo

>>> layer = Ether()/IP(src=»192.168.1.33″, dst=»192.168.1.1″)/TCP(sport=22,dport=22)/»GET HTTP/1.0\r\n\r\n»

>>> layer

<Ether type=0x800 |<IP frag=0 proto=tcp src=192.168.1.33 dst=192.168.1.1 |<TCP sport=ssh dport=ssh |<Raw load=’GET HTTP/1.0\r\n\r\n’ |>>>>

Ahora, cada uno de los elementos contenidos en la variable “layer” pueden ser accedidos de diferentes formas, teniendo en cuenta que en realidad se trata simplemente de un array de elementos

>>> layer[0]

<Ether type=0x800 |<IP frag=0 proto=tcp src=192.168.1.33 dst=192.168.1.1 |<TCP sport=ssh dport=ssh |<Raw load=’GET HTTP/1.0\r\n\r\n’ |>>>>

>>> layer[1]

<IP frag=0 proto=tcp src=192.168.1.33 dst=192.168.1.1 |<TCP sport=ssh dport=ssh |<Raw load=’GET HTTP/1.0\r\n\r\n’ |>>>

>>> layer[2]

<TCP sport=ssh dport=ssh |<Raw load=’GET HTTP/1.0\r\n\r\n’ |>>

>>> layer[3]

<Raw load=’GET HTTP/1.0\r\n\r\n’ |>

>>> layer[2].sport=80

>>> layer[2]

<TCP sport=www dport=ssh |<Raw load=’GET HTTP/1.0\r\n\r\n’ |>>

>>> [elements for elements in layer]

[<Ether type=0x800 |<IP frag=0 proto=tcp src=192.168.1.33 dst=192.168.1.1 |<TCP sport=www dport=ssh |<Raw load=’GET HTTP/1.0\r\n\r\n’ |>>>>]

>>> str(layer)

‘dh\x0cEq\x88TBI\xfa\xc1\r\x08\x00E\x00\x008\x00\x01\x00\x00@\x06\xf7L\xc0\xa8\x01!\xc0\xa8\x01\x01\x00\x16\x00\x16\x00\x00\x00\x00\x00\x00\x00\x00P\x02 \x00\\\xb4\x00\x00GET HTTP/1.0\r\n\r\n’

>> ether =Ether(layerStr)

>>> ether

<Ether dst=64:68:0c:45:71:88 src=54:42:49:fa:c1:0d type=0x800 |<IP version=4L ihl=5L tos=0x0 len=56 id=1 flags= frag=0L ttl=64 proto=tcp chksum=0xf74c src=192.168.1.33 dst=192.168.1.1 options=[] |<TCP sport=ssh dport=ssh seq=0 ack=0 dataofs=5L reserved=0L flags=S window=8192 chksum=0x5cb4 urgptr=0 options=[] |<Raw load=’GET HTTP/1.0\r\n\r\n’ |>>>>

>> ether.hide_defaults()

>>> ether

<Ether dst=64:68:0c:45:71:88 src=54:42:49:fa:c1:0d type=0x800 |<IP ihl=5L len=56 frag=0 proto=tcp chksum=0xf74c src=192.168.1.33 dst=192.168.1.1 |<TCP sport=ssh dport=ssh dataofs=5L chksum=0x5cb4 options=[] |<Raw load=’GET HTTP/1.0\r\n\r\n’ |>>>>

Las opciones son bastante amplias, se esta manipulando un array de objetos, por este motivo pueden hacerse cosas como acceder directamente a uno de los elementos partiendo de su posición, modificar y eliminar elementos, recorrer el array y almacenarlo en otra variable, etc. Pueden llevarse a cabo todas las opciones sobre arrays que permite Python.

USO DE FUNCIONES EN SCAPY

Sin embargo, esto no es todo, en Scapy existen una cantidad de funciones estándar que pueden ser empleadas para diversos fines, para cada versión de Scapy pueden existir más o menos funciones (algunas añadidas y otras depreciadas) pero en todos los casos es posible visualizarlas utilizando el comando lsc

>>>lsc()

arpcachepoison : Poison target’s cache with (your MAC,victim’s IP) couple

arping : Send ARP who-has requests to determine which hosts are up

bind_layers : Bind 2 layers on some specific fields’ values

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

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

promiscping : Send ARP who-has requests to determine which hosts are in promiscuous mode

rdpcap : Read a pcap 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

El uso más simple de algunas de las funciones anteriormente listadas es el siguiente:

>>> sniffed=sniff(filter=»tcp port 22″)

>>> wireshark(sniffed)

>>> scan = sniff()

>>> wrpcap(«/home/adastra/Escritorio/sniffed.cap», scan)

>>> sniff = rdpcap(«/pcaps/sniffed.cap»)

>>> sniff

<sniffed.cap: TCP:74 UDP:2 ICMP:1 Other:0>

>>> graph,routes=traceroute([‘www.google.co.uk’,’www.yahoo.com’,’www.microsoft.com’])

Begin emission:

***********************Finished to send 90 packets.

******.

Received 87 packets, got 86 answers, remaining 4 packets

207.46.131.43:tcp80 72.30.2.43:tcp80 74.125.224.183:tcp80

1 192.168.1.1 11 192.168.1.1 11 192.168.1.1 11

2 80.58.67.102 11 80.58.67.102 11 80.58.67.102 11

3 80.58.94.41 11 80.58.94.41 11 80.58.79.65 11

4 80.58.76.69 11 80.58.72.106 11 81.46.7.205 11

…..

>>>graph.graph(target=»> /tmp/graph.svg»)

Algunas de las funciones anteriores son bastante intuitivas y auto-explicativas, en ellas se indica como es posible realizar con Scapy operaciones de sniffing, lectura y escritura de ficheros PCAP e incluso en las lineas finales se ha indicado el uso de la función “traceroute” la cual permite realizar un seguimiento de todos los nodos (normalmente routers o gateways) por los que pasa un paquete antes de llegar a su correspondiente destino, es igual a la función en Linux traceroute o en windows tracert. Sin embargo resulta más interesante aun, la posibilidad de generar un gráfico con dicha información, por ejemplo, el resultado de la ejecución anterior puede apreciarse en la siguiente imagen

NETWORKING_ENTRADA2_IMAGEN1

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Algunas otras funciones interesantes que merece la pena mencionar

>>> is_promisc(«192.168.1.33»)

False

>>> is_promisc(«192.168.1.1»)

True

>>>arp = arping(«192.168.1.1»)

Begin emission:

Finished to send 1 packets.

*

Received 1 packets, got 1 answers, remaining 0 packets

64:68:0c:45:71:88 192.168.1.1

(<ARPing: TCP:0 UDP:0 ICMP:0 Other:1>, <Unanswered: TCP:0 UDP:0 ICMP:0 Other:0>)

>>> arp

(<ARPing: TCP:0 UDP:0 ICMP:0 Other:1>, <Unanswered: TCP:0 UDP:0 ICMP:0 Other:0>)

>>> getmacbyip(«192.168.1.1»)

’64:68:0c:45:71:88′

>>> promiscping(«192.168.1.0/24»)

Begin emission:

*Finished to send 256 packets.

*

Received 2 packets, got 2 answers, remaining 254 packets

64:68:0c:45:71:88 192.168.1.1

00:1c:bf:5a:2a:25 192.168.1.110

(<PROMISCPing: TCP:0 UDP:0 ICMP:0 Other:2>, <Unanswered: TCP:0 UDP:0 ICMP:0 Other:254>)

Estas funciones, también incluyen características interesantes, tales como la capacidad de determinar cuales puntos en la red tienen interfaces en modo promiscuo (interfaces que se encuentran capturando todos los paquetes en la red), ejecutar peticiones ARP a un host concreto o un segmento de red entero, así como consultar una dirección MAC a partir de una dirección.

Existen algunas otras funciones que son muy interesantes y que dan mucha flexibilidad a la hora de realizar operaciones de pentesting en una red, en la próxima publicación de esta serie intentaré hablar un poco más sobre dichas funciones y otras utilidades.

Por Daniel Echeverri

Formador e investigador en temas relacionados con la seguridad informática y hacking. Es el autor del blog thehackerway.com el cual ha sido el ganador del European Cybersecurity Blogger Awards 2021 en la categoría de “Best Technical Content“.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *