11. Host survival detection using python's scapy and nmap modules

Using scapy module to construct icmp packet probe

0x01 module installation

Scapy is used here, so you need to install pip install scapy first, and then encounter the following error reports:

ValueError: Unknown pypcap network interface '\\Device\\NPF_Loopback'

After searching the Internet, npcap needs to be installed to run scapy on windows

So download npcap, address: https://nmap.org/npcap/windows-10.html

0x02 scapy module learning notes

1. Generate data package

Generate a packet to 192.168.8.1

ip = IP(dst="192.168.8.1")

Scapy constructs data packets in a hierarchical form. Usually, the lowest protocol is Ether, followed by IP, followed by TCP or UDP. For example:

data packetexample
HTTPEther()/IP(dst="www.baidu.com")/TCP()/"GET /index.html HTTP/1.0 \n\n"
ARPEther()/ARP(pdst="192.168.8.12")
ICMPIP(dst="192.168.8.12")/ICMP()
TCPtcp=IP(dst="192.168.8.12")/TCP(dport=80,flags="S")

Generate HTTP package: IP() / TCP() / "GET/HTTP/1.0\r\n\r\n"
Generate an ICMP packet: IP(dst=ip, ttl=64, id=ip_id) / ICMP(id=icmp_id, seq=icmp_seq) / b'rootkit '

2. Send packets

There are six functions to send data packets in scapy, which is easy to understand and remember

The first group is sr(), sr1(), send(), where s stands for send, r stands for receive, 1 in sr1() stands for accepting one packet, sr() accepts all packets, and send() only sends and does not receive. This set of functions works on the third layer

The second group is srp(), srp1(), sendp(), each adding a p to the previous one, which means that only the second layer packets are sent

sr() requires two parameters to accept all packages

>>> anx,unans=sr(IP(dst="192.168.8.1")/ICMP())
Begin emission:
Finished sending 1 packets.
...*
Received 4 packets, got 1 answers, remaining 0 packets
#############################################
Received Indicates the number of packets received
answers Indicates the target response packet
 Save through 2 Parameters sr Return value
 One is the sent packet and the other is the received packet
anx,unans=sr(IP(dst="192.168.43.135")/ICMP())
adopt anx.summary()View the contents of both packages

sr1() only receives one packet and one parameter is enough

>>> packet=sr1(IP(dst="192.168.8.1")/ICMP())
Begin emission:
Finished sending 1 packets.
...*
Received 4 packets, got 1 answers, remaining 0 packets

0x03 scripting

Sure enough, there is no error after the installation. The script is as follows:

#!/usr/bin/python
# coding:utf-8
from scapy.all import *
from random import randint
from argparse import ArgumentParser


def Scan(ip):
    ip_id = randint(1, 65535)
    icmp_id = randint(1, 65535)
    icmp_seq = randint(1, 65535)
    packet = IP(dst=ip, ttl=64, id=ip_id) / ICMP(id=icmp_id, seq=icmp_seq) / b'rootkit'
    result = sr1(packet, timeout=1, verbose=False)
    if result:
        for rcv in result:
            scan_ip = rcv[IP].src
            print(scan_ip + '--->' 'Host is up')
    else:
        print(ip + '--->' 'host is down')


def scan(ip):
    ip_id = randint(1, 65535)
    icmp_id = randint(1, 65535)
    icmp_seq = randint(1, 65535)
    packet = IP(dst=ip, ttl=64, id=ip_id) / ICMP(id=icmp_id, seq=icmp_seq) / b'rootkit'
    result = sr1(packet, timeout=1, verbose=False)
    if result:
        for rcv in result:
            scan_ip = rcv[IP].src
            print(scan_ip + '-->' 'host is up')
    else:
        print(ip + 'host is down')


