Nmap NSE 库分析 >>> stdnse
https://nmap.org/nsedoc/lib/stdnse.html
0x00 简介
这个模块中都是一些小而有用的功能,他们不足以独立成模块,所以集成在这个标准库里
0x01 方法
函数名 |
功能介绍 |
---|---|
clock_ms () |
返回自纪元以来的当前时间(以毫秒为单位) |
clock_us () |
返回自纪元以来的当前时间(以微秒为单位) |
debug (level, fmt, ...) |
如果当前调试级别大于或等于给定级别,则打印格式化的调试消息。 |
format_mac (mac) |
将MAC地址格式化为以冒号分隔的十六进制字节。 |
format_output(status, data, indent) |
被弃用了 |
fromhex (hex) |
将十六进制字符串解码为原始字节 |
get_hostname(host) |
获取给定主机最可能的主机名。它可以是命令行中指定的目标,反向dns名称或简单的ip地址 |
get_script_args (..., Arguments) |
用来解析 --script-args 选项 |
get_timeout (host, max_timeout, min_timeout) |
返回主机的超时时间 |
make_buffer(socket, sep) |
这个就是一个迭代器,将socket接收到值根据 sep 进行分块,每次调用返回一块 |
module (name, ...) |
模拟Lua 5.1模块功能某些行为的模块功能 |
new_thread (main, ...) |
此功能使您可以创建工作线程,这些工作线程可以与脚本线程并行执行网络任务 |
output_table () |
返回一个表,该表按插入顺序保留元素,就是最后的输出表 |
parse_timespec(timespec) |
解析持续时间规范,该规范是一个数字,后跟一个单位,并返回秒数 |
pretty_printer (obj, printer) |
漂亮的Lua对象打印机 |
print_debug (level, fmt, ...) |
不推荐使用的debug()版本,目前保留该版本,以防止脚本ID被打印两次。脚本应使用debug()且不要传递SCRIPT_NAME |
print_verbose (level, fmt, ...) |
verbose()的不推荐使用的版本,保留至今,以防止脚本ID被打印两次。脚本应使用verbose()且不传递SCRIPT_NAME |
registry_add_array(subkeys, value, allow_duplicates) |
将一个值添加到registry的array中,并在必要时创建所有子项 |
registry_add_table(subkeys, key, value, allow_duplicates) |
这个是向 registry 的 table 中添加一个键值对 |
registry_get(subkeys) |
检查一个子键列表中每一层子键是不是都存在,如果不存在返回 nil |
seeall (env) |
更改环境以加载全局变量 |
silent_require () |
将 require 函数报错隐藏的执行 |
sleep (t) |
睡眠一段时间 |
string_or_blank(string, blank) |
判断如果是字符串为返回本身,不是返回 或者给定的参数 |
tobinary (n) |
转化成二进制数 |
tohex (s, options) |
转化成十六进制数 |
tooctal (n) |
转化成八进制数 |
verbose (level, fmt, ...) |
如果当前详细级别大于或等于给定级别,则打印格式化的详细消息 |
0x02 方法实战
0x001 debug
debug 函数为不定长参数,第一个参数为打印等级
如果当前调试级别大于或等于给定级别,则打印格式化的调试消息。这个函数是 nmap.log_write 的一个简单封装,第一个参数是打印等级,其余参数都是由 string.format 函数进行处理
如果已知,则输出包括一些基于上下文的信息:脚本标识符和目标ip /端口(如果有)。如果调试级别至少为2,则还将打印基本线程标识符以及它是工作线程还是主线程
0x002 print_debug
不推荐使用
0x003 verbose
verbose 是不定长参数
如果当前详细级别大于或等于给定级别,则打印格式化的详细消息。
0x004 make_buffer
make_buffer 函数有两个参数:socket, sep ,socket 参数是一个socket变量,sep为分隔符,返回值为读取到的块的数据以及错误信息
在http的脚本中没有用到这个函数的,在所有的脚本中,这个函数也用的较少,我们看一下吧
可以看到大家调用的时候sep参数基本都是 "n"、"r"、"rn"、"r?n",可以看到是用作获取相关分隔符分隔后的数据块
0x005 tobinary
tobinary 只有一个参数,待转换的数字,返回值为二进制字符串
---
--- Generated by EmmyLua(https://github.com/EmmyLua)
--- Created by root.
--- DateTime: 2020/1/2 上午9:39
---
local url = require "url"
local stdnse = require "stdnse"
description = [[
This is a test for http.lua's functions
]]
author = "test94"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"default"}
prerule = function()
print("functest running")
end
portrule = function () return true end --shortport.http
action = function(host, port)
local output = stdnse.output_table()
local demo = 35
local result = stdnse.tobinary(demo)
output.restype = type(result)
output.result = result
return output
end
测试一下
0x006 tooctal
tooctal 只有一个参数,这个参数为一个数字,返回一个八进制格式数字的字符串
---
--- Generated by EmmyLua(https://github.com/EmmyLua)
--- Created by root.
--- DateTime: 2020/1/2 上午9:39
---
local url = require "url"
local stdnse = require "stdnse"
description = [[
This is a test for http.lua's functions
]]
author = "test94"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"default"}
prerule = function()
print("functest running")
end
portrule = function () return true end --shortport.http
action = function(host, port)
local output = stdnse.output_table()
local demo = 64
local result = stdnse.tooctal(demo)
output.restype = type(result)
output.result = result
return output
end
测试一下
可以看到将十进制的 64 转换为 八进制的 100
0x007 tohex
tohex 函数有两个参数:s, options,返回值为16进制形式的字符串
- s 待转换的字符串或者数字
- options 这个是一个格式选项的表,表中字段 separator 为转化后的分隔符,最后返回值中会体现;字段 group 为分隔符之间每组数字的大小。默认值为2,但如果未同时提供 separator 则无效。
---
--- Generated by EmmyLua(https://github.com/EmmyLua)
--- Created by root.
--- DateTime: 2020/1/2 上午9:39
---
local url = require "url"
local stdnse = require "stdnse"
description = [[
This is a test for http.lua's functions
]]
author = "test94"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"default"}
prerule = function()
print("functest running")
end
portrule = function () return true end --shortport.http
action = function(host, port)
local output = stdnse.output_table()
local demo1 = "abc"
local demo2 = 123456
output.result_abc_sep_null_group_null = stdnse.tohex(demo1)
output.result_abc_sep_colon_group_null = stdnse.tohex(demo1, {separator = ":"})
output.result_abc_sep_colon_group_3 = stdnse.tohex(demo1, {separator = ":", group = 3})
output.result_123456_sep_null_group_null = stdnse.tohex(demo2)
output.result_123456_sep_colon_group_null = stdnse.tohex(demo2, {separator = ":"})
output.result_123456_sep_colon_group_3 = stdnse.tohex(demo2, {separator = ":", group = 3})
output.restype = type(output.result_123456_sep_colon_group_3)
return output
end
测试一下
可以看到, abc 被转换为 616263, 添加了分隔符后会按照默认的每两个字符来进行按照分隔符进行分隔返回,如果设置了分隔尺寸,则按照相关尺寸进行分隔。
0x008 fromhex
fromhex 只有一个参数,为16进制的字符串,该字符串可以包含任意数量的空格和大写或小写十六进制数字。十六进制数字必须是偶数,因为要用2个十六进制数字来构成一个字节。
---
--- Generated by EmmyLua(https://github.com/EmmyLua)
--- Created by root.
--- DateTime: 2020/1/2 上午9:39
---
local url = require "url"
local stdnse = require "stdnse"
description = [[
This is a test for http.lua's functions
]]
author = "test94"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"default"}
prerule = function()
print("functest running")
end
portrule = function () return true end --shortport.http
action = function(host, port)
local output = stdnse.output_table()
local demo = "534364"
local result = stdnse.fromhex(demo)
output.restype = type(result)
output.result = result
return output
end
测试一下
0x009 format_mac
format_mac 只有一个参数,参数为MAC地址二进制的字符串,比如 host.mac_addr, 返回值为 XX:XX:XX:XX:XX:XX 形式的字符串
上面这是 Nmap官方库的注释里写的,但是经过我的测试并不是这样,其实参数 MAC 是一个十进制数,假如我想得到一个正确的mac,我们需要将这个不带冒号的mac地址转换为10进制数,之后作为参数提交
---
--- Generated by EmmyLua(https://github.com/EmmyLua)
--- Created by root.
--- DateTime: 2020/1/2 上午9:39
---
local url = require "url"
local stdnse = require "stdnse"
description = [[
This is a test for http.lua's functions
]]
author = "test94"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"default"}
prerule = function()
print("functest running")
end
portrule = function () return true end --shortport.http
action = function(host, port)
local output = stdnse.output_table()
local demo = 20526534579951
local result = stdnse.format_mac(demo)
output.restype = type(result)
output.rawrest = demo
output.result = result
return output
end
测试一下
0x0010 string_or_blank
string_or_blank 有两个参数,string, blank,这个函数就是用来判断第一个参数是否为nil或者"" ,如果不是空则返回字符串本身,是空则返回第二个参数,第二个参数没有设置的时候返回 "" 字符串
---
--- Generated by EmmyLua(https://github.com/EmmyLua)
--- Created by root.
--- DateTime: 2020/1/2 上午9:39
---
local url = require "url"
local stdnse = require "stdnse"
description = [[
This is a test for http.lua's functions
]]
author = "test94"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"default"}
prerule = function()
print("functest running")
end
portrule = function () return true end --shortport.http
action = function(host, port)
local output = stdnse.output_table()
local demo1 = "test"
local result1 = stdnse.string_or_blank(demo1)
local demo2 = ""
local result2 = stdnse.string_or_blank(demo2, "this is blank")
output.restype = type(result1)
output.demo1 = demo1
output.result1 = result1
output.demo2 = demo2
output.result2 = result2
return output
end
测试一下
0x0011 parse_timespec
解析持续时间规范,该规范是一个数字,后跟一个单位,并返回秒数。
parse_timespec函数只有一个参数 timespec,这个参数是一个规范字符串,可以是以下格式:
- 10 --> 10
- 10ms --> 0.01
- 10s --> 10
- 10m --> 600
- 10h --> 36000
如果给定参数不是规范字符串,则返回 nil
---
--- Generated by EmmyLua(https://github.com/EmmyLua)
--- Created by root.
--- DateTime: 2020/1/2 上午9:39
---
local url = require "url"
local stdnse = require "stdnse"
description = [[
This is a test for http.lua's functions
]]
author = "test94"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"default"}
prerule = function()
print("functest running")
end
portrule = function () return true end --shortport.http
action = function(host, port)
local output = stdnse.output_table()
local res_10 = stdnse.parse_timespec("10")
local res_10ms = stdnse.parse_timespec("10ms")
local res_10s = stdnse.parse_timespec("10s")
local res_10m = stdnse.parse_timespec("10m")
local res_10h = stdnse.parse_timespec("10h")
output.restype = type(res_10h)
output.res_10 = res_10
output.res_10ms = res_10ms
output.res_10s = res_10s
output.res_10m = res_10m
output.res_10h = res_10h
return output
end
测试一下
0x0012 clock_ms
返回自纪元以来的当前时间(以毫秒为单位),无参数
---
--- Generated by EmmyLua(https://github.com/EmmyLua)
--- Created by root.
--- DateTime: 2020/1/2 上午9:39
---
local url = require "url"
local stdnse = require "stdnse"
description = [[
This is a test for http.lua's functions
]]
author = "test94"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"default"}
prerule = function()
print("functest running")
end
portrule = function () return true end --shortport.http
action = function(host, port)
local output = stdnse.output_table()
local result = stdnse.clock_ms()
output.restype = type(result)
output.result = result
return output
end
测试一下
0x0013 clock_us
返回自纪元以来的当前时间(以微秒为单位), 无参数
---
--- Generated by EmmyLua(https://github.com/EmmyLua)
--- Created by root.
--- DateTime: 2020/1/2 上午9:39
---
local url = require "url"
local stdnse = require "stdnse"
description = [[
This is a test for http.lua's functions
]]
author = "test94"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"default"}
prerule = function()
print("functest running")
end
portrule = function () return true end --shortport.http
action = function(host, port)
local output = stdnse.output_table()
local result = stdnse.clock_us()
output.restype = type(result)
output.result = result
return output
end
测试一下
0x0014 get_script_args
get_script_args 函数用来解析 --script-args ,不定长参数
这个函数非常重要且复杂,可能是我们以后经常用到的
---
--- Generated by EmmyLua(https://github.com/EmmyLua)
--- Created by root.
--- DateTime: 2020/1/2 上午9:39
---
local url = require "url"
local stdnse = require "stdnse"
description = [[
This is a test for http.lua's functions
]]
author = "test94"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"default"}
prerule = function()
print("functest running")
end
portrule = function () return true end --shortport.http
action = function(host, port)
local output = stdnse.output_table()
local functest_arg1, functest_arg2, functest_arg3, functest_arg4, functest_arg5 = stdnse.get_script_args("functest.arg1", "functest.arg2", "functest.arg3", "functest.arg4", "functest.arg5")
output.functest_arg1_type = type(functest_arg1)
output.functest_arg1_result = functest_arg1
output.functest_arg2_type = type(functest_arg2)
output.functest_arg2_result = functest_arg2
output.functest_arg3_type = type(functest_arg3)
output.functest_arg3_result = functest_arg3
output.functest_arg4_type = type(functest_arg4)
output.functest_arg4_result = functest_arg4
output.functest_arg4_type = type(functest_arg5)
output.functest_arg4_result = functest_arg5
return output
end
这里我定义了functest有五个参数,之后分别进行不同情况的测试
我们通过 --script-args 来进行参数传递,相关参数传递的值分别为
- functest.arg1 字符串 test1
- functest.arg2 一个表
- functest.arg3 未传递这个参数
- functest.arg4 传递了这个参数,未传递值
- functest.arg5 一个数字 2
得到的结果如下:
- functest.arg1 字符串 test1
- functest.arg2 一个表,{demo1,demo2}
- functest.arg3 nil
- functest.arg4 数字 1
- functest.arg5 字符串 2
可以得出结论
- 无论传递的是数字还是字符串都会被认定为字符串
- 如果传递的是一个表,得到结果也是一个表
- 如果要获取的参数没有传递,那么返回 nil
- 如果要获取的参数传递了,但是没有赋值,那么返回 1
通过以上结果可以事先做好类型定义以及异常处理
0x0015 get_hostname
获取给定主机的最可能的主机名。它可以是命令行中指定的目标,反向dns解析的名称或就是ip地址。
get_hostname 只有一个参数,参数为默认的 host, 返回值为最佳的 hostname 值
---
--- Generated by EmmyLua(https://github.com/EmmyLua)
--- Created by root.
--- DateTime: 2020/1/2 上午9:39
---
local http = require "http"
local stdnse = require "stdnse"
description = [[
This is a test for http.lua's functions
]]
author = "test94"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"default"}
prerule = function()
print("functest running")
end
portrule = function () return true end --shortport.http
action = function(host, port)
local output = stdnse.output_table()
local options = {header={}}
options["header"]["User-Agent"] = "function post test "
--local data = http.get(host, port, "/", options)
--local contain, content = http.response_contains(data,'[a-z](.+?)',false)
local result = stdnse.get_hostname(host)
output.restype = type(result)
output.result = result
return output
end
使用百度测试一下
可以看到返回值为字符串类型的hostname
0x0016 registry_get
registry_get 函数只有一个参数 subkeys ,是一个表,即子键
这个表中存放着要查询的子键,如果所有层子键都存在则返回最下层的值,如果有一个不存在就返回 nil
0x0017 registry_exists
registry_exists 函数有三个参数,subkeys, key, value
- subkeys 子键列表
- key 要查询的key
- value 要查询的 value
如果key,value键值对存在,那么返回 true,否则返回false
0x0018 registry_add_array
registry_add_array有三个参数:subkeys, value, allow_duplicates ,没有返回值
- subkeys 子键
- value 存储的值
- allow_duplicates 允许重复
---
--- Generated by EmmyLua(https://github.com/EmmyLua)
--- Created by root.
--- DateTime: 2020/1/2 上午9:39
---
local http = require "http"
local stdnse = require "stdnse"
local nmap = require "nmap"
description = [[
This is a test for http.lua's functions
]]
author = "test94"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"default"}
prerule = function()
print("functest running")
end
portrule = function () return true end --shortport.http
action = function(host, port)
local output = stdnse.output_table()
local result = stdnse.registry_add_array({'192.168.1.100', 'www', '80', 'pages'}, 'index.html')
output.restype = type(result)
output.result = result
output.reg = nmap.registry
return output
end
这里我们将返回值打印,将运行后的 nmap.registry 打印
从结果可以看到,这个函数并没有返回值,运行后的 nmap.registry 按照 subkeys的层级关系建立了一个数组,并将 value 的值存储到了其中
0x0019 registry_add_table
registry_add_table 与 registry_add_array 相似,有四个参数 subkeys, key, value, allow_duplicates,这个函数是向 nmap.registry 中的表中插入键值对
---
--- Generated by EmmyLua(https://github.com/EmmyLua)
--- Created by root.
--- DateTime: 2020/1/2 上午9:39
---
local http = require "http"
local stdnse = require "stdnse"
local nmap = require "nmap"
description = [[
This is a test for http.lua's functions
]]
author = "test94"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"default"}
prerule = function()
print("functest running")
end
portrule = function () return true end --shortport.http
action = function(host, port)
local output = stdnse.output_table()
local result = stdnse.registry_add_table({'192.168.1.100', 'www', '80', 'pages'}, 'index_page','index.html')
output.restype = type(result)
output.result = result
output.reg = nmap.registry
return output
end
测试一下
0x0020 output_table
这个函数应该就不用说了,咱们的每个代码都有这个,这就是一个输出表,会按照插入数据的顺序进行显示
0x0021 pretty_printer
pretty_printer 这个函数在nse中用的极少,可以使用下面命令进行查询
可以看到没有script 使用了这个函数
0x0022 get_timeout
get_timeout 函数有三个参数:host, max_timeout, min_timeout ,返回一个以毫秒为单位的适合传递给 set_timeout 的数字
- host 默认参数
- max_timeout 默认最大超时时间,默认 8000ms
- min_timeout 默认最小超时时间,默认 1000ms
---
--- Generated by EmmyLua(https://github.com/EmmyLua)
--- Created by root.
--- DateTime: 2020/1/2 上午9:39
---
local http = require "http"
local stdnse = require "stdnse"
local nmap = require "nmap"
description = [[
This is a test for http.lua's functions
]]
author = "test94"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"default"}
prerule = function()
print("functest running")
end
portrule = function () return true end --shortport.http
action = function(host, port)
local output = stdnse.output_table()
local result = stdnse.get_timeout(host, 4000, 1000)
output.restype = type(result)
output.result = result
output.host_timeout = host.times.timeout
return output
end
找一个美国的主机测试一下
- 数据库连接池-tomcat-jdbc食用笔记
- Java.NIO编程一览笔录
- Hbase 学习(三)Coprocessors
- Spring4+Spring MVC+MyBatis整合思路
- Zookeeper ACL权限配置及zkclient示例
- Spring Session 实现分布式会话管理
- 通过ambari安装hadoop集群(一)
- Hbase 学习(十) HBase Snapshots
- sqoop 常用命令整理(二)
- oozie 重新提交作业
- Hbase 学习(十一)使用hive往hbase当中导入数据
- WF追忆
- OpenCV和SVM分类器在自动驾驶中的车辆检测
- Hive Tunning(三) 最佳实践
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 第6章 Jenkins系统权限划分与授权管理
- Python爬虫新手教程: 知乎文章图片爬取器
- 《重构-代码整洁之道TypeScript版》第4天
- C++基础 杂记(一)
- 一种Cortex-M内核中的精确延时方法(ns级别)
- 算法集锦(17)|自然语言处理| 比特币市场情绪分析算法
- Linux匿名管道及实例
- 查找算法笔记(C++版)
- C++基础 指针使用注意
- FreeRTOS移植-基于STM32F407
- 感知机的股票预测算例及python代码实现 | 山人聊算法 | 5th
- C++基础 智能指针
- 排序算法笔记(C++版)
- 算法集锦(17) | 推荐系统 | 基于机器学习的商品定价系统
- C++基础 STL简介