工具| 诸神之眼nmap定制化之并发处理

当我们使用nmap来进行大规模探测的时候,速度和准确度是摆在我们面前的两个问题,这时需要考虑到nmap的并发处理能力。

0x01 nmap本身的并发执行

相关参数

-T<0-5> Set timing template (higher is faster)

--min-hostgroup/max-hostgroup <size> 并行主机扫描组大小 。 将多个目标IP地址分成扫描组,然后在同一时间对一个扫描组进行扫描。 hostgroup代表了一个扫描组。

--min-hostgroup 一个扫描组的下限 。

--max-hostgroup 一个扫描组的上限。

--min-parallelism/max-parallelism <numprobes> nmap 进行扫描时,同一时间发送的报文数量。

eg:

nmap -sC -F --min-hostgroup 500 --max-hostgroup 800 <target>

实验数据:

斗哥分别对上述几个参数做了探测速度和准确度的测试,测试过程如下:

首先测试目标是选取一个B段地址,www.xxx.com/16。

1.无并发优化的情况下,有8378个主机存活,耗时925.11秒。

2.利用了-T5配置选项,有8368个主机存活,耗时903.80秒。

3.测试并行扫描组

设定扫描组最小数量为50,发现耗时反而更多,有947.14秒。

最小数量为100,耗时大幅度下降,613秒。

最小数量为200,发送了一个警告,耗时比数量100的组稍多,682秒。

4.测试并行发包率

同一时间至少发包100个。用时899秒。

同一时间至少发包150个,用时736.13秒。

5.结论

增加并行扫描组和并行发包率可以大幅度节省扫描时间,不过这个值也不能无限制增大,可能和本地带宽或者是接口IO有关系,而且速度往往和准确度相挂钩,对准确度要求不大的可以试试提一个比较高的速度。

0x02 lua 中的并发执行

lua采用coroutine的方式来实现并发执行。

●coroutine.create(f):用来完成对coroutine的创建工作。

●coroutine.resume(co,[,vall,...]):用来完成将coroutine的状态从暂停变为运行。

●coroutine.running():返回当前正在执行的coroutine。

●coroutine.status(co):返回coroutine的状态。

●coroutine.wrap(f):作用同 coroutine.create()和 coroutine.resume()。

●coroutine.yield(...):用来暂停coroutine。

0x03 NSE中的并发执行

在使用NSE处理并发执行时,并不需要考虑资源的保护,因为Nmap是单线程的。但是当在处理大规模的脚本实例时,就需要考虑网络的带宽以及socket的限制等问题。

在NSE中通过stdNSE库文件的函数stdNSE.new_thread()来支持NSE线程的创建。 如建立一个线程: stdNSE.new_thread(func,arg1,arg2,arg3,...)

func 就是我们要在线程中执行的函数,arg1,arg2...就是这个函数里要传递进去的参数。

下面一段脚本,创建了3个线程,并将这三个线程执行完成。

local stdNSE = require "stdNSE"
...
function func1(host,port) ... end
function func2(host,port) ... end
function func3(host,port) ... end
...
action = function(host,port)
    ...
local thread1 = stdNSE.new_thread(func1,host,port)
local thread2 = stdNSE.new_thread(func1,host,port)
local thread3 = stdNSE.new_thread(func1,host,port)
while true do
    if coroutine.status(thread1) == "dead" and coroutine.status(thread2) == "dead" and coroutine.status(threads3) == "dead" then
    break
    end
stdNSE.sleep(1)
end
end

我们可以通过循环语句,来批量添加线程到stdNSE.new_thread去执行。下面是nmap的一个Web 服务动态发现脚本(broadcast-wsdd-discover.nse)关于线程的运用。

-- 首先定义discoverThread函数,该函数要执行线程操作
discoverThread = function( funcname, results )
  local condvar = nmap.condvar( results )
  ...
end
...
action = function()

  local threads, results = {}, {}
  local condvar = nmap.condvar( results )

  -- 尝试发现设备和 WCF web 服务
  -- 建立for循环,遍历{"discoverDevices", "discoverWCFServices"}作为discoverThread的参数
  for _, f in ipairs( {"discoverDevices", "discoverWCFServices"} ) do
    --线程添加
    threads[stdnse.new_thread( discoverThread, f, results )] = true
  end

  local done
  -- 等待所有的线程完成
  while( not(done) ) do
    done = true
    for thread in pairs(threads) do
      if (coroutine.status(thread) ~= "dead") then done = false end
    end
    if ( not(done) ) then
      condvar("wait")
    end
  end
