使用外部工具,subprocess.Popen和线程进行多端口扫描

时间:2010-12-16 11:10:16

标签: python subprocess python-2.4

我正在使用端口扫描程序扫描我的子网。遗憾的是,端口扫描器一次只能扫描一个主机的一个端口。对于无法访问的主机,扫描程序还有1秒的超时时间。扫描程序(作为外部程序)必须从subprocess.Popen()运行并加速它 - 这样我可以发送多个探测器,而一些先前的探测器正在等待回复 - 我使用线程。问题出现在具有大量线程的完整/ 24子网扫描中。实际打开的端口的SOY显示为已关闭。我怀疑输出会出现乱码。请注意,如果我一次扫描较少的主机或一个主机

,则不会发生这种情况

以下代码是我尝试创建一个线程池,它接受一个I​​P地址并对定义的端口运行“顺序”端口扫描。扫描完所有指定的端口后,它会从列表中获取下一个IP。

        while True:
            if not thread_queue.empty():
                try:
                    hst = ip_iter.next()
                except StopIteration:
                    break
                m=thread_queue.get()
                l=ThreadWork(self,hst,m)
                l.start()
        while open_threads != 0:
            pass      

此片段设置线程队列

        thread_list = [x for x in range(num_threads)]
        for t in thread_list:
            thread_queue.put(str(t))
        ip_iter=iter(self.final_target)

在ThreadWork函数中,我保留了一个开放线程的标签(因为thread_queue.empty被证明是不可靠的,我不得不使用这种粗略的方式)

class ThreadWork(threading.Thread):
    def __init__(self,i,hst,thread_no):
        global open_threads
        threading.Thread.__init__(self)
        self.host = hst
        self.ptr = i
        self.t = thread_no
        lock.acquire()
        open_threads = open_threads + 1
        lock.release() 

    def run(self):
        global thread_queue
        global open_threads
        global lock
        user_log.info("Executing sinfp for IP Address : %s"%self.host)
        self.ptr.result.append(SinFpRes(self.host,self.ptr.init_ports,self.ptr.all_ports,self.ptr.options,self.ptr.cf))
        lock.acquire()
        open_threads = open_threads - 1
        lock.release()
        thread_queue.put(self.t)

对SinFpRes的调用会为一个IP创建一个结果对象,并仅启动该IP端口的顺序扫描。 每个端口的实际扫描如图所示

        com_string = '/usr/local/sinfp/bin/sinfp.pl '+self.options+' -ai '+str(self.ip)+' -p '+str(p)
        args = shlex.split(com_string) 
        self.result=subprocess.Popen(args,stdout=subprocess.PIPE).communicate()[0]
        self.parse(p)

解析函数然后利用存储在self.result中的结果来存储该PORT的输出。所有端口的聚合构成了IP的扫描结果。

使用10个线程调用此代码可提供准确的o / p(与nmap输出相比)。在给出15个线程时,偶尔会打开一个开放端口。在给出20个线程时,错过了更多的开放端口。在提供50个线程时,错过了许多端口。

P.S。 - 作为第一个计时器,此代码非常复杂。向清教徒道歉。

P.P.S。 - 对于整个C类子网,即使是线程端口扫描也需要15分钟,而扫描的端口几乎不需要20个。我想知道是否应该将此代码移动到另一种语言并使用Python仅解析结果。有人可以建议我使用一种语言吗? 注意 - 我正在探索Shell选项,如S.Lott所示,但在将其转储到文件之前需要手动处理。

3 个答案:

答案 0 :(得分:1)

你为什么不试试?

(答案:不,他们会有自己的管道)

答案 1 :(得分:1)

使用shell

 for h in host1 host2 host3
 do
     scan $h >$h.scan &
 done
 cat *.scan >all.scan

这将同时扫描整个主机列表,每个主机都在一个单独的进程中。没有线程。

每次扫描都会生成.scan个文件。然后,您可以将所有.scan文件捕获到一个巨大的all.scan文件中,以便进一步处理或者您正在进行的任何操作。

答案 2 :(得分:0)

使用Perl而不是Python。程序(SinFP)是用Perl编写的,您可以修改代码以满足您的需求。