lib/rex/post/meterpreter/extensions/extapi/adsi/adsi.rb
# -*- coding: binary -*-
module Rex
module Post
module Meterpreter
module Extensions
module Extapi
module Adsi
###
#
# This meterpreter extension contains extended API functions for
# querying and managing desktop windows.
#
###
class Adsi
def initialize(client)
@client = client
end
#
# Perform a generic domain query against ADSI.
#
# @param domain_name [String] The FQDN of the target domain.
# @param filter [String] The filter to apply to the query in
# LDAP format.
# @param max_results [Integer] The maximum number of results
# to return.
# @param page_size [Integer] The size of the page of results
# to return.
# @param fields [Array] Array of string fields to return for
# each result found
#
# @return [Hash] Array of field names with associated results.
#
def domain_query(domain_name, filter, max_results, page_size, fields)
request = Packet.create_request(COMMAND_ID_EXTAPI_ADSI_DOMAIN_QUERY)
request.add_tlv(TLV_TYPE_EXT_ADSI_DOMAIN, domain_name)
request.add_tlv(TLV_TYPE_EXT_ADSI_FILTER, filter)
request.add_tlv(TLV_TYPE_EXT_ADSI_MAXRESULTS, max_results)
request.add_tlv(TLV_TYPE_EXT_ADSI_PAGESIZE, page_size)
fields.each do |f|
request.add_tlv(TLV_TYPE_EXT_ADSI_FIELD, f)
end
response = client.send_request(request)
results = extract_results(response)
return {
:fields => fields,
:results => results
}
end
attr_accessor :client
protected
#
# Retrieve the results of the query from the response
# packet that was returned from Meterpreter.
#
# @param response [Packet] Reference to the received
# packet that was returned from Meterpreter.
#
# @return [Array[Array[[Hash]]] Collection of results from
# the ADSI query.
#
def extract_results(response)
results = []
response.each(TLV_TYPE_EXT_ADSI_RESULT) do |r|
results << extract_values(r)
end
results
end
#
# Extract a single row of results from a TLV group.
#
# @param tlv_container [Packet] Reference to the TLV
# group to pull the values from.
#
# @return [Array[Hash]] Collection of values from
# the single ADSI query result row.
#
def extract_values(tlv_container)
values = []
tlv_container.get_tlvs(TLV_TYPE_ANY).each do |v|
values << extract_value(v)
end
values
end
#
# Convert a single ADSI result value into a usable
# value that also describes its type.
#
# @param v [TLV] The TLV item that contains the value.
#
# @return [Hash] The type/value pair from the TLV.
#
def extract_value(v)
value = {
:type => :unknown
}
case v.type
when TLV_TYPE_EXT_ADSI_STRING
value = {
:type => :string,
:value => v.value
}
when TLV_TYPE_EXT_ADSI_NUMBER, TLV_TYPE_EXT_ADSI_BIGNUMBER
value = {
:type => :number,
:value => v.value
}
when TLV_TYPE_EXT_ADSI_BOOL
value = {
:type => :bool,
:value => v.value
}
when TLV_TYPE_EXT_ADSI_RAW
value = {
:type => :raw,
:value => v.value
}
when TLV_TYPE_EXT_ADSI_ARRAY
value = {
:type => :array,
:value => extract_values(v.value)
}
when TLV_TYPE_EXT_ADSI_PATH
value = {
:type => :path,
:volume => v.get_tlv_value(TLV_TYPE_EXT_ADSI_PATH_VOL),
:path => v.get_tlv_value(TLV_TYPE_EXT_ADSI_PATH_PATH),
:vol_type => v.get_tlv_value(TLV_TYPE_EXT_ADSI_PATH_TYPE)
}
when TLV_TYPE_EXT_ADSI_DN
values = v.get_tlvs(TLV_TYPE_ALL)
value = {
:type => :dn,
:label => values[0].value
}
if values[1].type == TLV_TYPE_EXT_ADSI_STRING
value[:string] = value[1].value
else
value[:raw] = value[1].value
end
end
value
end
end
end; end; end; end; end; end