/ 这里Thisis阳光王国Sunrays的疆域Kingdom.。 /

Sunrays Network Scanner

阅读需

43–65 分钟
# Author: Ryan Alloriadonis
# Copyright © 2022 Sunrays Kingdom
# This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
# View license terms at https://creativecommons.org/licenses/by-nc-sa/4.0/

import os
import sys
import multiprocessing
import time
import csv
import telnetlib
import shutil
# from pythonping import ping
from ping3 import ping, verbose_ping
import ipaddress


def del_file(path):
    ls = os.listdir(path)
    for i in ls:
        c_path = os.path.join(path, i)
        if os.path.isdir(c_path):
            del_file(c_path)
        else:
            os.remove(c_path)


def progress_bar(done, total, i, found):
    # print("\r", end="")
    print("\r" + str(done) + "/" + str(total) + ": {}%: ".format(i), "▋" * (i // 4) + " 发现IP数:" + str(found), end="",
          flush=True)
    # sys.stdout.flush()


def testTelnet(ip, timeout):
    try:
        tn = telnetlib.Telnet(str(ip), timeout=timeout)
        """
        # Get Name
        name = (bytes.decode(tn.read_until(b' ', timeout=5))).split("\n")[-1]
        """
        tn.close()

        return ip
    except:
        return -1


def testPing(ip, timeout):
    try:
        # Ping Target IP
        ping_result = ping(str(ip), timeout=timeout)
        if ping_result is False or ping_result is None:
            return -1
        else:
            return ip
    except:
        return -1


def main(a, b, c, d, e, f, ind):
    digit_1 = a
    digit_2 = b
    digit_3 = int(c)
    digit_4 = int(d)
    if e == 0:
        TIMEOUT = 0.05
    else:
        TIMEOUT = e
    retry = int(f)

    ip_pool = []
    ip_digit = int(digit_3)
    ip_digit_3 = digit_2

    done = 0
    with open("./temp/counter_thread_" + str(ind) + ".txt", "w+") as f:
        f.write("0.0")

    while ip_digit <= int(d):
        ip_digit_2 = 0
        while ip_digit_2 <= 255:
            ip = str(digit_1) + "." + str(ip_digit_3) + "." + str(ip_digit) + "." + str(ip_digit_2)
            result = -1
            counter = 0
            while result == -1 and counter <= retry:
                result = testTelnet(ip, TIMEOUT)
                # print("扫描中:", ip, "->", "当前线程已找到:",len(ip_pool), "个IP")
                if result != -1:
                    with open("./temp/Scan_list_" + str(digit_1) + "_" + str(digit_2) + "_" + str(digit_3) + "_" + str(
                            digit_4) + ".txt", "a+") as f:
                        f.write(str(result) + "\n")
                    ip_pool.append(result)
                    with open("./temp/counter_thread_" + str(ind) + ".txt", "w+") as f:
                        f.write(str(done) + "." + str(len(ip_pool)))
                counter += 1
            done += 1
            ip_digit_2 += 1
            with open("./temp/counter_thread_" + str(ind) + ".txt", "w+") as f:
                f.write(str(done) + "." + str(len(ip_pool)))
        ip_digit += 1

    with open("./temp/counter_thread_" + str(ind) + ".txt", "w+") as f:
        f.write(str(done) + "." + str(len(ip_pool)))

    with open("./temp/Scan_list_" + str(digit_1) + "_" + str(digit_2) + "_" + str(digit_3) + "_" + str(digit_4) + ".csv",
              "w+") as ap:
        writer = csv.writer(ap, dialect="unix")
        for i in ip_pool:
            writer.writerow([i, ""])

def main_ping(a, b, c, d, e, f, ind):
    digit_1 = a
    digit_2 = b
    digit_3 = int(c)
    digit_4 = int(d)
    if e == 0:
        TIMEOUT = 0.05
    else:
        TIMEOUT = e
    retry = int(f)

    ip_pool = []
    ip_digit = int(digit_3)
    ip_digit_3 = digit_2

    done = 0
    with open("./temp/counter_thread_" + str(ind) + ".txt", "w+") as f:
        f.write("0.0")

    while ip_digit <= int(d):
        ip_digit_2 = 0
        while ip_digit_2 <= 255:
            ip = str(digit_1) + "." + str(ip_digit_3) + "." + str(ip_digit) + "." + str(ip_digit_2)
            result = -1
            counter = 0
            while result == -1 and counter <= retry:
                result = testPing(ip, TIMEOUT)
                # print("扫描中:", ip, "->", "当前线程已找到:",len(ip_pool), "个IP")
                if result != -1:
                    with open("./temp/Scan_list_" + str(digit_1) + "_" + str(digit_2) + "_" + str(digit_3) + "_" + str(
                            digit_4) + ".txt", "a+") as f:
                        f.write(str(result) + "\n")
                    ip_pool.append(result)
                    with open("./temp/counter_thread_" + str(ind) + ".txt", "w+") as f:
                        f.write(str(done) + "." + str(len(ip_pool)))
                counter += 1
            done += 1
            ip_digit_2 += 1
            with open("./temp/counter_thread_" + str(ind) + ".txt", "w+") as f:
                f.write(str(done) + "." + str(len(ip_pool)))
        ip_digit += 1

    with open("./temp/counter_thread_" + str(ind) + ".txt", "w+") as f:
        f.write(str(done) + "." + str(len(ip_pool)))

    with open("./temp/Scan_list_" + str(digit_1) + "_" + str(digit_2) + "_" + str(digit_3) + "_" + str(digit_4) + ".csv",
              "w+") as ap:
        writer = csv.writer(ap, dialect="unix")
        for i in ip_pool:
            writer.writerow([i, ""])


def watcher():
    time.sleep(1)
    total = 256 * 256
    while True:
        time.sleep(1)
        count_sum = 0
        found = 0
        for root, path, files in os.walk("./temp"):
            for file in files:
                if "counter" in file:
                    while True:
                        try:
                            with open("./temp/" + file, "r") as f:
                                content = f.read()
                            count_sum += int(content.split(".")[0])
                            found += int(content.split(".")[1])
                            break
                        except:
                            pass
        i = round((count_sum / total) * 100)
        progress_bar(count_sum, total, i, found)
        if count_sum == total:
            print()
            break


def sub_pro(roundcount, multi, digit_1, digit_2, timeout, tr):
    low_list = [0, 16, 31, 46, 61, 76, 91, 106, 121, 136, 151, 166, 181, 196, 211, 226, 241]
    high_list = [15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165, 180, 195, 210, 225, 240, 255]

    low_list_h = [0, 6, 11, 16, 21, 26, 31, 36, 41, 46, 51, 56, 61, 66, 71, 76, 81, 86, 91, 96, 101, 106, 111, 116, 121,
                  126, 131, 136, 141, 146, 151, 156, 161, 166, 171, 176, 181, 186, 191, 196, 201, 206, 211, 216, 221,
                  226, 231, 236, 241, 246, 251]
    high_list_h = [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100, 105, 110, 115, 120,
                   125, 130, 135, 140, 145, 150, 155, 160, 165, 170, 175, 180, 185, 190, 195, 200, 205, 210, 215, 220,
                   225, 230, 235, 240, 245, 250, 255]
    if multi == 17:
        for i in range(multi):
            round_count = roundcount
            low = low_list[i - round_count * multi]
            high = high_list[i - round_count * multi]
            p = multiprocessing.Process(target=main, args=(digit_1, digit_2, low, high, timeout, tr, i))
            p.start()
            if i == multi - 1:
                watch = multiprocessing.Process(target=watcher)
                watch.start()
            else:
                pass
    if multi == 51:
        for i in range(multi):
            round_count = roundcount
            low = low_list_h[i - round_count * multi]
            high = high_list_h[i - round_count * multi]
            p = multiprocessing.Process(target=main, args=(digit_1, digit_2, low, high, timeout, tr, i))
            p.start()
            if i == multi - 1:
                watch = multiprocessing.Process(target=watcher)
                watch.start()
            else:
                pass

    if multi == 256:
        for i in range(multi):
            round_count = roundcount
            low = i
            high = i
            p = multiprocessing.Process(target=main, args=(digit_1, digit_2, low, high, timeout, tr, i))
            p.start()
            if i == multi - 1:
                watch = multiprocessing.Process(target=watcher)
                watch.start()
            else:
                pass

def sub_pro_ping(roundcount, multi, digit_1, digit_2, timeout, tr):
    low_list = [0, 16, 31, 46, 61, 76, 91, 106, 121, 136, 151, 166, 181, 196, 211, 226, 241]
    high_list = [15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165, 180, 195, 210, 225, 240, 255]

    low_list_h = [0, 6, 11, 16, 21, 26, 31, 36, 41, 46, 51, 56, 61, 66, 71, 76, 81, 86, 91, 96, 101, 106, 111, 116, 121,
                  126, 131, 136, 141, 146, 151, 156, 161, 166, 171, 176, 181, 186, 191, 196, 201, 206, 211, 216, 221,
                  226, 231, 236, 241, 246, 251]
    high_list_h = [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100, 105, 110, 115, 120,
                   125, 130, 135, 140, 145, 150, 155, 160, 165, 170, 175, 180, 185, 190, 195, 200, 205, 210, 215, 220,
                   225, 230, 235, 240, 245, 250, 255]
    if multi == 17:
        for i in range(multi):
            round_count = roundcount
            low = low_list[i - round_count * multi]
            high = high_list[i - round_count * multi]
            p = multiprocessing.Process(target=main_ping, args=(digit_1, digit_2, low, high, timeout, tr, i))
            p.start()
            if i == multi - 1:
                watch = multiprocessing.Process(target=watcher)
                watch.start()
            else:
                pass
    if multi == 51:
        for i in range(multi):
            round_count = roundcount
            low = low_list_h[i - round_count * multi]
            high = high_list_h[i - round_count * multi]
            p = multiprocessing.Process(target=main_ping, args=(digit_1, digit_2, low, high, timeout, tr, i))
            p.start()
            if i == multi - 1:
                watch = multiprocessing.Process(target=watcher)
                watch.start()
            else:
                pass

    if multi == 256:
        for i in range(multi):
            round_count = roundcount
            low = i
            high = i
            p = multiprocessing.Process(target=main_ping, args=(digit_1, digit_2, low, high, timeout, tr, i))
            p.start()
            if i == multi - 1:
                watch = multiprocessing.Process(target=watcher)
                watch.start()
            else:
                pass


if __name__ == '__main__':
    multiprocessing.freeze_support()
    print("欢迎使用桑雷斯多线程端口协议扫描工具")
    while True:
        try:
            print("\n请完成如下参数配置:")
            print(
                "——————————————————————————————————————————————————————————————————————————————————————————————————————————————————")
            ip_address_start = input("[1/6]扫描起始IP地址段(仅支持前两位,例如:192.168): ")
            ip_address_end = input("[2/6]扫描结束IP地址段(仅支持前两位,例如:192.169, 若仅需扫描一个网段则与扫描起始网段相同): ")
            multi = int(input("[3/6]扫描线程配置(默认性能[17/网段]:请输入0; 高性能[51线程/网段]:请输入1; 极高性能[256线程/网段]:请输入2): "))
            timeout_user = float(input("[4/6]扫描超时阈值设定(单位秒,默认值(0.05)则输入0): "))
            retry = int((input("[5/6]连接超时后的重连尝试次数(可避免网络波动带来的影响,默认值为0): ")))
            protocol = int((input("[6/6]扫描的协议类型(telnet: 0, ping: 1): ")))
            print(
                "——————————————————————————————————————————————————————————————————————————————————————————————————————————————————")

            # check
            print("正在检查配置...")
            try:
                start = ip_address_start.split('.')
                end = ip_address_end.split('.')
                if len(start) == len(end) == 2 and int(start[0]) >= 0 and int(start[1]) >= 0 and int(
                        end[0]) >= 0 and int(end[1]) >= 0 and int(start[0]) <= 255 and int(start[1]) <= 255 and int(
                    end[0]) <= 255 and int(start[0]) == int(end[0]) and int(start[1]) <= int(end[1]):
                    if multi == 0 or multi == 1 or multi == 2:
                        if timeout_user >= 0:
                            if retry >= 0:
                                if protocol == 0 or protocol == 1:
                                    print("配置检测通过!")
                                    print("配置已存储!\n")
                                    break
                                else:
                                    print(">>>>协议类型错误!<<<<")
                                    pass
                            else:
                                print(">>>>重连尝试次数错误!<<<<")
                                pass
                        else:
                            print(">>>>超时时间错误!<<<<")
                            pass
                    else:
                        print(">>>>多线程配置错误!<<<<")
                        pass
                else:
                    print(">>>>IP地址段配置错误!<<<<")
                    pass
                print("您的配置信息有上述错误!请检查重试!\n")
            except:
                print("您输入的配置信息有误!请检查重试!\n")
        except:
            print("您输入的数据不合法!请检查重试!\n")

    # Initialization

    digit_1 = start[0]
    digit_2 = start[1]
    i = int(digit_2)

    digit_2_list = []
    while i <= int(end[1]):
        digit_2_list.append(i)
        i += 1

    if os.path.exists('./temp/'):
        del_file('./temp/')
        shutil.rmtree('./temp/')
        print("正在清空缓存...")
        os.mkdir('./temp/')
        pass
    else:
        os.makedirs('./temp/')

    # multiprocessing
    print("正在创建扫描线程...")
    multi_proc = 0
    if multi == 0:
        multi_proc = 17
    elif multi == 1:
        multi_proc = 51
    else:
        multi_proc = 256

    NUMBER_OF_SESSIONS = (int(end[1]) - int(start[1]) + 1) * multi_proc
    print("线程创建完成!预计: 总共使用:" + str(NUMBER_OF_SESSIONS) + " 个线程! 同时最大使用: " + str(multi_proc) + "个线程!")

    # Start
    print()
    print("扫描开始,请耐心等待...")
    print(
        "——————————————————————————————————————————————————————————————————————————————————————————————————————————————————")

    if protocol == 0:
        for index, n in enumerate(digit_2_list):
            print("[" + str(index + 1) + "]" + str(multi_proc) + "个进程正在扫描网段:", str(digit_1) + "." + str(n) + ". * . *")
            pro = multiprocessing.Process(target=sub_pro, args=(index, multi_proc, digit_1, n, timeout_user, retry))
            pro.start()
            pro.join()
    else:
        for index, n in enumerate(digit_2_list):
            print("[" + str(index + 1) + "]" + str(multi_proc) + "个进程正在扫描网段:", str(digit_1) + "." + str(n) + ". * . *")
            pro = multiprocessing.Process(target=sub_pro_ping, args=(index, multi_proc, digit_1, n, timeout_user, retry))
            pro.start()
            pro.join()

    # data sorting
    print(
        "——————————————————————————————————————————————————————————————————————————————————————————————————————————————————")
    print("扫描完毕!")
    print("\n正在汇总处理临时文件并输出至'扫描结果.txt'...")
    print(
        "——————————————————————————————————————————————————————————————————————————————————————————————————————————————————")
    time.sleep(2)
    total = []
    for root, path, files in os.walk("./temp"):
        for file in files:
            if ".csv" in file:
                print("\r正在处理临时文件:" + file, end="", flush=True)
                with open("./temp/" + file, "r") as f:
                    reader = csv.reader(f)
                    for line in reader:
                        total.append(line[0])

    # sort result before output
    total_sorted = sorted(total, key=ipaddress.IPv4Address)

    with open("扫描结果-" + start[0] + "_" + start[1] + "-" + end[0] + "_" + end[1] + "_" + str(time.time()) + ".txt",
              "w+") as f:
        for i in total_sorted:
            f.write(str(i) + "\n")
    print(
        "\n——————————————————————————————————————————————————————————————————————————————————————————————————————————————————")
    print("输出成功!\n")
    print("感谢使用,10秒后退出...")
    time.sleep(10)
    sys.exit(0)

创作于