This repository has been archived by the owner on Jan 29, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #74 from pasv/module_dev_paranoia
Invoke-Paranoia
- Loading branch information
Showing
2 changed files
with
171 additions
and
0 deletions.
There are no files selected for viewing
70 changes: 70 additions & 0 deletions
70
data/module_source/situational_awareness/host/Invoke-Paranoia.ps1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
function Invoke-Paranoia { | ||
param( | ||
[String[]] $watchUsers, | ||
[String[]] $watchProcesses, | ||
[String[]] $watchGroups | ||
|
||
) | ||
|
||
$defaultprocesses = @("taskmgr.exe", "mmc.exe", "wireshark.exe", "tcpview.exe", "procdump.exe", "procexp.exe", "procmon.exe", "netstat.exe", "psloggedon.exe", "logonsessions.exe", "processhacker.exe", "autoruns.exe", "autorunsc.exe") | ||
$watchProcesses = $watchProcesses + $defaultprocesses | ||
$defaultgroups = @("Domain Admins") | ||
$watchGroups = $watchGroups + $defaultgroups | ||
$groups_members = @{} | ||
|
||
function get_groupmembers { | ||
param([String[]] $groups) | ||
|
||
$root=([ADSI]"").distinguishedName | ||
$enumd_groups = @{} | ||
$groups | foreach { | ||
$to_search = $_ | ||
$enumd_groups.Add($to_search, @()) | ||
$group = [ADSI]("LDAP://CN=" + $to_search + ", CN=Users,$root") | ||
$group.member|foreach { | ||
$enumd_groups[$to_search] += $_.split(",")[0].split("=")[1] | ||
} | ||
} | ||
return $enumd_groups | ||
} | ||
|
||
function process_proc { | ||
param($proc,$group_members) | ||
$userdom = ($proc.getOwner().Domain + "\" + $proc.getOwner().User).tolower() | ||
$watchUsers | foreach { | ||
if ($userdom -eq $_.tolower()) { | ||
"USER_DETECTED: $userdom : "+ $proc.name + "`n" | ||
} | ||
if ($proc.getOwner().Domain.tolower() -eq $env:COMPUTERNAME -and $proc.getOwner().User.tolower() -eq $_) { | ||
"USER_DETECTED_LOCAL: $userdom : "+ $proc.name + "`n" | ||
} | ||
} | ||
foreach ($group in $group_members.keys) { | ||
foreach ($user in $group_members[$group]) { | ||
if ($proc.getOwner().User.tolower() -eq $user.tolower() -and $proc.getOwner().Domain -ne $env:COMPUTERNAME) { | ||
"USER_DETECTED_GROUP: $userdom : $group :" + $proc.name + "`n" | ||
} | ||
} | ||
} | ||
$watchProcesses | foreach { | ||
if($proc.name.tolower() -eq $_.tolower()) { | ||
"PROCESS_DETECTED: $userdom : " + $proc.name + "`n" | ||
} | ||
} | ||
Get-WmiObject Win32_LogicalDisk | Where-Object {($_.DriveType -eq 2) -and ($_.DeviceID -ne 'A:')} | %{ | ||
if( ($proc.path.split(":")[0]+":").tolower() -eq $_.DeviceID) { | ||
"USB_PROCESS_DETECTED: " + $proc.path + "`n" | ||
} | ||
} | ||
} | ||
|
||
$groups_members = get_groupmembers $watchGroups | ||
|
||
# Main loop | ||
while($True) { | ||
Sleep 3 | ||
Get-WmiObject win32_process | %{ | ||
process_proc -proc $_ -group_members $groups_members | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
from lib.common import helpers | ||
|
||
class Module: | ||
|
||
def __init__(self, mainMenu, params=[]): | ||
|
||
# metadata info about the module, not modified during runtime | ||
self.info = { | ||
'Name': 'Invoke-Paranoia', | ||
|
||
'Author': ['pasv'], | ||
|
||
'Description': ('Continuously check running processes for the presence of suspicious users, members of groups, process names, and for any processes running off of USB drives.'), | ||
|
||
'Background' : True, | ||
|
||
'OutputExtension' : None, | ||
|
||
'NeedsAdmin' : True, | ||
|
||
'OpsecSafe' : True, | ||
|
||
'MinPSVersion' : '2', | ||
|
||
'Comments': [ | ||
'http://shell.fishing/code/Invoke-Paranoia.ps1' | ||
] | ||
} | ||
|
||
# any options needed by the module, settable during runtime | ||
self.options = { | ||
# format: | ||
# value_name : {description, required, default_value} | ||
'Agent' : { | ||
# The 'Agent' option is the only one that MUST be in a module | ||
'Description' : 'Agent to deploy Paranoia on.', | ||
'Required' : True, | ||
'Value' : '' | ||
}, | ||
'WatchProcesses' : { | ||
'Description' : 'Process names to watch out for. Default list is already appended.', | ||
'Required' : False, | ||
'Value' : '' | ||
}, | ||
'WatchUsers' : { | ||
'Description' : 'Users to watch out for in the form of domain\user, domain\user2, localuser', | ||
'Required' : False, | ||
'Value' : '' | ||
}, | ||
'WatchGroups' : { | ||
'Description' : 'AD Groups to watch out for (Default is \'Domain Admins\')', | ||
'Required' : False, | ||
'Value' : '' | ||
} | ||
} | ||
|
||
# save off a copy of the mainMenu object to access external functionality | ||
# like listeners/agent handlers/etc. | ||
self.mainMenu = mainMenu | ||
|
||
# During instantiation, any settable option parameters | ||
# are passed as an object set to the module and the | ||
# options dictionary is automatically set. This is mostly | ||
# in case options are passed on the command line | ||
if params: | ||
for param in params: | ||
# parameter format is [Name, Value] | ||
option, value = param | ||
if option in self.options: | ||
self.options[option]['Value'] = value | ||
|
||
|
||
def generate(self): | ||
# if you're reading in a large, external script that might be updates, | ||
# use the pattern below | ||
# read in the common module source code | ||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/host/Invoke-Paranoia.ps1" | ||
try: | ||
f = open(moduleSource, 'r') | ||
except: | ||
print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) | ||
return "" | ||
|
||
moduleCode = f.read() | ||
f.close() | ||
|
||
script = moduleCode | ||
|
||
script += "Invoke-Paranoia " | ||
|
||
# add any arguments to the end execution of the script | ||
for option,values in self.options.iteritems(): | ||
if option.lower() != "agent": | ||
if values['Value'] and values['Value'] != '': | ||
if values['Value'].lower() == "true": | ||
# if we're just adding a switch | ||
script += " -" + str(option) | ||
else: | ||
script += " -" + str(option) + " " + str(values['Value']) | ||
|
||
return script |