Nmap脚本引擎原理
Nmap脚本引擎原理
一、NSE介绍
虽然Nmap内嵌的服务于版本探测已足够强大,但是在某些情况下我们需要多伦次的交互才能够探测到服务器的信息,这时候就需要自己编写NSE插件实现这个功能。NSE插件能够完成网络发现、复杂版本探测、脆弱性探测、简单漏洞利用等功能。
转载请注明出处:http://www.cnblogs.com/liun1994/
在文章 "Nmap脚本文件分析(AMQP协议为例)" 中会将版本探测,NSE脚本原理联系起来,具体分析Nmap探测的执行过程。
在文章 " 编写自己的NSE脚本" 中将以一个简单的例子说明NSE的编写。
脚本扫描通过选项被激活
-sC: 使通用scripts生效
--script: 指定自己的脚本文件
--script-trace: 查看脚本执行过程
-A: 同时进行版本探测和脚本扫描 为了不进行主机发现也不进行端口扫描,直接使用自定义的脚本探测。可以使用下面的选项:
-Pn -sn --script --script-args和--script-args-file,指定脚本要读入的参数
nmap --script snmp-sysdescr --script-args snmpcommunity=admin example.com nmap --script default,safe 加载default和safe类脚本。
参考: https://nmap.org/book/nse-usage.html#nse-categories
脚本文件分类:brute、default、dos、safe、exploit等,具体的可查看:https://nmap.org/book/nse-usage.html#nse-categories
根据脚本的运行阶段不同分为四类:Prerule scripts、Host scripts、Service scripts、Postrule scripts。
应用最多的就是Service scripts,Post scripts对Nmap输出进行格式化输出,Host scripts这个阶段在Nmap运行完主机发现、端口扫描、版本探测、OS侦测后执行;Prerule scripts执行一些资源操作,先于各探测执行。
二、Nmap执行原理图

