Writing penetration test scripts and learning records in python

Posted by abhic on Thu, 10 Feb 2022 05:46:15 +0100

Learning record of writing penetration test script in python (4)

Writing penetration test script in python -- information collection host discovery based on two protocols

This is my first time to write a blog. As a beginner of network security, I hope to record, consolidate and strengthen what I have learned in the form of blogging. At the same time, I hope to find my shortcomings in the process of blogging and gradually improve myself.

During my study, my main reference book is Python security attack and defense - penetration test guide

The process of penetration test is mainly divided into:

  1. Clear objectives
  2. information gathering
  3. Vulnerability detection
  4. Vulnerability verification
  5. information analysis
  6. Get the information you need
  7. Clear trace
  8. report writing

The most recent task is to use python to complete the second item: information collection

Today's experiment is host discovery based on ICMP and TCP protocols. The main idea is: Send a message to the target host. If the source host receives a response packet, it indicates that the host is active.

The first is to use ICMP Protocol for host discovery. First, send an ICMP request message to the target host. If the source host receives the response from the target host, it indicates that the host exists.

# scapy is used to send ping requests and accept response data
# Random is used to generate random fields
# optparse is used to generate command line parameter forms
from scapy.all import *
from random import randint
from optparse import OptionParser

# Batch process the parameters entered by the user, and pass the processed IP address into the scan function
from scapy.layers.inet import IP, ICMP


def main():
    #Create a command-line parser. The parameter Usage is: the Usage summary to be printed when the program runs incorrectly or has help options.
    parser = OptionParser("Usage:%prog -i <target host> ")
    # add_option() function, adding option type, dest stored variable and help information
    # Get IP address parameters
    parser.add_option('-i', type='string', dest='IP', help='specify target host')
    # options, which is an object (optpars.Values) that holds command line parameter values. As long as you know the command line parameter name, you can access its corresponding value.
    # args, which is a list of positive arguments.
    options,args = parser.parse_args()
    print("Enter the to scan IP The address is:" + options.IP + "\n")

    # Determine whether the input is multiple hosts or a single host
    # If the IP contains' - ', it indicates that the scanned host is polymorphic
    if '-' in options.IP:
        # Example of IP address: 190.168.45.1-120
        # options.IP.split('-')[0].split('.')[3]: cut the ip address into two segments (190.168.45.1 and 120) according to '-', and the first half (190.168.45.1) according to '.' Cut, take the fourth section (1) after cutting
        # options.IP.split('-')[1]: cut the ip address into two segments (190.168.45.1 and 120) according to '-', and take the second half
        for i in range(int(options.IP.split('-')[0].split('.')[3]),int(options.IP.split('-')[1]) + 1):
            new_IP = options.IP.split('.')[0] + '.' + options.IP.split('.')[1] + '.' + options.IP.split('.')[2] + '.' + str(i)
            scan(new_IP)
            # Thread pauses for 0.2 seconds after each scan
            time.sleep(0.2)
    else:
        scan(options.IP)
    print("End of scan!")

# Send the constructed request packet to the destination address by calling ICMP, and judge whether the host is alive according to the response data of the destination address
def scan(ip):
    #65535 converted to hexadecimal: FFFF
    #Define packet data
    ip_id = randint(1,65535)
    icmp_id = randint(1,65535)
    icmp_seq = randint(1,65535)
    #Build package
    packet = IP(dst = ip,ttl = 64,id = ip_id)/ICMP(id = icmp_id,seq = icmp_seq)/b'rootkit'
    #Send packet and accept return data
    result = sr1(packet, timeout = 1,verbose = False)
    #Judge the return result
    if result :
        for rcv in result:
            scan_ip = rcv[IP].src
            print(scan_ip + '--->' 'Host is up')
    else:
        print(ip + '--->' 'host is down')

#ICMP detection using Nmap
def NmapScan(ip):
    #Instantiate PortScanner
    nm = nmap.PortScanner()
    try:
        #hosts is the target ip address and arguments is the Nmap scan parameter
        #-sn: scan with ping
        #-PE: echo package using ICMP
        result = nm.scan(hosts = ip,arguments = '-sn -PE')
        #Slice the results and extract the host status information
        state = result['scan'][ip]['status']['state']
        print("[{}] is [{}]".format(ip,state))
    except Exception as e:
        pass

if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        print("It is interrupted by the user and all threads are terminated")

This is a simple tool for sending and receiving data packets. There are no other functions, so when I test, the host of the Intranet can't be scanned. Later, I thought that the detection method is the same as using the ping command, so I try to use the ping command to test www.baidu.com COM, I found that I can ping, so I used the obtained Baidu ip address to test, and found that using the above program can detect the target host (Baidu). Then I thought I could use the ping command to test the host of my intranet first. The expected result is: it should not Ping. It turned out like this.

Test the intranet host

Test baidu host

Later, I checked a lot of data and found that many current network devices have adopted shielding strategies for ICMP. In some cases, even if the source host and target host are under the same LAN, the scanning results will be inaccurate.

So I went on to do the experiment: host detection using TCP protocol.

The general principle is: when sending ACK packets to the target host, if the target host survives, an RST packet will be returned to terminate the abnormal TCP connection.

def scan_tcp(ip):
    try:
    	#Randomly generated port number
        dport = random.randint(1,65535)
        #Building TCP packets
        packet = IP(dst = ip)/TCP(flags = 'A',dport = dport)
        #Send a packet and accept the returned data
        resp = sr1(packet,timeout = 1.0,verbose = 0)
        if resp:
            #Judge whether flags is' R '(its integer value is 4)
            if int(resp[TCP].flags) == 4:
                time.sleep(0.5)
                print(ip + '  ' + "is up")
            else:
                print(ip + '  ' + "is down")
        else:
            print(ip + '  ' + "is down")
    except:
        pass

Change the probe method in the previous code block to scan_tcp is ready to use.

Then I started testing scan_tcp(), which also ended in failure, and then began to think about possible reasons:

  1. The first reason I think of is the port number. I use the randomly generated port number, so I can't guarantee that the target host does open this port.
  2. . . . . Then I didn't think of any other reason,

The way to solve the above problems is to scan the port, find the open port of the target host, and change the randomly generated port number to the open port of the target host.

Then the question comes again. Since I have started port scanning on the target host, why should I probe the host (≖) ͞_ ≖ ̥),,,,

Topics: Python security