def main():
    parse = ArgumentParser()
    parse.add_argument("-u", "--url", dest="url", type=str, help="To convert to domain name ip")
    url = parse.parse_args().url
    print("Scan report for " + url.strip() + "\n")
    if '-' in url.strip():
        for i in range(int(url.strip().split('-')[0].split('.')[3]), int(url.strip().split('-')[1]) + 1):
            Scan(
                url.strip().split('.')[0] + '.' + url.strip().split('.')[1] + '.' + url.strip().split('.')[
                    2] + '.' + str(i))
            time.sleep(0.2)
    else:
        Scan(url.strip())

    print("\nScan finished!....\n")


if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print("interrupted by user, killing all threads...")

Here, we use python's scapy module to send icmp packets to the target, and judge whether the target host is turned on by whether there is a response or not

Scan with nmap module

0x01 download nmap module and nmap installation package

Install the nmap module (note that it is not nmap but Python nmap)

pip install python-nmap

Install the latest version of nmap
https://nmap.org/dist/nmap-7.80-setup.exe

0x02 nmap module learning notes

This part is learned from: https://blog.csdn.net/qq_36119192/article/details/83717690

portScanner() class

The portScanner() class is used to scan the port of the specified host

nmScan=nmap.PortScanner()  #instantiation 

Scan (host, port, args) method: scan the specified port of the specified host or network segment in the specified way

Parameters:

  • Host: the host or network segment to be scanned, which can be a separate ip: 192.168.10.10; It can also be a small network segment: 192.168.10.10-20; It can also be a large network segment: 192.168.10.0/24
  • Port: optional parameter. The port to be scanned. Multiple ports are separated by commas, such as 20, 21, 22, 23, 24
  • args: optional parameter, the method to scan
import nmap
nm = nmap.PortScanner()
nm.scan('192.168.8.1-100', '22,21','-sV')
 
You can do the same
nm.scan(hosts='192.168.1.0/24', arguments='-n -sP -PE -PA21,23,80,3389')

command_line() method: the returned scanning method is mapped to the specific nmap command line, that is, the nm Scan() command, corresponding to the specific nmap command

import nmap
nm = nmap.PortScanner()
nm.scan('192.168.8.1-100', '22,21','-sV')
a=nm.command_line()
print(a)
###########################
nmap -oX - -p 20,21 -sV 192.168.125.134

scaninfo() method: returns the nmap scanning information in the form of dictionary

import nmap
nm = nmap.PortScanner()
nm.scan('192.168.8.11-100', '22,21','-sV')
a=nm.scaninfo()
print(a)
###########################
{'tcp': {'services': '20-21', 'method': 'syn'}}

all_hosts() method: returns the list of hosts scanned by nmap in the format of list type

```python
import nmap
nm = nmap.PortScanner()
nm.scan('192.168.10.10-12', '22,21','-sV')
####################################################
['192.168.10.10','192.168.10.11','192.168.10.12']

0x03 scripting

# -*- coding: utf-8 -*-
import nmap
import optparse


def NmapScan(targetIP):
    nm = nmap.PortScanner()
    try:
        result = nm.scan(hosts=targetIP, arguments='-sn -PE')
        state = result['scan'][targetIP]['status']['state']
        print("[{}] is [{}]".format(targetIP, state))
    except Exception as e:
        pass


if __name__ == '__main__':
    parser = optparse.OptionParser('usage: python %prog -i ip \n\n'
                                   'Example: python %prog -i 192.168.1.1[192.168.1.1-100]\n')
    parser.add_option('-i', '--ip', dest='targetIP', default='192.168.1.1', type='string', help='target ip address')
    options, args = parser.parse_args()
    if '-' in options.targetIP:
        for i in range(int(options.targetIP.split('-')[0].split('.')[3]), int(options.targetIP.split('-')[1]) + 1):
            NmapScan(options.targetIP.split('.')[0] + '.' + options.targetIP.split('.')[1] + '.' +
                     options.targetIP.split('.')[2] + '.' + str(i))
    else:
        NmapScan(options.targetIP)

use

Added by CraigRoberts on Sat, 05 Mar 2022 01:25:57 +0200