由上图可以看到四类脚本的运行阶段,以及他们的功能。
1)在nmap_main里面,调用init_main()进行详细的初始化过程,加载Lua标准库与Nmap扩展库,准备参数环境,加载并执行nse_main.lua文件;这个文件加载用户选择的脚本文件,执行完之后返回函数对象给init_main(),被保存到Lua注册表中。
2)在nse_main.lua中,定义两个核心的类,Script和Thread,Script用于管理NSE脚本,当新的脚本被加载时,调用 Script.new创建脚本对象,该对象被保存下来在后续的扫描过程中使用;Thread用于管理脚本的执行,该类中也包含对脚本健全性的检查。在脚本执行时,如果脚本之间存在依赖关系,那么会将基础的无依赖的脚本统一执行完毕,再执行依赖性的脚本。
3)执行脚本扫描时,从nmap_main()中调用script_scan()函数。在进入script_scan()后,会标记扫描阶段类型,然后进入到初始化阶段返回的main()函数(来自nse_main.lua脚本中的main)中,在函数中解析具体的扫描类型。
4)main()函数负责处理三种类型的脚本扫描:预扫描(SCRIPT_PRE_SCAN)、脚本扫描(SCRIPT_SCAN)、后扫描 (SCRIPT_POST_SCAN)。预扫描即在Nmap调用的最前面(没有进行主机发现、端口扫描等操作)执行的脚本扫描,通常该类扫描用于准备基本的信息,例如到第三服务器查询相关的DNS信息。而脚本扫描,是使用NSE脚本来扫描目标主机,这是最核心的扫描方式。后扫描,是整个扫描结束后,做一些善后处理的脚本,比如优化整理某些扫描。
5)在main()函数中核心操作由run函数负责。而run()函数的本身设计用于执行所有同一级别的脚本(根据依赖关系划分的级别),直到所有线程执行完毕才退出。run()函数中实现三个队列:执行队列(Running Queue)、等待队列(Waiting Queue)、挂起队列(Pending Queue),并管理三个队列中线程的切换,直到全部队列为空或出错而退出。
三、Nmap API
数据传递
nmap.luadoc是与nmap内部函数交互和数据结构化的API,API提供目标主机的详细信息例如端口状态和版本探测结果;同时API也提供与Nsock交互的接口,这样方便我们自己写NSE脚本与服务器交互,目前文件中共48个函数。
在脚本引擎中,用户可以轻松访问Nmap已经了解的有关目标主机的信息。该数据作为参数传递给NSE脚本的action方法,参数host和port是lua表,其中包含脚本执行的目标的信息。下面介绍每个表里面所含有的变量。
nmap使用注册表来共享信息,每个脚本之间共享nmap.registry,每个主机还有自己的注册表名为host.registry;在整个扫描会话中,全局注册表始终存在。脚本可以使用它,例如,存储稍后将由postrule脚本显示的值。机注册表仅在主机被扫描时存在。它们可以用于将信息从一个脚本发送到另一个脚本。例如:1)ssh-hostkey脚本的portrule收集SSH密钥指纹,并将其存储在全局nmap.registry中,以便稍后可以由postrule打印。2)ssl-cert脚本收集SSL证书并将其存储在每个主机注册表中,以便ssl-google-cert-catalog脚本可以使用它们,而无需再次连接到服务器。nmap.registry是全局的,因此key选择很重要;使用另一个脚本结果的脚本必须使用dependencies变量来声明它,以确保先前的脚本首先运行。
host.ip
host.name 通过dns反向查询的主机名,如果没查到则为空串
host.targetname
host.reason: 给出host处于现在这个状态的解释
host.reason_ttl
host.mac_addr
host.directly_connected
host.mac_addr_next_hop
host.mac_addr_src
host.interface
host.interface_mtu
host.bin_ip
host.bin_ip_src
host.times
host.traceroute port.number
port.protocol: 有效值为tcp、udp
port.service: 字符串表示的运行在端口号上的服务,该服务由服务探测阶段探测出,如果 port.version.service_dtype字段是table,那么Nmap基于端口号猜测服务;如果不是table,那么版本探测阶段能够确定是什么服务,这个字段的值被设定为port.version.name
port.reason: 字符串解释处于port.state状态的原因。
port.reason_ttl
port.version: 这个字段是一个表格,包含版本探测阶段返回的全部信息,包括:name;name_confidence;等,具体可参考官方文档版本探测章节。
port.state 参考:https://nmap.org/book/nse-api.htm
Network I/O API
require("nmap")
-- 简单的使用Nsock连接服务器的例子
local socket = nmap.new_socket()
socket:set_timeout()
try = nmap.new_try(function() socket:close() end)
try(socket:connect(host.ip, port.number))
try(socket:send("login"))
response = try(socket:receive())
socket:close()
除此之外还有receive_bytes方法,receive_lines方法,receive_buf方法,可查看nmap.luadoc文件
除了Network的方式还有行包连接的方式:参考https://nmap.org/book/nse-api.html
四、编写自己的脚本的建议
编写NSE脚本,需要根据Nmap规范编写description,author,license,categories,rule,action字段的内容,其中主要是action字段的编写;如果rule函数返回结果为真,那么执行编写的action函数。
The Rule
这部分决定是否执行action函数,A prerule or a postrule 类型的脚本总是执行;在端口规则脚本里面,NSE仅给我们当前扫描端口的信息,比如一个脚本要执行,但是必须保证当前端口开启并且113端口开启,为了检测113端口是否开启,我们使用nmap.get_port_state这个函数,如果113端口没有被扫描,函数将返回nil。
portrule = function(host, port)
local auth_port = { number=, protocol="tcp" }
local identd = nmap.get_port_state(host, auth_port)
return identd ~= nil
and identd.state == "open"
and port.protocol == "tcp"
and port.state == "open"
end
The Action
脚本首先连接到我们探测的端口,通过调用nmap.new_socket创建两个套接字选项。接下来,我们定义一个错误处理捕获功能,如果检测到故障,则关闭这些套接字。此时我们可以安全地使用诸如打开,关闭,发送和接收的对象方法来在网络套接字上操作。在这种情况下,我们调用connect来建立连接。 NSE的异常处理机制用于避免过多的错误处理代码。 try用来包围可能出错的代码,如果有任何问题,这将调用catch函数。如果两个连接成功,我们构造一个查询字符串并解析响应,最后返回解析结果。
action = function(host, port)
local owner = ""
local client_ident = nmap.new_socket()
local client_service = nmap.new_socket()
local catch = function()
client_ident:close()
client_service:close()
end
local try = nmap.new_try(catch)
try(client_ident:connect(host.ip, ))
try(client_service:connect(host.ip, port.number))
local localip, localport, remoteip, remoteport =
try(client_service:get_info())
local request = port.number .. ", " .. localport .. "\r\n"
try(client_ident:send(request))
owner = try(client_ident:receive_lines())
if string.match(owner, "ERROR") then
owner = nil
else
owner = string.match(owner,
"%d+%s*,%s*%d+%s*:%s*USERID%s*:%s*.+%s*:%s*(.+)\r?\n")
end
try(client_ident:close())
try(client_service:close())
return owner
end
五、参考文献
https://nmap.org/changelog.html#7.50 Nmap各版本更新内容
https://nmap.org/book/nse-tutorial.html NSE编写指南
https://nmap.org/book/nse-api.html Nmap API
https://nmap.org/ Nmap官网
Nmap脚本引擎原理的更多相关文章
- Nmap脚本文件分析(AMQP协议为例)
Nmap脚本文件分析(AMQP协议为例) 一.介绍 上两篇文章 Nmap脚本引擎原理 编写自己的Nmap(NSE)脚本,分析了Nmap脚本引擎的执行过程,以及脚本文件的编写,这篇文章将以解析AMQ ...
- Nmap源码分析(脚本引擎)
Nmap提供了强大的脚本引擎(NSE),以支持通过Lua编程来扩展Nmap的功能.目前脚本库已经包含300多个常用的Lua脚本,辅助完成Nmap的主机发现.端口扫描.服务侦测.操作系统侦测四个基本功能 ...
- nmap 使用脚本引擎进行扫描
1.下载nmap(nmap官网). 2.安装nmap. 3.编辑环境变量(windows下所需),保存.
- nmap脚本扫描使用总结
nmap的脚本默认目录为:/usr/share/nmap/scripts/ Nmap提供的命令行参数如下 -sC: 等价于--script=default,使用默认类别的脚本进行扫描 可更换其他类别 ...
- C#脚本引擎 CS-Script 之(三)——如何部署
本文不但介绍了CS-Script如何部署,还介绍了CS-Script的部署后面的原理,并用一个框图详细介绍了部署中的各种细节. 一.获取资源 1.从官网上下载编译好的csscript资源:cs-scr ...
- 脚本AI与脚本引擎
Scripted AI and Scripting Engines 脚本AI与脚本引擎 This chapter discusses some of the techniques you can us ...
- nmap脚本使用总结
0x00 前言: nmap的基本介绍和基本使用方法,在乌云知识库中已经有人提交过,讲的比较详细,在此文中就不再讲述. 具体链接:http://drops.wooyun.org/tips/2002 本文 ...
- nmap脚本nse的使用
nmap脚本(nse)使用总结 0x01 nmap按脚本分类扫描 nmap脚本主要分为以下几类,在扫描时可根据需要设置--script=类别这种方式进行比较笼统的扫描: auth: 负责处理鉴权证书( ...
- nmap脚本(nse)使用总结
nmap脚本主要分为以下几类,在扫描时可根据需要设置--script=类别这种方式进行比较笼统的扫描: auth: 负责处理鉴权证书(绕开鉴权)的脚本 broadcast: 在局域网内探查更多服务 ...
随机推荐
- 使用HTML5地理位置定位到城市的方法及注意事项
介绍 本文将简述一下如何通过HTML5和百度地图开放平台提供的API来实现对浏览器的定位.实现效果为显示出用户所在的省市,即: XXX省 XXX市. 实现思路 利用HTML5 提供的API获取到用户的 ...
- [Monkey King]
题目描述 在一个森林里住着N(N<=10000)只猴子.在一开始,他们是互不认识的.但是随着时间的推移,猴子们少不了争斗,但那只会发生在互不认识(认识具有传递性)的两只猴子之间.争斗时,两只猴子 ...
- Gartner:当商业智能成熟度低时,如何加快分析采用率
文 | 水手哥 本文出自:知乎专栏<帆软数据应用研究院>--数据干货&资讯集中地 根据Gartner近7年的调查结果,71%的受访企业处于低成熟度阶段,也就是Gartner五级BI ...
- 【Java SE】利用Java的for循环加random制作小学试卷
前期介绍:很多同学以为学习一门编程语言,一定要学到很高深的时候才可以做项目,其实不然,很多时候我们不需要学到面向对象的思想,就可以从事一些小项目的开发,来增加自己对开发的热情,比如现在我就可以利用Ja ...
- JAVA并发编程实战---第三章:对象的共享(2)
线程封闭 如果仅仅在单线程内访问数据,就不需要同步,这种技术被称为线程封闭,它是实现线程安全性的最简单的方式之一.当某个对象封闭在一个线程中时,这种方法将自动实现线程安全性,即使被封闭的对象本生不是线 ...
- Brief introduction to Cassandra 【Cassandra简介】
From wikipedia https://en.wikipedia.org/wiki/CAP_theorem In theoretical computer science, the CAP t ...
- Spring——Web应用中的IoC容器创建(WebApplicationContext根应用上下文的创建过程)
基于Spring-4.3.7.RELEASE Spring的配置不仅仅局限在XML文件,同样也可以使用Java代码来配置.在这里我使用XML配置文件的方式来粗略地讲讲WebApplicationCon ...
- GD库知识点
GD库:PHP的一个扩展库,主要用于绘制动态图,根据数据动态响应的图片 如统计图 验证码 其他的用途如:处理已有图像 图片的缩放 裁剪 图片水印 文字水印 1.安装GD库 2.画图步骤:创建背景图像( ...
- 彻底搞清函数中的this指向
近日阅读<javascript设计模式与开发实践> 书中的apply和call调用函数层出不穷,很多妙用: 函数中的this是根据调用方式来决定的 函数调用方式有4中 1.直接调用 a(. ...
- cin 对象取值过程详解
突然又空,鉴于对cin对象的去值机制还不是很了解,就探究一番,并且记下来,方便以后复习. #include <iostream> int main(void) { using namesp ...