注意: 这个文档可能需要审查 一个数据存储选项是用户可以设置的变量的一个类型,允许metasploit的各种组件在使用时更具有配置性.例子,在msfconsole,你能设置ConsoleLogging选项来记录所有控制台的输入输出的所有日志 -- 在渗透过程中方便文档记录的一种方法.当你载入一个模块,这个mixin或模块会注册更多选项.一些常见的有:用于服务器exploit或辅助模块的 RHOST 和 RPORT ,客户端模块的SRVHOST等等.准确找出可以设置的数据存储选项的最佳方法是通过使用以下命令
show options
- Shows you all the basic options.show advanced
- Shows you all the advanced options.show missing
- Shows you all the required options you have not configured.set
- Shows you everything. Obviously you also use this command to set an option.
用户如何查看数据储存选项:
在用户方面,数据储存选项 像全局或者模块级别:全局 意味全部模块都能使用该选项.可以使用setg
命令来设置.模块级别意味着只有你当前正在使用的模块会记住储存选项,没有其他的能记住.如果先加载模块,则需要设置模块级别选项,然后使用set
命令,像下面这样:
msf > use exploit/windows/smb/ms08_067_netapi
msf exploit(ms08_067_netapi) > set rhost 10.0.1.3
rhost => 10.0.1.3
metasploit开发者如何查看数据储存选项 在开发方面,事情有点疯狂.数据存储选项实际上可以在至少四个不同的来源中找到:the ModuleDataStore object, active_module, session object, or the framework object. 如果你只是进行模块开发.你能信任的最好的源是ModuleDataStore对象.这个对象有一个特定的加载顺序,然后把所需的选项交给你.如果这个选项可以在模块的数据存储中找到,它会给你这个选项。如果没有找到,它从一个框架给你一个.以下是如何读取模块中的数据存储选项的例子
current_host = datastore['RHOST']
如果你的开发工作在模块领域之外,那么很有可能你甚至没有ModuleDataStore对象。但是在一些情况,你仍然可以从驱动程序读取active_module accessor .或者如果你可以访问ModuleCommandDispatcher,有一个一个给你相同东西的mod
方法.有时mixin会在派发模块的时候会通过 run_simple
方法进行传递.比如,你可以看这个Msf::Ui::Console::CommandDispatcher::Auxiliary类
在一些情况就像在post exploit运行脚本,你可能没有 ModuleDataStore 或者 active_module,但是你应该仍然有一个session对象.应该有一个exploit_datastore
给你所有的数据储存选项
session.exploit_datastore
如果你无权访问模块或者session对象,最后的源显然是这个framework对象.并且这个framework对象总是存在.否则,像我们之前说的,如果用户设置一个 module-level 选项 没有其他的组件可以看到他,这引入框架对象
framework.datastore
所以现在你知道数据储存选项的多个来源.希望在这一点上,你清楚的认识到不是所有的源必然分享所有的东西.如果你尝试所有东西,像一个生成规则,这应该是你的载入顺序
- Try from the ModuleDataStore
- Try from active_module
- Try from session
- Try from framework
所有核心数据储存选项类型是定义在option_container.rb 文件.你应该总是挑选最合适的一个,因为每个都有自己的输入验证
那么你在数据注册阶段初始化一个选项,它应该遵循以下格式
OptSomething.new(option_name, [boolean, description, value])
- option_name -选项的名字
- boolean - 第一个属性,true的意思是这是一个必选的 false的意思是这是一个可选的
- description - 关于这个选项的短描述
- value - 一个默认值,注意如果第一个属性是false,你不需要提供这个值,它将会自动填充nil
现在让我们讨论关于什么类是可用的
- OptString - 通常用于字符串选项。如果输入以“file://”开头,则OptString也会自动假定这是一个文件,并从中读取。但是,在发生这种情况时没有文件路径验证,所以如果要加载文件,则应该使用OptPath,然后自己读取该文件。代码示例:
OptString.new('MYTEST', [ true, 'Set a MYTEST option', 'This is a default value' ])
-
OptRaw 实际上它的功能与OptString完全相同
-
OptBool - bool选项它将验证输入是true或者false.例如y, yes, n, no, 0, 1, 代码示例
OptBool.new('BLAH', [ true, 'Set a BLAH option', false ])
- OptEnum - 基本上这将限制输入到特定的选项。例如,如果您希望输入是
apple
或者orange
,而不是其他的.那么OptEnum就是您的选择。代码示例:
# Choices are: apple or range, defaults to apple
OptEnum.new('FRUIT', [ true, 'Set a fruit', 'apple', ['apple', 'orange']])
- OptPort -对于输入它意味着是用作端口号。这个数字应该在0 - 65535之间。代码示例:
OptPort.new('RPORT', [ true, 'Set a port', 21 ])
- OptAddress 作为IPv4地址的输入。代码示例:
OptAddress.new('IP', [ true, 'Set an IP', '10.0.1.3' ])
- OptAddressRange 作为IPv4地址的输入,例如:10.0.1.1-10.0.1.20或10.0.1.1/24。您也可以提供文件路径而不是范围,它会自动将该文件视为IP列表。或者,如果你使用rand:3语法,其中3意味着3次,它会为你生成3个随机IP。代码示例:
OptAddressRange.new('Range', [ true, 'Set an IP range', '10.0.1.3-10.0.1.23' ])
- OptPath 如果你的数据储存选项要求一个本地文件路径.请使用此选项。
OptPath.new('FILE', [ true, 'Load a local file' ])
- OptInt 它可以是一个16进制值或者10进制
OptInt.new('FILE', [ true, 'A hex or decimal', 1024 ])
- OptRegexp 是一个正则表达式数据存储选项。
OptRegexp.new('PATTERN', [true, 'Match a name', '^alien']),
Other types: 在某些情况下,可能没有适合您的数据存储选项类型。最好的例子是URL:即使没有OptUrl这样的东西,你可以做的是使用OptString类型,然后在你的模块中做一些验证,如下所示:
def valid?(input)
if input =~ /^http:\/\/.+/i
return true
else
# Here you can consider raising OptionValidateError
return false
end
end
if valid?(datastore['URL'])
# We can do something with the URL
else
# Not the format we're looking for. Refuse to do anything.
end
这register_options
方法可以注册多个基本数据存储选项。基本数据存储选项是必须配置的选项,例如服务器端漏洞中的RHOST选项。或者它是非常常用的,例如登录模块中的各种用户名/密码选项。
以下是在模块中注册多个数据存储选项的示例:
register_options(
[
OptString.new('SUBJECT', [ true, 'Set a subject' ]),
OptString.new('MESSAGE', [ true, 'Set a message' ])
], self.class)
这个register_advanced_options
方法 以注册多个高级数据存储选项。高级数据存储选项是在使用模块之前不需要用户配置的选项。例如,代理选项几乎总是被视为“高级”。但是,当然,这也意味着大多数用户会觉得难以配置。
注册高级选项的示例:
register_advanced_options(
[
OptInt.new('TIMEOUT', [ true, 'Set a timeout, in seconds', 60 ])
], self.class)
当一个数据存储选项已经被一个mixin注册时,仍然有办法改变模块的默认值。您可以使用register_options
方法,也可以在模块的元数据中添加一个DefaultOptions键。
使用register_options其中一个优点是,如果数据存储选项是高级的,这就允许它在基本选项菜单上,这意味着当人们在msfconsole上“show options”时,该选项将会在那里。您还可以更改选项说明,以及此方法是否必须。
当Metasploit初始化一个模块时,将会调用import_defaults
方法。此方法将更新所有现有的数据存储选项(这就是为什么register_options
可以用来更新默认值),然后它将专门检查模块元数据中的DefaultOptions键,并再次更新。
下面是一个使用DefaultOptions键的exploit模块初始化的例子:
def initialize(info={})
super(update_info(info,
'Name' => "Module name",
'Description' => %q{
This is an example of setting the default value of RPORT using the DefaultOptions key
},
'License' => MSF_LICENSE,
'Author' => [ 'Name' ],
'References' =>
[
[ 'URL', '' ]
],
'Platform' => 'win',
'Targets' =>
[
[ 'Windows', { 'Ret' => 0x41414141 } ]
],
'Payload' =>
{
'BadChars' => "\x00"
},
'DefaultOptions' =>
{
'RPORT' => 8080
},
'Privileged' => false,
'DisclosureDate' => "",
'DefaultTarget' => 0))
end
deregister_options
方法可以注销基本或高级选项。用法非常简单:
deregister_options('OPTION1', 'OPTION2', 'OPTION3')
目前,在运行时修改数据存储选项最安全的方法是重写一个方法。例如,一些mixins像这样检索RPORT选项:
def rport
datastore['RPORT']
end
在这种情况下,你可以从模块中覆盖这个rport方法,并返回一个不同的值
def rport
80
end
这样,当一个mixin想要这个信息的时候,最终的值是80,而不是实际的值datastore['RPORT']
正常选项总是大写,高级选项是驼峰式,规避选项是前缀::驼峰式