Skip to content

Commit 8d49e44

Browse files
committed
Merge pull request EmpireProject#74 from pasv/module_dev_paranoia
Invoke-Paranoia
2 parents e62c586 + d6daa45 commit 8d49e44

File tree

2 files changed

+171
-0
lines changed

2 files changed

+171
-0
lines changed
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
function Invoke-Paranoia {
2+
param(
3+
[String[]] $watchUsers,
4+
[String[]] $watchProcesses,
5+
[String[]] $watchGroups
6+
7+
)
8+
9+
$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")
10+
$watchProcesses = $watchProcesses + $defaultprocesses
11+
$defaultgroups = @("Domain Admins")
12+
$watchGroups = $watchGroups + $defaultgroups
13+
$groups_members = @{}
14+
15+
function get_groupmembers {
16+
param([String[]] $groups)
17+
18+
$root=([ADSI]"").distinguishedName
19+
$enumd_groups = @{}
20+
$groups | foreach {
21+
$to_search = $_
22+
$enumd_groups.Add($to_search, @())
23+
$group = [ADSI]("LDAP://CN=" + $to_search + ", CN=Users,$root")
24+
$group.member|foreach {
25+
$enumd_groups[$to_search] += $_.split(",")[0].split("=")[1]
26+
}
27+
}
28+
return $enumd_groups
29+
}
30+
31+
function process_proc {
32+
param($proc,$group_members)
33+
$userdom = ($proc.getOwner().Domain + "\" + $proc.getOwner().User).tolower()
34+
$watchUsers | foreach {
35+
if ($userdom -eq $_.tolower()) {
36+
"USER_DETECTED: $userdom : "+ $proc.name + "`n"
37+
}
38+
if ($proc.getOwner().Domain.tolower() -eq $env:COMPUTERNAME -and $proc.getOwner().User.tolower() -eq $_) {
39+
"USER_DETECTED_LOCAL: $userdom : "+ $proc.name + "`n"
40+
}
41+
}
42+
foreach ($group in $group_members.keys) {
43+
foreach ($user in $group_members[$group]) {
44+
if ($proc.getOwner().User.tolower() -eq $user.tolower() -and $proc.getOwner().Domain -ne $env:COMPUTERNAME) {
45+
"USER_DETECTED_GROUP: $userdom : $group :" + $proc.name + "`n"
46+
}
47+
}
48+
}
49+
$watchProcesses | foreach {
50+
if($proc.name.tolower() -eq $_.tolower()) {
51+
"PROCESS_DETECTED: $userdom : " + $proc.name + "`n"
52+
}
53+
}
54+
Get-WmiObject Win32_LogicalDisk | Where-Object {($_.DriveType -eq 2) -and ($_.DeviceID -ne 'A:')} | %{
55+
if( ($proc.path.split(":")[0]+":").tolower() -eq $_.DeviceID) {
56+
"USB_PROCESS_DETECTED: " + $proc.path + "`n"
57+
}
58+
}
59+
}
60+
61+
$groups_members = get_groupmembers $watchGroups
62+
63+
# Main loop
64+
while($True) {
65+
Sleep 3
66+
Get-WmiObject win32_process | %{
67+
process_proc -proc $_ -group_members $groups_members
68+
}
69+
}
70+
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
from lib.common import helpers
2+
3+
class Module:
4+
5+
def __init__(self, mainMenu, params=[]):
6+
7+
# metadata info about the module, not modified during runtime
8+
self.info = {
9+
'Name': 'Invoke-Paranoia',
10+
11+
'Author': ['pasv'],
12+
13+
'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.'),
14+
15+
'Background' : True,
16+
17+
'OutputExtension' : None,
18+
19+
'NeedsAdmin' : True,
20+
21+
'OpsecSafe' : True,
22+
23+
'MinPSVersion' : '2',
24+
25+
'Comments': [
26+
'http://shell.fishing/code/Invoke-Paranoia.ps1'
27+
]
28+
}
29+
30+
# any options needed by the module, settable during runtime
31+
self.options = {
32+
# format:
33+
# value_name : {description, required, default_value}
34+
'Agent' : {
35+
# The 'Agent' option is the only one that MUST be in a module
36+
'Description' : 'Agent to deploy Paranoia on.',
37+
'Required' : True,
38+
'Value' : ''
39+
},
40+
'WatchProcesses' : {
41+
'Description' : 'Process names to watch out for. Default list is already appended.',
42+
'Required' : False,
43+
'Value' : ''
44+
},
45+
'WatchUsers' : {
46+
'Description' : 'Users to watch out for in the form of domain\user, domain\user2, localuser',
47+
'Required' : False,
48+
'Value' : ''
49+
},
50+
'WatchGroups' : {
51+
'Description' : 'AD Groups to watch out for (Default is \'Domain Admins\')',
52+
'Required' : False,
53+
'Value' : ''
54+
}
55+
}
56+
57+
# save off a copy of the mainMenu object to access external functionality
58+
# like listeners/agent handlers/etc.
59+
self.mainMenu = mainMenu
60+
61+
# During instantiation, any settable option parameters
62+
# are passed as an object set to the module and the
63+
# options dictionary is automatically set. This is mostly
64+
# in case options are passed on the command line
65+
if params:
66+
for param in params:
67+
# parameter format is [Name, Value]
68+
option, value = param
69+
if option in self.options:
70+
self.options[option]['Value'] = value
71+
72+
73+
def generate(self):
74+
# if you're reading in a large, external script that might be updates,
75+
# use the pattern below
76+
# read in the common module source code
77+
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/host/Invoke-Paranoia.ps1"
78+
try:
79+
f = open(moduleSource, 'r')
80+
except:
81+
print helpers.color("[!] Could not read module source path at: " + str(moduleSource))
82+
return ""
83+
84+
moduleCode = f.read()
85+
f.close()
86+
87+
script = moduleCode
88+
89+
script += "Invoke-Paranoia "
90+
91+
# add any arguments to the end execution of the script
92+
for option,values in self.options.iteritems():
93+
if option.lower() != "agent":
94+
if values['Value'] and values['Value'] != '':
95+
if values['Value'].lower() == "true":
96+
# if we're just adding a switch
97+
script += " -" + str(option)
98+
else:
99+
script += " -" + str(option) + " " + str(values['Value'])
100+
101+
return script

0 commit comments

Comments
 (0)