Module: Msf::Post::Windows::CliParse

Included in:
Registry
Defined in:
lib/msf/core/post/windows/cli_parse.rb

Defined Under Namespace

Classes: ParseError

Instance Method Summary collapse

Instance Method Details

#win_parse_error(results) ⇒ Object

Parses error output of some windows CLI commands and returns hash with the keys/vals detected always returns hash as follows but :errval only comes back from sc.exe using 'FAILED' keyword

Note, most of the time the :errval will be nil, it's not usually provided

sc.exe error example:

[SC] EnumQueryServicesStatus:OpenService FAILED 1060:

The specified service does not exist as an installed service.

returns:

{
  :error  => "The specified service does not exist as an installed service",
  :errval => 1060
}

reg.exe error example:

ERROR: Invalid key name.
Type "REG QUERY /?" for usage.

returns:

{
  :error  => "INVALID KEY NAME."
  :errval => nil
}

142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/msf/core/post/windows/cli_parse.rb', line 142

def win_parse_error(results)
  hashish = {
    :error => "Unknown Error",
    :errval => nil
  }
  # parse the results
  if ma = /^error:.*/i.match(results) # if line starts with Error: just pass to regular parser
    hashish.merge!(win_parse_results(ma[0].upcase)) #upcase required to satisfy regular parser
    # merge results.  Results from win_parse_results will override any duplicates in hashish
  elsif ma = /FAILED +[0-9]+/.match(results) # look for 'FAILED ' followed by some numbers
    sa = ma[0].split(' ')
    hashish[:errval] = sa[1].chomp.to_i
    # ^ intended to capture the numbers after the word 'FAILED' as [:errval]
    ma = /^[^\[\n].+/.match(results)
    hashish[:error] = ma[0].chomp.strip
    # above intended to capture first non-empty line not starting with '[' or \n into [:error]
  else
    # do nothing, defaults are good
  end
  return hashish
end

#win_parse_results(str) ⇒ Object

Parses output of some windows CLI commands and returns a hash with the keys/vals detected. If the item has multiple values, they will all be returned in the val separated by commas. Keys are downcased and symbolized (key.downcase.to_sym)

sc.exe example (somewhat contrived):

SERVICE_NAME: dumbservice
DISPLAY_NAME: KernelSmith Dumb Service - User-mode
TYPE               : 20  WIN32_SHARE_PROCESS
STATE              : 4  RUNNING
                        (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
START_TYPE         : 2   AUTO_START
BINARY_PATH_NAME   : C:\Windows\system32\svchost.exe -k LocalSystemNetworkRestricted
DEPENDENCIES       : PlugPlay
                   : DumberService
SERVICE_START_NAME : LocalSystem

returns:

{
  :service_name     => "dumbservice",
  :display_name     => "KernelSmith Dumb Service - User-mod",
  :state            => "4  RUNNING",
  :start_type       => "2   AUTO_START",
  :binary_path_name => "C:\Windows\system32\svchost.exe -k LocalSystemNetworkRestricted",
  :dependencies     => "PlugPlay,DumberService"
  <...etc...>
}

77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/msf/core/post/windows/cli_parse.rb', line 77

def win_parse_results(str)
  tip = false
  hashish = {}
  lastkey = nil
  str.each_line do |line|
    line.chomp!
    line.gsub!("\t",' ') # lose any tabs
    if (tip == true && line =~ /^ + :/)
      # then this is probably a continuation of the previous, let's append to previous
      # NOTE:  this will NOT pickup the (NOT_STOPPABLE, NOT_PAUSABLE), see next, but it
      # 	 will pickup when there's multiple dependencies
      arr = line.scan(/\w+/)
      val = arr.join(',') # join with commas, tho there is probably only one item in arr
      hashish[lastkey] << ",#{val}" # append to old val with preceding ','
      # if that's confusing, maybe:  hashish[lastkey] = "#{hashish[lastkey]},#{val}"
      tip = false
    elsif (tip == true && line =~ /^ + \(/)
      # then this is probably a continuation of the previous, let's append to previous
      # NOTE:  this WILL pickup (NOT_STOPPABLE, NOT_PAUSABLE) etc
      arr = line.scan(/\w+/) # put each "word" into an array
      val = arr.join(',') # join back together with commas in case comma wasn't the sep
      hashish[lastkey] << ",#{val}" # append to old val with preceding ','
      # if that's confusing, maybe:  hashish[lastkey] = "#{hashish[lastkey]},#{val}"
      tip = false
    elsif line =~ /^ *[A-Z]+[_]*[A-Z]+.*:/
      tip = true
      arr = line.split(':')
      k = arr[0].strip.downcase.to_sym
      # grab all remaining fields for hash val in case ':' present in val
      v = arr[1..-1].join(':').strip
      # now add this entry to the hash
      hashish[k] = v
      lastkey = k
    end
  end
  return hashish
end