...
end

在NSE线程控制中,可以使用条件变量来控制脚本的执行流程。可以使用Nmap API和函数Nmap.condvar()创建一个条件变量。上述脚本local condvar = nmap.condvar( results )就是一个条件变量。

Nmap.condvar()的参数可以是除了nil、布尔类型、数值型以外的任何类型。对于一个条件变量可以进行的操作包括如下三个。

●wait

●broadcast

●signal

这里所有需要处理的线程都按顺序存放在一个等待队列中。

1.当一个线程调用wait函数之后,可以加入到这个队列中;

2.当一个线程调用signal函数之后,可以从这个队列中释放出来,然后恢复执行;

3.当一个线程调用broadcast函数之后,可以恢复所有线程的执行。

0x04 小结

本期主要介绍nmap中的并发执行机制,包括如何在lua和NSE去创建线程的操作。在nmap的脚本库当中,很多爆破脚本,或者是服务枚举,目录遍历等脚本都较为经常使用到线程并发的处理机制。NSE脚本中Nmap.mutex()函数还提供了类似python当中线程锁的机制,可以避免多个进程在同一时间对同一个资源进行操作,有兴趣的同学可以进一步深入研究。本期nmap定制化之并发处理介绍就到这里,我们下期见。

原文发布于微信公众号 - 漏斗社区(newdooneSec)

原文发表时间:2018-03-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏康怀帅的专栏

Fish Shell 安装配置

fish-shell GitHub:https://github.com/fish-shell/fish-shell oh-my-fish GitHub:htt...

6524
来自专栏linux驱动个人学习

VFS四大对象之三 struct dentry

继上一篇文章介绍了inode结构体:继续介绍目录项dentry: https://cloud.tencent.com/developer/article/105...

5006
来自专栏LuckQI

学习Java基础知识,打通面试关~十七了解类的加载过程

在我们Java程序中我们所写的Calss文件最终都会加载到内存当中,再次过程中会进行数据校验,转换解析和初始化的操作。完成后就可以形成我们虚拟机所需要的Java...

1222
来自专栏青青天空树

git crlf、lf自动转换引起的问题

  项目组最近加了一个新功能到代码中,使用flyway记录数据库版本变更,,,该工具会记录每次数据库结构的修改并生成sql文件存在指定目录上(当然必须用它来变更...

3941
来自专栏IT可乐

Nginx(三)------nginx 反向代理

  Nginx 服务器的反向代理服务是其最常用的重要功能,由反向代理服务也可以衍生出很多与此相关的 Nginx 服务器重要功能,比如后面会介绍的负载均衡。本篇博...

1893
来自专栏你不就像风一样

Java中用final修饰参数的方法当传入i++时异常

我的项目是这样写项目运行不起来,具体原因我参考的 https://www.cnblogs.com/xiohao/p/4861500.html, 解决方法...

1083
来自专栏Java技术栈

Maven Optional & Exclusions使用区别

Optional和Exclusions都是用来排除jar包依赖使用的,两者在使用上却是相反。 Optional定义后,该依赖只能在本项目中传递,不会传递到引用该...

3409
来自专栏全沾开发(huā)

使用postman进行API自动化测试

使用postman进行API自动化测试 最近在进行一个老项目的升级,第一步是先将node版本从4.x升级到8.x,担心升级会出现问题...

6177
来自专栏java思维导图

【读书笔记】1.1-基于TCP协议的RPC

1.1.1RPC名词解释 概念 全称Remote Process Call,即远程过程调用 rpc的实现包括服务的调用方和服务的提供方 过程 服务调用方发送RP...

2853
来自专栏阮一峰的网络日志

什么是 Event Loop?

Event Loop 是一个很重要的概念,指的是计算机系统的一种运行机制。 JavaScript语言就采用这种机制,来解决单线程运行带来的一些问题。 ? ...

3008

扫码关注云+社区

领取腾讯云代金券