From 18ee35149a70ebc7411a1e128b7e16be8d49fd3c Mon Sep 17 00:00:00 2001 From: James Lee Date: Tue, 11 Jan 2011 17:53:24 +0000 Subject: [PATCH] move script mixin code into Post mixins and include them back in for backwards compatibility git-svn-id: file:///home/svn/framework3/trunk@11544 4d416f70-5f16-0410-b530-b9f4589650da --- lib/msf/core/post/file.rb | 101 +++++++++++++ lib/msf/core/post/windows/services.rb | 189 ++++++++++++++++++++++++ lib/msf/scripts/meterpreter/file.rb | 48 +----- lib/msf/scripts/meterpreter/registry.rb | 97 +----------- lib/msf/scripts/meterpreter/services.rb | 156 +------------------ 5 files changed, 299 insertions(+), 292 deletions(-) create mode 100644 lib/msf/core/post/file.rb create mode 100644 lib/msf/core/post/windows/services.rb diff --git a/lib/msf/core/post/file.rb b/lib/msf/core/post/file.rb new file mode 100644 index 0000000000..b22f75dc91 --- /dev/null +++ b/lib/msf/core/post/file.rb @@ -0,0 +1,101 @@ + +module Msf +class Post + +module File + + # + # Writes a given string to a file specified + # + def file_local_write(file2wrt, data2wrt) + if not ::File.exists?(file2wrt) + ::FileUtils.touch(file2wrt) + end + + output = ::File.open(file2wrt, "a") + data2wrt.each_line do |d| + output.puts(d) + end + output.close + end + + # + # Returns a MD5 checksum of a given local file + # + def file_local_digestmd5(file2md5) + if not ::File.exists?(file2md5) + raise "File #{file2md5} does not exists!" + else + require 'digest/md5' + chksum = nil + chksum = Digest::MD5.hexdigest(::File.open(file2md5, "rb") { |f| f.read}) + return chksum + end + end + + # + # Returns a SHA1 checksum of a given local file + # + def file_local_digestsha1(file2sha1) + if not ::File.exists?(file2sha1) + raise "File #{file2sha1} does not exists!" + else + require 'digest/sha1' + chksum = nil + chksum = Digest::SHA1.hexdigest(::File.open(file2sha1, "rb") { |f| f.read}) + return chksum + end + end + + # + # Returns a SHA256 checksum of a given local file + # + def file_local_digestsha2(file2sha2) + if not ::File.exists?(file2sha2) + raise "File #{file2sha2} does not exists!" + else + require 'digest/sha2' + chksum = nil + chksum = Digest::SHA256.hexdigest(::File.open(file2sha2, "rb") { |f| f.read}) + return chksum + end + end + + # + # Platform-agnostic file read. Returns contents of remote file +file_name+ + # as a String. + # + def read_file(file_name) + return false if file_name.length > 0 + + data = nil + if session.type == "meterpreter" + data = read_file_meterpreter(file_name) + elsif session.respond_to? :shell_command_token + data = session.shell_command_token("cat '#{file_name}'") + end + data + end + +protected + # + # Meterpreter-specific file read. Returns contents of remote file + # +file_name+ as a String + # + def read_file_meterpreter(file_name) + fd = session.fs.file.new(file_name, "rb") + data = '' + begin + until fd.eof? + data << fd.read + end + ensure + fd.close + end + data + end + +end + +end +end diff --git a/lib/msf/core/post/windows/services.rb b/lib/msf/core/post/windows/services.rb new file mode 100644 index 0000000000..c8d07f5cdb --- /dev/null +++ b/lib/msf/core/post/windows/services.rb @@ -0,0 +1,189 @@ + +module Msf +class Post + +module WindowsServices + + # + # List all Windows Services present. Returns an Array containing the names + # of the services. + # + def service_list + serviceskey = "HKLM\\SYSTEM\\CurrentControlSet\\Services" + threadnum = 0 + a =[] + services = [] + registry_enumkeys(serviceskey).each do |s| + if threadnum < 10 + a.push(::Thread.new(s) { |sk| + begin + srvtype = registry_getvaldata("#{serviceskey}\\#{sk}","Type").to_s + if srvtype =~ /32|16/ + services << sk + end + rescue + end + }) + threadnum += 1 + else + sleep(0.05) and a.delete_if {|x| not x.alive?} while not a.empty? + threadnum = 0 + end + end + + return services + end + + # + # Get Windows Service information. + # + # Information returned in a hash with display name, startup mode and + # command executed by the service. Service name is case sensitive. Hash + # keys are Name, Start, Command and Credentials. + # + def service_info(name) + service = {} + servicekey = "HKLM\\SYSTEM\\CurrentControlSet\\Services\\#{name.chomp}" + service["Name"] = registry_getvaldata(servicekey,"DisplayName").to_s + srvstart = registry_getvaldata(servicekey,"Start").to_i + if srvstart == 2 + service["Startup"] = "Auto" + elsif srvstart == 3 + service["Startup"] = "Manual" + elsif srvstart == 4 + service["Startup"] = "Disabled" + end + service["Command"] = registry_getvaldata(servicekey,"ImagePath").to_s + service["Creentials"] = registry_getvaldata(servicekey,"ObjectName").to_s + return service + end + + # + # Changes a given service startup mode, name must be provided and the mode. + # + # Mode is a string with either auto, manual or disable for the + # corresponding setting. The name of the service is case sensitive. + # + def service_change_startup(name,mode) + servicekey = "HKLM\\SYSTEM\\CurrentControlSet\\Services\\#{name.chomp}" + case mode.downcase + when "auto" then + registry_setvaldata(servicekey,"Start","2","REG_DWORD") + when "manual" then + registry_setvaldata(servicekey,"Start","3","REG_DWORD") + when "disable" then + registry_setvaldata(servicekey,"Start","4","REG_DWORD") + end + end + + # + # Create a service that runs it's own process. + # + # It takes as values the service name as string, the display name as + # string, the path of the executable on the host that will execute at + # startup as string and the startup type as an integer of 2 for Auto, 3 for + # Manual or 4 for Disable, default Auto. + # + def service_create(name, display_name, executable_on_host,startup=2) + adv = client.railgun.get_dll('advapi32') + manag = adv.OpenSCManagerA(nil,nil,0x13) + if(manag["return"] != 0) + # SC_MANAGER_CREATE_SERVICE = 0x0002 + newservice = adv.CreateServiceA(manag["return"],name,display_name, + 0x0010,0X00000010,startup,0,executable_on_host,nil,nil,nil,nil,nil) + adv.CloseServiceHandle(newservice["return"]) + adv.CloseServiceHandle(manag["return"]) + #SERVICE_START=0x0010 SERVICE_WIN32_OWN_PROCESS= 0X00000010 + #SERVICE_AUTO_START = 2 SERVICE_ERROR_IGNORE = 0 + if newservice["GetLastError"] == 0 + return true + else + return false + end + else + raise "Could not open Service Control Manager, Access Denied" + end + end + + # + # Start a service. + # + # Returns 0 if service started, 1 if service is already started and 2 if + # service is disabled. + # + def service_start(name) + adv = client.railgun.get_dll('advapi32') + manag = adv.OpenSCManagerA(nil,nil,1) + if(manag["return"] == 0) + raise "Could not open Service Control Manager, Access Denied" + end + #open with SERVICE_START (0x0010) + servhandleret = adv.OpenServiceA(manag["return"],name,0x10) + if(servhandleret["return"] == 0) + adv.CloseServiceHandle(manag["return"]) + raise "Could not Open Service, Access Denied" + end + retval = adv.StartServiceA(servhandleret["return"],0,nil) + adv.CloseServiceHandle(servhandleret["return"]) + adv.CloseServiceHandle(manag["return"]) + if retval["GetLastError"] == 0 + return 0 + elsif retval["GetLastError"] == 1056 + return 1 + elsif retval["GetLastError"] == 1058 + return 2 + end + end + + # + # Stop a service. + # + # Returns 0 if service is stopped successfully, 1 if service is already + # stopped or disabled and 2 if the service can not be stopped. + # + def service_stop(name) + adv = client.railgun.get_dll('advapi32') + manag = adv.OpenSCManagerA(nil,nil,1) + if(manag["return"] == 0) + raise "Could not open Service Control Manager, Access Denied" + end + #open with SERVICE_STOP (0x0020) + servhandleret = adv.OpenServiceA(manag["return"],name,0x30) + if(servhandleret["return"] == 0) + adv.CloseServiceHandle(manag["return"]) + raise "Could not Open Service, Access Denied" + end + retval = adv.ControlService(servhandleret["return"],1,56) + adv.CloseServiceHandle(servhandleret["return"]) + adv.CloseServiceHandle(manag["return"]) + if retval["GetLastError"] == 0 + return 0 + elsif retval["GetLastError"] == 1062 + return 1 + elsif retval["GetLastError"] == 1052 + return 2 + end + end + + # + # Delete a service by deleting the key in the registry. + # + def service_delete(name) + begin + basekey = "HKLM\\SYSTEM\\CurrentControlSet\\Services" + if registry_enumkeys(basekey).index(name) + servicekey = "HKLM\\SYSTEM\\CurrentControlSet\\Services\\#{name.chomp}" + registry_delkey(servicekey) + return true + else + return false + end + rescue::Exception => e + print_error(e) + return false + end + end +end + +end +end diff --git a/lib/msf/scripts/meterpreter/file.rb b/lib/msf/scripts/meterpreter/file.rb index df1c8bafee..be58b460fb 100644 --- a/lib/msf/scripts/meterpreter/file.rb +++ b/lib/msf/scripts/meterpreter/file.rb @@ -1,53 +1,11 @@ +require 'msf/core/post/file' + module Msf module Scripts module Meterpreter module Common - -#Writes a given string to a file specified -def file_local_write(file2wrt, data2wrt) - if not ::File.exists?(file2wrt) - ::FileUtils.touch(file2wrt) - end - output = ::File.open(file2wrt, "a") - data2wrt.each_line do |d| - output.puts(d) - end - output.close -end -#Returns a MD5 checksum of a given local file -def file_local_digestmd5(file2md5) - if not ::File.exists?(file2md5) - raise "File #{file2md5} does not exists!" - else - require 'digest/md5' - chksum = nil - chksum = Digest::MD5.hexdigest(::File.open(file2md5, "rb") { |f| f.read}) - return chksum - end -end -#Returns a SHA1 checksum of a given local file -def file_local_digestsha1(file2sha1) - if not ::File.exists?(file2sha1) - raise "File #{file2sha1} does not exists!" - else - require 'digest/sha1' - chksum = nil - chksum = Digest::SHA1.hexdigest(::File.open(file2sha1, "rb") { |f| f.read}) - return chksum - end -end -#Returns a SHA256 checksum of a given local file -def file_local_digestsha2(file2sha2) - if not ::File.exists?(file2sha2) - raise "File #{file2sha2} does not exists!" - else - require 'digest/sha2' - chksum = nil - chksum = Digest::SHA256.hexdigest(::File.open(file2sha2, "rb") { |f| f.read}) - return chksum - end -end +include ::Msf::Post::File end end diff --git a/lib/msf/scripts/meterpreter/registry.rb b/lib/msf/scripts/meterpreter/registry.rb index 6418537df7..68f1cb64fd 100644 --- a/lib/msf/scripts/meterpreter/registry.rb +++ b/lib/msf/scripts/meterpreter/registry.rb @@ -1,102 +1,11 @@ +require 'msf/core/post/registry' + module Msf module Scripts module Meterpreter module Common -#Returns the data and type of a given registry key and value -def registry_getvalinfo(key,valname) - value = {} - begin - root_key, base_key = client.sys.registry.splitkey(key) - open_key = client.sys.registry.open_key(root_key, base_key, KEY_READ) - v = open_key.query_value(valname) - value["Data"] = v.data - value["Type"] = v.type - open_key.close - end - return value -end -#Returns the data of a given registry key and value -def registry_getvaldata(key,valname) - value = nil - begin - root_key, base_key = client.sys.registry.splitkey(key) - open_key = client.sys.registry.open_key(root_key, base_key, KEY_READ) - v = open_key.query_value(valname) - value = v.data - open_key.close - end - return value -end -#Sets the data for a given value and type of data on the target registry returns true if succesful -def registry_setvaldata(key,valname,data,type) - begin - root_key, base_key = client.sys.registry.splitkey(key) - open_key = client.sys.registry.open_key(root_key, base_key, KEY_WRITE) - open_key.set_value(valname, client.sys.registry.type2str(type), data) - open_key.close - return true - end -end -#Deletes a registry value given the key and value name returns true if succesful -def registry_deleteval(key,valname) - begin - root_key, base_key = client.sys.registry.splitkey(key) - open_key = client.sys.registry.open_key(root_key, base_key, KEY_WRITE) - open_key.delete_value(valname) - open_key.close - return true - end -end -#Enumerates the values of a given registry key returns array of value names -def registry_enumvals(key) - values = [] - begin - vals = {} - root_key, base_key = client.sys.registry.splitkey(key) - open_key = client.sys.registry.open_key(root_key, base_key, KEY_READ) - vals = open_key.enum_value - vals.each { |val| - values << val.name - } - open_key.close - end - return values -end -#Enumerates the subkeys of a given registry key returns array of subkeys -def registry_enumkeys(key) - subkeys = [] - begin - root_key, base_key = client.sys.registry.splitkey(key) - open_key = client.sys.registry.open_key(root_key, base_key, KEY_READ) - keys = open_key.enum_key - keys.each { |subkey| - subkeys << subkey - } - open_key.close - end - return subkeys -end -#Create a given registry key returns true if succesful -def registry_createkey(key) - begin - root_key, base_key = client.sys.registry.splitkey(key) - open_key = client.sys.registry.create_key(root_key, base_key) - open_key.close - return true - end - -end -#Delete a given registry key returns true if succesful -def registry_delkey(key) - begin - root_key, base_key = client.sys.registry.splitkey(key) - open_key = client.sys.registry.delete_key(root_key, base_key) - open_key.close - return true - end - -end +include ::Msf::Post::Registry end end diff --git a/lib/msf/scripts/meterpreter/services.rb b/lib/msf/scripts/meterpreter/services.rb index 4e2b4a7d0f..bd6e0f3c4d 100644 --- a/lib/msf/scripts/meterpreter/services.rb +++ b/lib/msf/scripts/meterpreter/services.rb @@ -1,162 +1,12 @@ +require 'msf/core/post/windows/services' + module Msf module Scripts module Meterpreter module Common +include ::Msf::Post::WindowsServices - -#List all Windows Services present. Returns an Array containing the names of the services. -def service_list - serviceskey = "HKLM\\SYSTEM\\CurrentControlSet\\Services" - threadnum = 0 - a =[] - services = [] - registry_enumkeys(serviceskey).each do |s| - if threadnum < 10 - a.push(::Thread.new(s) { |sk| - begin - srvtype = registry_getvaldata("#{serviceskey}\\#{sk}","Type").to_s - if srvtype =~ /32|16/ - services << sk - end - rescue - end - }) - threadnum += 1 - else - sleep(0.05) and a.delete_if {|x| not x.alive?} while not a.empty? - threadnum = 0 - end - end - - return services -end -#Get Windows Service information. Information returned in a hash with display name, startup -#mode and command executed by the service. Service name is case sensitive. Hash keys are Name, -#Start, Command and Credentials. -def service_info(name) - service = {} - servicekey = "HKLM\\SYSTEM\\CurrentControlSet\\Services\\#{name.chomp}" - service["Name"] = registry_getvaldata(servicekey,"DisplayName").to_s - srvstart = registry_getvaldata(servicekey,"Start").to_i - if srvstart == 2 - service["Startup"] = "Auto" - elsif srvstart == 3 - service["Startup"] = "Manual" - elsif srvstart == 4 - service["Startup"] = "Disabled" - end - service["Command"] = registry_getvaldata(servicekey,"ImagePath").to_s - service["Creentials"] = registry_getvaldata(servicekey,"ObjectName").to_s - return service -end -#Changes a given service startup mode, name must be provided and the mode. Mode is a string with either -#auto, manual or disable for the corresponding setting. The name of the service is case sensitive. -def service_change_startup(name,mode) - servicekey = "HKLM\\SYSTEM\\CurrentControlSet\\Services\\#{name.chomp}" - case mode.downcase - when "auto" then - registry_setvaldata(servicekey,"Start","2","REG_DWORD") - when "manual" then - registry_setvaldata(servicekey,"Start","3","REG_DWORD") - when "disable" then - registry_setvaldata(servicekey,"Start","4","REG_DWORD") - end -end - -# Function for the creation of a service that runs it's own process. It takes as -# values the service name as string, the display name as string, the path of the -# executable on the host that will execute at startup as string and the startup -# type as an integer of 2 for Auto, 3 for Manual or 4 for Disable, default Auto. -def service_create(name, display_name, executable_on_host,startup=2) - adv = client.railgun.get_dll('advapi32') - manag = adv.OpenSCManagerA(nil,nil,0x13) - if(manag["return"] != 0) - # SC_MANAGER_CREATE_SERVICE = 0x0002 - newservice = adv.CreateServiceA(manag["return"],name,display_name, - 0x0010,0X00000010,startup,0,executable_on_host,nil,nil,nil,nil,nil) - adv.CloseServiceHandle(newservice["return"]) - adv.CloseServiceHandle(manag["return"]) - #SERVICE_START=0x0010 SERVICE_WIN32_OWN_PROCESS= 0X00000010 - #SERVICE_AUTO_START = 2 SERVICE_ERROR_IGNORE = 0 - if newservice["GetLastError"] == 0 - return true - else - return false - end - else - raise "Could not open Service Control Manager, Access Denied" - end -end -# Function for service startup, returns 0 if service started, 1 if service is -# already started and 2 if service is disabled. -def service_start(name) - adv = client.railgun.get_dll('advapi32') - manag = adv.OpenSCManagerA(nil,nil,1) - if(manag["return"] == 0) - raise "Could not open Service Control Manager, Access Denied" - end - #open with SERVICE_START (0x0010) - servhandleret = adv.OpenServiceA(manag["return"],name,0x10) - if(servhandleret["return"] == 0) - adv.CloseServiceHandle(manag["return"]) - raise "Could not Open Service, Access Denied" - end - retval = adv.StartServiceA(servhandleret["return"],0,nil) - adv.CloseServiceHandle(servhandleret["return"]) - adv.CloseServiceHandle(manag["return"]) - if retval["GetLastError"] == 0 - return 0 - elsif retval["GetLastError"] == 1056 - return 1 - elsif retval["GetLastError"] == 1058 - return 2 - end -end - - -# Function for stopping a service, returns 0 if service is stopped successfully, -# 1 if service is already stopped or disabled and 2 if the service can not be stopped. -def service_stop(name) - adv = client.railgun.get_dll('advapi32') - manag = adv.OpenSCManagerA(nil,nil,1) - if(manag["return"] == 0) - raise "Could not open Service Control Manager, Access Denied" - end - #open with SERVICE_STOP (0x0020) - servhandleret = adv.OpenServiceA(manag["return"],name,0x30) - if(servhandleret["return"] == 0) - adv.CloseServiceHandle(manag["return"]) - raise "Could not Open Service, Access Denied" - end - retval = adv.ControlService(servhandleret["return"],1,56) - adv.CloseServiceHandle(servhandleret["return"]) - adv.CloseServiceHandle(manag["return"]) - if retval["GetLastError"] == 0 - return 0 - elsif retval["GetLastError"] == 1062 - return 1 - elsif retval["GetLastError"] == 1052 - return 2 - end -end - -# Function for deleting service, by deleting the key in the registry. -def service_delete(name) - begin - basekey = "HKLM\\SYSTEM\\CurrentControlSet\\Services" - if registry_enumkeys(basekey).index(name) - servicekey = "HKLM\\SYSTEM\\CurrentControlSet\\Services\\#{name.chomp}" - registry_delkey(servicekey) - return true - else - return false - end - rescue::Exception => e - print_error(e) - return false - end -end end end end