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: 在局域网内探查更多服务 ...
随机推荐
- FrameBuffer系列 之 一点资源
Iamonlyme的FrameBuffer编程实例http://download.csdn.net/detail/iamonlyme/6512955 light588的通过framebuffer直接写 ...
- css写出三角形(兼容IE)
css写出三角形 利用css写三角形,兼容IE7 .arrow-up { width:0px; height:0px; border-left:10px solid transparent; bo ...
- 纯css实现翻牌特效
大家有没有看到过网上很炫的翻牌效果,牌正面对着我们,然后点击一下,牌就被翻过来了,效果很酷炫,是不是很想知道是怎么实现的么,代码很简单,跟着小编往下走. 先给大家介绍一下翻牌的原理: 1.父容器设置设 ...
- iOS-SQLite(FMDB)
在已经存在的表中,添加字段,更新表结构 /** Test to see if particular column exists for particular table in database @pa ...
- 「七天自制PHP框架」第三天:PHP实现的设计模式
往期回顾:「七天自制PHP框架」第二天:模型与数据库,点击此处 原文地址:http://www.cnblogs.com/sweng/p/6624845.html,欢迎关注:编程老头 为什么要使用设计模 ...
- iis7 安装laravel5.4环境
laravel版本: Laravel5.4IIS版本:IIS7站点配置就不详细说啦,大家网上可以搜一坨很多的配置方法啦哈直接上图: 由于IIS没有像Apache.htaccess文件,创建一个Web. ...
- Jquery datatable 动态隐藏列(根据有无值)
一场景: 前端利用datatable初始化的时候会向后端调用数据,需求是 要动态的使某一列根据传回来的一个标志位是否有值来决定显示与否 这是当前传回值有活动优惠幅度的情况下 这是没有活动优惠的情况下 ...
- XML文件生成——借助JDOM
import java.io.* ; import org.jdom.* ; import org.jdom.output.* ; public class DOMDemo { public stat ...
- scauoj 18025 小明的密码 数位DP
18025 小明的密码 时间限制:4000MS 内存限制:65535K提交次数:0 通过次数:0 题型: 编程题 语言: G++;GCC Description 小明的密码由N(1<=N& ...
- Azure Messaging-ServiceBus Messaging消息队列技术系列-索引篇
Azure Messaging ServiceBus Messaging相关的技术系列,最近已经整理了不少了,统一做一个索引链接,置顶. 方便查找,并后续陆陆续续再增加. 学习消息队列技术,可以先看第 ...