· 10 years ago · May 03, 2016, 04:03 AM
1#Requires -Version 3
2
3#[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
4
5$TOOL_NAME = "Torque"
6$TOOL_VERSION = "1.4.0.1"
7
8$Global:CONF = @{ 'USING_INTERNET' = $false #Modify if they will be downloading or uploading files
9 'SCHEDULE_TASK' = $false #Modify to schedule recurring runs automatically (requires local admin acccess)
10 'AD_DOMAINS' = $false #Set to $false to auto-detect domain controllers. Otherwise, value should be a comma-separated string - e.g. "dc.domain1.local,dc.domain2.local"
11 'AD_FULL_COLLECT' = $false #Modify this if we cannot collect the entire db for users, computers, and groups
12 'USING_SCCM' = $false
13 'TOOL_NAME' = $TOOL_NAME
14 'TOOL_VERSION' = $TOOL_VERSION
15 'PROGRAM_PATH' = $false
16 'WEB_ORG_ID' = $false #Modify if $USING_INTERNET is set to $true, it will contain the orgId to push data to.
17 'WEB_MULTIPASS_TOKEN' = $false #Modify if $USING_INTERNET is set to $true, it will contain the multipass token
18 'WEB_UL_DIR' = $false #Modify if they will be shipping us the data and $USING_INTERNET is $true - e.g. "https://instance.palantircloud.com"
19 'WEB_COMPUTE' = $true #Set to $false if you don't want Torque to handle COMPUTING on the endpoint
20 'WEB_UL_ONLY' = $false #Set to $true if you want to only ship data off from the Exports directory
21 'WEB_DEL_AFTER_UL' = $true #Set to $false if you don't want to delete the data after upload.
22 'SCCM' = @{ 'SCCM_2007' = @{ 'USING' = $false
23 'VERSION' = $false
24 'WIN_AUTH' = $false
25 'SCCM_SRV' = $false
26 'SCCM_DB' = $false
27 'SCCM_CREDS' = @{ 'USER' = $false
28 'PASS' = $false
29 }
30 }
31 'SCCM_2012' = @{ 'USING' = $false
32 'VERSION' = $false
33 'WIN_AUTH' = $false
34 'SCCM_SRV' = $false
35 'SCCM_DB' = $false
36 'SCCM_CREDS' = @{ 'USER' = $false
37 'PASS' = $false
38 }
39 }
40 }
41 }
42
43Add-Type -typedef @"
44 using System;
45 using System.Net;
46
47 public class MyWebClient : WebClient
48 {
49 protected override WebRequest GetWebRequest(Uri uri)
50 {
51 WebRequest w = base.GetWebRequest(uri);
52 w.Timeout = 20 * 60 * 1000;
53 return w;
54 }
55 }
56"@
57
58function Check-Privs{
59<#
60 .SYNOPSIS
61
62 Checks to see if we have admin privileges in the script
63
64 .EXAMPLE
65
66 Check-Privs
67#>
68 $user = [Security.Principal.WindowsIdentity]::GetCurrent()
69 (New-Object Security.Principal.WindowsPrincipal $user).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
70}
71
72function Get-Config {
73<#
74 .SYNOPSIS
75
76 Grabs Configuration from $XML_CONFIG and outputs the results into hash list ($Global:CONF)
77
78 .EXAMPLE
79
80 Get-Config
81#>
82 Write-Host "Grabbing Configuration from XML file" -ForegroundColor Green
83 $ans = Test-Path -Path $XML_CONF -ErrorAction SilentlyContinue
84 if (-not $ans){return $false}
85
86 [xml]$xmlDoc = Get-Content -Path $XML_CONF
87
88 #will make this dynamic later
89 $Global:CONF.SCCM.SCCM_2007.USING = [System.Convert]::ToBoolean($xmlDoc.Configuration.SCCM.SCCM_2007.USING.Trim())
90 $Global:CONF.SCCM.SCCM_2007.WIN_AUTH = [System.Convert]::ToBoolean($xmlDoc.Configuration.SCCM.SCCM_2007.WIN_AUTH.Trim())
91 $Global:CONF.SCCM.SCCM_2007.SCCM_SRV = $xmlDoc.Configuration.SCCM.SCCM_2007.SCCM_SRV.Trim()
92 $Global:CONF.SCCM.SCCM_2007.VERSION = $xmlDoc.Configuration.SCCM.SCCM_2007.VERSION.Trim()
93 $Global:CONF.SCCM.SCCM_2007.SCCM_DB = $xmlDoc.Configuration.SCCM.SCCM_2007.SCCM_DB.Trim()
94 $Global:CONF.SCCM.SCCM_2007.SCCM_CREDS.USER = $xmlDoc.Configuration.SCCM.SCCM_2007.SCCM_CREDS.USER.Trim()
95 $Global:CONF.SCCM.SCCM_2007.SCCM_CREDS.PASS = $xmlDoc.Configuration.SCCM.SCCM_2007.SCCM_CREDS.PASS.Trim()
96 $Global:CONF.SCCM.SCCM_2012.USING = [System.Convert]::ToBoolean($xmlDoc.Configuration.SCCM.SCCM_2012.USING.Trim())
97 $Global:CONF.SCCM.SCCM_2012.WIN_AUTH = [System.Convert]::ToBoolean($xmlDoc.Configuration.SCCM.SCCM_2012.WIN_AUTH.Trim())
98 $Global:CONF.SCCM.SCCM_2012.SCCM_SRV = $xmlDoc.Configuration.SCCM.SCCM_2012.SCCM_SRV.Trim()
99 $Global:CONF.SCCM.SCCM_2012.VERSION = $xmlDoc.Configuration.SCCM.SCCM_2012.VERSION.Trim()
100 $Global:CONF.SCCM.SCCM_2012.SCCM_DB = $xmlDoc.Configuration.SCCM.SCCM_2012.SCCM_DB.Trim()
101 $Global:CONF.SCCM.SCCM_2012.SCCM_CREDS.USER = $xmlDoc.Configuration.SCCM.SCCM_2012.SCCM_CREDS.USER.Trim()
102 $Global:CONF.SCCM.SCCM_2012.SCCM_CREDS.PASS = $xmlDoc.Configuration.SCCM.SCCM_2012.SCCM_CREDS.PASS.Trim()
103 $Global:CONF.AD_DOMAINS = $xmlDoc.Configuration.AD_DOMAINS.Trim()
104 $Global:CONF.TOOL_NAME = $xmlDoc.Configuration.TOOL_NAME.Trim()
105 $Global:CONF.TOOL_VERSION = $xmlDoc.Configuration.TOOL_VERSION.Trim()
106 $Global:CONF.PROGRAM_PATH = $xmlDoc.Configuration.PROGRAM_PATH.Trim()
107 $Global:CONF.SCHEDULE_TASK = [System.Convert]::ToBoolean($xmlDoc.Configuration.SCHEDULE_TASK.Trim())
108 $Global:CONF.USING_INTERNET = [System.Convert]::ToBoolean($xmlDoc.Configuration.USING_INTERNET.Trim())
109 $Global:CONF.AD_FULL_COLLECT = [System.Convert]::ToBoolean($xmlDoc.Configuration.AD_FULL_COLLECT.Trim())
110 $Global:CONF.WEB_DEL_AFTER_UL = [System.Convert]::ToBoolean($xmlDoc.Configuration.WEB_DEL_AFTER_UL.Trim())
111 $Global:CONF.WEB_UL_ONLY = [System.Convert]::ToBoolean($xmlDoc.Configuration.WEB_UL_ONLY.Trim())
112 $Global:CONF.WEB_COMPUTE = [System.Convert]::ToBoolean($xmlDoc.Configuration.WEB_COMPUTE.Trim())
113 $Global:CONF.WEB_UL_DIR = $xmlDoc.Configuration.WEB_UL_DIR.Trim()
114 $Global:CONF.WEB_ORG_ID = $xmlDoc.Configuration.WEB_ORG_ID.Trim()
115 $Global:CONF.WEB_MULTIPASS_TOKEN = $xmlDoc.Configuration.WEB_MULTIPASS_TOKEN.Trim()
116
117 return $true
118}
119
120function Helper-CreateDirectory{
121<#
122 .SYNOPSIS
123
124 Quick helper function to create a directory to include the checks needed to be made.
125
126 .PARAMETER Path
127
128 Path of the directory to create. This is a required field
129
130 .EXAMPLE
131
132 Helper-CreateDirectory -Path C:\windows\temp\data
133#>
134 [CmdletBinding()]
135 Param (
136 [Parameter(Mandatory=$true)]
137 [string]$Path
138 )
139
140 $ans = Test-Path -Path $Path
141 if (-not $ans){New-Item -ItemType directory -Path $Path | Out-Null}
142 return $Path
143}
144
145function Helper-HashTableToXml {
146<#
147 .SYNOPSIS
148
149 Helper function to convert a hashtable to xml file
150
151 .PARAMETER Root
152
153 The root of the XML hierachy structure.
154
155 .PARAMETER InputObject
156
157 Hashtable that you want to convert to XML
158
159 .PARAMETER Path
160
161 XML File that you want to create
162
163 .EXAMPLE
164
165 Helper-HashTableToXml -Root Configuration -InputObject $Global:CONF -Path C:\windows\temp\file.xml
166
167 This will take the $Global:CONF object and convert it to XML and set the root to "Configuration".
168 It will then write this XML object to a file (C:\windows\temp\file.xml)
169#>
170 [cmdletbinding()]
171 Param(
172 [ValidateNotNullOrEmpty()]
173 [System.String]$Root,
174
175 [Parameter(ValueFromPipeline = $true, Position = 0)]
176 [System.Collections.Hashtable]$InputObject,
177
178 [ValidateScript({Test-Path $_ -IsValid})]
179 [System.String]$Path
180 )
181
182 Begin{
183 $ScriptBlock = {
184 Param($Elem, $Root)
185 if( $Elem.Value -is [System.Collections.Hashtable] ){
186 $RootNode = $Root.AppendChild($Doc.CreateNode([System.Xml.XmlNodeType]::Element,$Elem.Key,$Null))
187 $Elem.Value.GetEnumerator() | ForEach-Object {
188 $Scriptblock.Invoke( @($_, $RootNode) )
189 }
190 }
191 else{
192 $Element = $Doc.CreateElement($Elem.Key)
193 $Element.InnerText = if($Elem.Value -is [Array]) {
194 $Elem.Value -join ','
195 }
196 else{
197 $Elem.Value | Out-String
198 }
199 $Root.AppendChild($Element) | Out-Null
200 }
201 }
202 }
203
204 Process{
205 $Doc = [xml]"<$($Root)></$($Root)>"
206 $InputObject.GetEnumerator() | ForEach-Object {
207 $scriptblock.Invoke( @($_, $doc.DocumentElement) )
208 }
209 $doc.Save($Path)
210 }
211}
212
213function Helper-InstallSCCM{
214<#
215 .SYNOPSIS
216
217 Helper function to install all required software for SCCM queries to function. Should only
218 be called by Invoke-Install
219
220 .EXAMPLE
221
222 Helper-InstallSCCM
223#>
224 $sccmWinAuth = Helper-QuestionYn -Question "Are we using Windows Authentication?" -YesHelp "Will use current token" -NoHelp "Will prompt for credentials"
225 if (-not $sccmWinAuth){
226 $creds = Get-Credential
227 $user = $creds.UserName
228 $password = $creds.Password | ConvertFrom-SecureString
229 }
230 $sccmSrv = Helper-QuestionShortAns -Question "Enter the location of the SCCM Server"
231
232 Log-Write -LogPath $LOG_FILE -LineValue "`t[*] Validating Settings"
233
234 #Running automated checks on SCCM
235 if($sccmWinAuth) {
236 $database = (Invoke-SqlCmds -Server $sccmSrv -WriteToFile 0 -Queries @{'FIND_DATABASE' = "SELECT name FROM Sys.Databases WHERE name LIKE 'CM_%' AND state_desc = 'ONLINE'"}).name
237 if (-not $database){return $false}
238 $userPrivs = Invoke-SqlCmds -Server $sccmSrv -Database $database -WriteToFile 0 -Queries @{'VALIDATE_PERMISSIONS' = "SELECT * FROM fn_my_permissions (NULL, 'DATABASE')"}
239 $sccmVer = Invoke-SqlCmds -Server $sccmSrv -Database $database -WriteToFile 0 -Queries @{'SCCM_VERSION' = "SELECT DISTINCT TOP 1 LEFT(Client_Version0,CHARINDEX('.',Client_Version0)-1) Version0 FROM v_R_System WHERE Client_Version0 IS NOT NULL ORDER BY Version0 DESC"}
240 } else {
241 $database = Invoke-SqlCmds -Server $sccmSrv -WriteToFile 0 -Queries @{'FIND_DATABASE' = "SELECT name FROM Sys.Databases WHERE name LIKE 'CM_%' AND state_desc = 'ONLINE'"}
242 if (-not $database){return $false}
243 $userPrivs = Invoke-SqlCmds -Server $sccmSrv -Database $database -WriteToFile 0 -Queries @{'VALIDATE_PERMISSIONS' = "SELECT * FROM fn_my_permissions (NULL, 'DATABASE')"} -User $user -Password $password
244 $sccmVer = Invoke-SqlCmds -Server $sccmSrv -Database $database -WriteToFile 0 -Queries @{'SCCM_VERSION' = "SELECT DISTINCT TOP 1 LEFT(Client_Version0,CHARINDEX('.',Client_Version0)-1) Version0 FROM v_R_System WHERE Client_Version0 IS NOT NULL ORDER BY Version0 DESC"} -User $user -Password $password
245 }
246
247 $databaseIp = ([System.Net.Dns]::GetHostAddresses($sccmSrv)).IPAddressToString
248 Log-Write -LogPath $LOG_FILE -LineValue "`t`t[*] SCCM Database is $database"
249 Log-Write -LogPath $LOG_FILE -LineValue "`t`t[*] SCCM Database IP is $databaseIp"
250
251 if (-not $userPrivs.permission_name.contains("SELECT") ){
252 Log-Error -LogPath $LOG_FILE -ErrorDesc "`[!] You currently do not have the appropriate permissions, Please have a dba add db_datareader to your permissions"
253 return $false
254 }else{
255 $version = $sccmVer.Version0
256 Log-Write -LogPath $LOG_FILE -LineValue "`t`t[*] SCCM Version is $version"
257 }
258
259 if ($sccmVer.Version0 -eq 5){$version = 'SCCM_2012'
260 }elseif ($sccVer.Version0 -eq 4){$version = 'SCCM_2007'}
261
262 $Global:CONF.SCCM.$version.USING = $true
263 $Global:CONF.SCCM.$version.VERSION = $sccmVer.Version0
264 $Global:CONF.SCCM.$version.WIN_AUTH = $sccmWinAuth
265 $Global:CONF.SCCM.$version.SCCM_SRV = $sccmSrv
266 $Global:CONF.SCCM.$version.SCCM_DB = $database
267 if (-NOT $sccmWinAuth){
268 $Global:CONF.SCCM.$version.SCCM_CREDS.USER = $user
269 $Global:CONF.SCCM.$version.SCCM_CREDS.PASS = $password
270 }
271}
272
273function Helper-InstallPersistance{
274<#
275 .SYNOPSIS
276
277 Helper function to setup persistance via Schtasks. This is Powershell Version 2 complaint.
278
279 .EXAMPLE
280
281 Helper-InstallPersistance
282#>
283 Log-Write -LogPath $LOG_FILE -LineValue "[+] Creating Persistance via SchTasks"
284 $currentUser = [Environment]::UserName
285 $creds = Get-Credential -Message "Enter credentials for the user the account that will be making the queries" -UserName $currentUser
286
287 $scriptPath = $Global:CONF.PROGRAM_PATH + "\$TOOL_NAME.ps1"
288 &schtasks /Delete /TN $TOOL_NAME /F 2>&1| Out-Null
289
290 $password = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($creds.Password))
291 &schtasks /Create /SC daily /TN $TOOL_NAME /ST 00:02 /TR "powershell.exe `"'$scriptPath'`"" /RU $creds.UserName /RP $password
292
293 $job = schtasks /query /tn $TOOL_NAME /v /fo csv |convertfrom-csv
294 $jobSplit = $job -split ";"
295 Log-Write -LogPath $LOG_FILE -LineValue "`t[+] Added new job: $TOOL_NAME"
296 ForEach ($j in $jobSplit){Log-Write -LogPath $LOG_FILE -LineValue "`t`t[*] $j"}
297}
298
299function Helper-InstallProgramPath{
300<#
301 .SYNOPSIS
302
303 Helper function to setup the programs folder structure. Should only
304 be called by Invoke-Install
305
306 .EXAMPLE
307
308 Helper-InstallProgramPath
309#>
310 [CmdletBinding()]
311 Param (
312 [Parameter(Mandatory=$true)]
313 [string]$Directory = $env:ProgramFiles + "\$TOOL_NAME"
314 )
315
316 while ($true){
317 $ans = Test-Path -Path $Directory
318 if ($ans){
319 $startFresh = Helper-QuestionYn -Question "$Directory already exists, do you want to blow away the contents in it" -NoHelp "Will use the config files in there" `
320 -YesHelp "Will erase everthing in that directory and start fresh"
321 if ($startFresh){
322 try{Remove-Item -Path $Directory -Recurse; continue}
323 catch{Write-Host "Directory cannot be deleted, please manually delete the contents or try a different location" -ForegroundColor Red}
324 return $false
325 }else{return $true}
326 }else{
327 try{
328 New-Item -ItemType directory -Path $Directory -ErrorAction Stop | Out-Null
329 return $true
330 }catch [exception]{
331 Write-Host "Directory cannot be created, please try a different location" -ForegroundColor Red
332 return $false
333 }
334 }
335 }
336}
337
338function Helper-QueryAD{
339<#
340 .SYNOPSIS
341
342 Helper function to run all Active Directory queries. It should only be ran from Invoke-Execute.
343
344 .EXAMPLE
345
346 Helper-QueryAD
347#>
348
349 [CmdletBinding()]
350 Param (
351 [Parameter(Mandatory=$true)]
352 [array]$Domains
353 )
354
355
356 $uProp = @("OfficePhone", "Manager", "Title", "DistinguishedName","displayName","samAccountName","userAccountControl","Name","CN","pwdLastSet","mail","department","physicalDeliveryOfficeName","adminCount","lastLogon","lastLogonTimestamp","memberOf","SID")
357 $gProp = @("DistinguishedName","member","name","SID")
358 $cProp = @("DistinguishedName","cn","memberOf","name","userAccountControl","pwdLastSet","operatingSystem","operatingSystemVersion","operatingSystemServicePack","lastLogonTimestamp","lastLogon","SID")
359
360 ForEach($domain in $domains){
361 Log-Write -LogPath $LOG_FILE -LineValue "`t[+] Running Active Directory Queries for $domain" -ForegroundColor Green
362 Log-Write -LogPath $LOG_FILE -LineValue "`t`t[*] Getting User Objects"
363 Get-ADUser -Filter * -Properties $uProp -Server $domain |Select -Property @{name="DN";expression={$_.DistinguishedName}}, userAccountControl, name, cn, displayName, samAccountName, pwdLastSet, mail, department, `
364 physicalDeliveryOfficeName, adminCount, lastLogonTimestamp, @{name="memberOf";expression={$_.memberof -join ";"}}, title, SID| Export-Csv -NoTypeInformation -Encoding UTF8 `
365 -Append -Path "$TEMP_PATH\AD_USERS$DATE`.csv"
366
367 Log-Write -LogPath $LOG_FILE -LineValue "`t`t[*] Getting Group Objects"
368 Get-ADGroup -Filter * -Properties $gProp -Server $domain|Select -Property @{name="DN";expression={$_.DistinguishedName}}, @{name="member";expression={$_.member -join ";"}}, name, SID| `
369 Export-Csv -NoTypeInformation -Encoding UTF8 -Append -Path "$TEMP_PATH\AD_GROUPS$DATE`.csv"
370
371 Log-Write -LogPath $LOG_FILE -LineValue "`t`t[*] Getting Computer Objects"
372 Get-ADComputer -Filter * -Properties $cProp -Server $domain|Select -Property @{name="DN";expression={$_.DistinguishedName}}, userAccountControl, name, cn, pwdLastSet, lastLogonTimestamp, `
373 operatingSystem, operatingSystemVersion, operatingSystemServicePack, @{name="memberOf";expression={$_.memberof -join ";"}}, SID| Export-Csv -NoTypeInformation -Encoding UTF8 `
374 -Append -Path "$TEMP_PATH\AD_COMPUTERS$DATE`.csv"
375
376 if ($Global:CONF.AD_FULL_COLLECT){
377 Log-Write -LogPath $LOG_FILE -LineValue "`t`t[*] Getting Full User Objects"
378 Get-ADUser -Filter * -Properties * -Server $domain |Export-Csv -NoTypeInformation -Encoding UTF8 -Append -Path "$TEMP_PATH\AD_USERS_FULL$DATE`.csv"
379
380 Log-Write -LogPath $LOG_FILE -LineValue "`t`t[*] Getting Full Group Objects"
381 Get-ADGroup -Filter * -Properties * -Server $domain |Export-Csv -NoTypeInformation -Encoding UTF8 -Append -Path "$TEMP_PATH\AD_GROUPS_FULL$DATE`.csv"
382
383 Log-Write -LogPath $LOG_FILE -LineValue "`t`t[*] Getting Full Computer Objects"
384 Get-ADComputer -Filter * -Properties * -Server $domain |Export-Csv -NoTypeInformation -Encoding UTF8 -Append -Path "$TEMP_PATH\AD_COMPUTERS_FULL$DATE`.csv"
385 }
386
387 Helper-QueryAD-Domain -Domain $domain | Export-Csv -NoTypeInformation -Encoding UTF8 -Append -Path "$TEMP_PATH\AD_DOMAINS$DATE`.csv"
388 Helper-QueryAD-Trusts -Domain $domain | Export-Csv -NoTypeInformation -Encoding UTF8 -Append -Path "$TEMP_PATH\AD_TRUSTS$DATE`.csv"
389 }
390}
391
392function Helper-QueryAD-AppendCsv{
393<#
394 .SYNOPSIS
395
396 Helper function to take csvde data and append it to a file. CSVDE does not have an append option.
397
398 .PARAMETER inFile
399
400 Location of the file to use.
401
402 .EXAMPLE
403
404 Helper-QueryAD-AppendCsv -inFile c:\temp_ad_computers__2012_02_14.csv
405
406 This will read in c:\temp_ad_computers__2012_02_14.csv and check to see if c:\ad_computers__2012_02_14.csv exists, if it does than it will append [1:] rows.
407 If it doesn't exist it will create it and append all rows
408#>
409 [CmdletBinding()]
410 Param (
411 [Parameter(Mandatory=$true)]
412 [string]$inFile
413 )
414
415 $outFile = $infile.Trim("TEMP_")
416 if (Test-Path -Path $outFile){
417 $csvInFile = Import-Csv -Path $inFile
418 $csvInFile[1..($csvInFile.count - 1)] |Export-Csv -NoTypeInformation -Encoding UTF8 -Append -Path $outFile
419 }
420 else{
421 Import-Csv -Path $inFile | Export-Csv -NoTypeInformation -Encoding UTF8 -Path $outFile
422 }
423
424 Remove-Item -Path $inFile
425}
426
427function Helper-QueryAD-Domain{
428<#
429 .SYNOPSIS
430
431 Helper function run AD Domain Analytics
432
433 .PARAMETER Domain
434
435 Domain to query
436
437 .EXAMPLE
438
439 Helper-QueryAD-Domain -Domain centoso.com
440
441 This will return the domain data for centoso.com
442#>
443 Log-Write -LogPath $LOG_FILE -LineValue "`t`t[*] Running Active Directory Domain Enumeration Queries"
444 return (Get-ADDomain -Identity $Domain | Select-Object -Property @{name="ChildDomains";expression={$_.ChildDomains}}, ComputersContainer, DistinguishedName, DNSRoot, DomainSID, Forest, Name, NetBIOSName, objectClass, ParentDomain)
445}
446
447function Helper-QueryAD-Trusts{
448<#
449 .SYNOPSIS
450
451 Helper function run AD Trust Analytics
452
453 .PARAMETER Domain
454
455 Domain to query
456
457 .EXAMPLE
458
459 Helper-QueryAD-Trusts -Domain centoso.com
460
461 This will return the trusts relationships for centoso.com
462#>
463 [CmdletBinding()]
464 Param (
465 [Parameter(Mandatory=$true)]
466 [string]$Domain
467 )
468
469 $trusts = @()
470
471 Log-Write -LogPath $LOG_FILE -LineValue "`t`t[*] Running Active Directory Trust Enumeration Queries"
472 ForEach($trust in (Get-ADObject -Filter {ObjectClass -eq "trustedDomain"} -Server $Domain -Properties * -EA 0)){
473 $obj = New-Object -TypeName PSObject
474 $obj | Add-Member -MemberType NoteProperty -Name CanonicalName -Value $trust.CanonicalName
475 $obj | Add-Member -MemberType NoteProperty -Name CN -Value $trust.CN
476 $obj | Add-Member -MemberType NoteProperty -Name Created -Value $trust.Created
477 $obj | Add-Member -MemberType NoteProperty -Name Description -Value $trust.Description
478 $obj | Add-Member -MemberType NoteProperty -Name DistinguishedName -Value $trust.DistinguishedName
479 $obj | Add-Member -MemberType NoteProperty -Name FlatName -Value $trust.flatName
480 $obj | Add-Member -MemberType NoteProperty -Name Modified -Value $trust.Modified
481 $obj | Add-Member -MemberType NoteProperty -Name TargetDomain -Value $trust.Name
482 $obj | Add-Member -MemberType NoteProperty -Name ObjectCategory -Value $trust.objectCategory
483 $obj | Add-Member -MemberType NoteProperty -Name ObjectClass -Value $trust.objectClass
484 $obj | Add-Member -MemberType NoteProperty -Name ObjectGUID -Value $trust.objectGUID
485 $obj | Add-Member -MemberType NoteProperty -Name SecurityIdentifier -Value $trust.securityIdentifier
486 $obj | Add-Member -MemberType NoteProperty -Name TrustAttributes -Value $trust.trustAttributes
487 $obj | Add-Member -MemberType NoteProperty -Name TrustDirection -Value $trust.trustDirection
488 $obj | Add-Member -MemberType NoteProperty -Name TrustType -Value $trust.trustType
489 $obj | Add-Member -MemberType NoteProperty -Name SourceDomain -Value $Domain
490 $trusts += $obj
491 }
492 return $trusts
493}
494
495function Helper-QueryGetDomains{
496<#
497 .SYNOPSIS
498
499 Helper function to standardize the domains for Active Directory and GPOs.
500
501 .EXAMPLE
502
503 Helper-QueryGetDomains
504#>
505 if(($Global:CONF.AD_DOMAINS -ne 'False') -and ($Global:CONF.AD_DOMAINS -ne $false)){
506 $domainStr = $Global:CONF.AD_DOMAINS
507 return $domainStr.ToUpper().Split(",")
508 }elseIf($MOD_AD){
509 $networks = (Get-ADForest).Domains
510
511 ForEach($domain in $networks){
512 Get-ADObject -Filter {ObjectClass -eq "trustedDomain"} -Server $domain -Properties * -EA 0| ForEach{$networks += $_.name}
513 }
514 return $networks | % {$_.ToUpper()} | Select -Unique
515 }else{
516 $domain = [Environment]::UserDomainName
517 $fqd = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain().Name
518 $machine = [Environment]::MachineName
519 $domainController = (Get-WmiObject -Class win32_ntdomain -Filter "DomainName = '$domain'" -ComputerName $machine).DomainControllerName -replace "\\", ""
520 return @("$domainController`.$fqd".ToUpper())
521 }
522}
523
524function Helper-QueryGP{
525<#
526 .SYNOPSIS
527
528 Helper function to run all queries for Group Policy.
529
530 .EXAMPLE
531
532 Helper-QueryGP
533#>
534 [CmdletBinding()]
535 Param (
536 [Parameter(Mandatory=$true)]
537 [array]$Domains
538 )
539
540 ForEach ($domain in $domains){
541 $domain_sid = (Get-ADDomain -Identity $domain).DomainSID.Value
542 Log-Write -LogPath $LOG_FILE -LineValue "`t[+] Running Group Policy Queries for $domain" -ForegroundColor Green
543 Log-Write -LogPath $LOG_FILE -LineValue "`t`t[*] Getting Group Policy Blocked Inheritance"
544 Helper-QueryGP-BlockedInheritance -Domain $domain -DomainSid $domain_sid
545
546 Log-Write -LogPath $LOG_FILE -LineValue "`t`t[*] Getting Group Policy Privileged Users"
547 (Get-GPO -All -Domain $domain).DisplayName | ForEach{ Helper-QueryGP-Policy -Name $_ -Domain $domain -DomainSid $domain_sid}
548 }
549}
550
551function Helper-QueryGP-BlockedInheritance{
552<#
553 .SYNOPSIS
554
555 Helper function to find blocked inheritance within Active Directory. Should only be called from Helper-QueryGP
556
557 .PARAMETER Domain
558
559 This will be domain to query. This is required.
560
561 .PARAMETER DomainSid
562
563 This will be Sid to pass in. This is required.
564
565 .EXAMPLE
566
567 Helper-QueryGP-BlockedInheritance -Domain contoso.com -DomainSid S-1-5-21-2097483910-320099886-2325232636
568#>
569 [CmdletBinding()]
570 Param(
571 [Parameter(Mandatory=$true)]
572 [string]$Domain,
573
574 [Parameter(Mandatory=$true)]
575 [string]$DomainSid
576 )
577
578 $policies = Get-ADOrganizationalUnit -Filter * -Server $Domain | Get-GPInheritance -Domain $Domain | Where-Object {$_.GPOInheritanceBlocked}
579 ForEach ($policy in $policies){
580 ForEach ($link in $policy.InheritedGpoLinks){
581 $obj = New-Object -TypeName PSObject
582 $obj | Add-Member -MemberType NoteProperty -Name display_name -Value $link.DisplayName
583 $obj | Add-Member -MemberType NoteProperty -Name policy_id -Value $link.GpoId
584 $obj | Add-Member -MemberType NoteProperty -Name enabled -Value $link.Enabled
585 $obj | Add-Member -MemberType NoteProperty -Name enforced -Value $link.Enforced
586 $obj | Add-Member -MemberType NoteProperty -Name ou -Value $policy.Path
587 $obj | Add-Member -MemberType NoteProperty -Name domain_sid -Value $DomainSid
588 $obj | Select-Object -Property policy_id, domain_sid, enabled, enforced, ou `
589 | Export-Csv -NoTypeInformation -Append -Encoding UTF8 -Path "$TEMP_PATH\AD_GP_BLOCKED_INHERITANCE$DATE`.csv"
590 }
591 }
592}
593
594function Helper-QueryGP-Policy{
595<#
596 .SYNOPSIS
597
598 Helper function to run all queries for an individual policy for Group Policy. Should only be ran
599 from Helper-QueryGP.
600
601 .PARAMETER Name
602
603 This is the Name of the policy to query. This is required.
604
605 .PARAMETER Domain
606
607 This will be domain to query. This is required.
608
609 .PARAMETER DomainSid
610
611 This will be Sid to pass in. This is required.
612
613 .EXAMPLE
614
615 Helper-QueryGP-Policy -Domain contoso.com -Name "Default Domain Controllers Policy" -DomainSid S-1-5-21-2097483910-320099886-2325232636
616#>
617 [CmdletBinding()]
618 Param(
619 [Parameter(Mandatory=$true)]
620 [string]$Name,
621
622 [Parameter(Mandatory=$true)]
623 [string]$Domain,
624
625 [Parameter(Mandatory=$true)]
626 [string]$DomainSid
627 )
628
629 try{
630 [xml]$report = Get-GPOReport -Name $Name -ReportType Xml -Domain $Domain -ErrorAction Stop
631 }catch {
632 Log-Error -LogPath $LOG_FILE -ErrorDesc "`t[!] Do not have permission to access '$Name' Group Policy"
633 }
634
635 $links = $report.GPO.LinksTo.SomPath #This will show all the OUs where the GPO has been applied"
636 if ($links -eq $null){return}
637
638 $computers = Helper-QueryGP-Links-Applied -Links $links -Domain $Domain
639 if ($computers.length -eq 0){return}
640
641 $Global:Sids = @()
642 $owner_sid = $report.GPO.SecurityDescriptor.Owner.SID.'#text'
643 $policy_id = $report.GPO.Identifier.Identifier.'#text'.Trim('{}')
644 Helper-QueryGP-Convert-Sid -Sid $owner_sid -Domain $Domain
645
646 #Find the owner of the policy, they can do what ever they want to the computers this belongs to.
647 $obj = New-Object -TypeName PSObject
648 $obj | Add-Member -MemberType NoteProperty -Name owners -Value $Global:Sids
649 $obj | Add-Member -MemberType NoteProperty -Name policy_name -Value $Name
650 $obj | Add-Member -MemberType NoteProperty -Name policy_id -Value $policy_id
651 $obj | Add-Member -MemberType NoteProperty -Name computer_ous -Value $computers
652 $obj | Add-Member -MemberType NoteProperty -Name domain_sid -Value $DomainSid
653 $obj | Select-Object -Property policy_id, domain_sid, policy_name, @{name="owners";expression={$_.owners -join ";"}}, @{name="computer_ous";expression={$_.computer_ous -join ";"}} `
654 | Export-Csv -NoTypeInformation -Append -Encoding UTF8 -Path "$TEMP_PATH\AD_GP_OWNERS$DATE`.csv"
655
656 #Determining Group Policy Privileged Users
657 $xmlCapPrivUser = @("SeAssignPrimaryTokenPrivilege","SeCreateTokenPrivilege","SeCreateGlobalPrivilege","SeDebugPrivilege",
658 "SeEnableDelegationPrivilege","SeImpersonatePrivilege","SeInteractiveLogonRight","SeLoadDriverPrivilege",
659 "SeRemoteInteractiveLogonRight","SeRemoteShutdownPrivilege","SeRelabelPrivilege","SeSecurityPrivilege",
660 "SeSystemEnvironmentPrivilege","SeTakeOwnershipPrivilege","SeTrustedCredManAccessPrivilege",
661 "SeNetworkLogonRight","SeMachineAccountPrivilege","SeRestorePrivilege")
662
663 ForEach ($policy in $report.GPO.Computer.ExtensionData.Extension.UserRightsAssignment){
664
665 if ($policy.Name -notin $xmlCapPrivUser){continue}
666
667 $Global:Sids = @()
668 ForEach ($uSid in $policy.Member.SID){
669 If ($uSid.'#text'.length -gt 0){ #Making sure the SID is valid
670 Helper-QueryGP-Convert-Sid -Sid $uSid.'#text' -Domain $Domain
671 }
672 }
673
674 if ($Global:Sids.Length -eq 0){continue}
675
676 $obj = New-Object -TypeName PSObject
677 $obj | Add-Member -MemberType NoteProperty -Name users -Value $Global:Sids
678 $obj | Add-Member -MemberType NoteProperty -Name privilege -Value $policy.Name
679 $obj | Add-Member -MemberType NoteProperty -Name policy_id -Value $policy_id
680 $obj | Add-Member -MemberType NoteProperty -Name policy_name -Value $Name
681 $obj | Add-Member -MemberType NoteProperty -Name computers -Value $computers
682 $obj | Add-Member -MemberType NoteProperty -Name domain_sid -Value $DomainSid
683 $obj | Select-Object -Property policy_id, domain_sid, @{name="users";expression={$_.users -join ";"}}, privilege `
684 | Export-Csv -NoTypeInformation -Append -Encoding UTF8 -Path "$TEMP_PATH\AD_GP_PRIVILEGES$DATE`.csv"
685 }
686}
687
688function Helper-QueryGP-Convert-Sid{
689<#
690 .SYNOPSIS
691
692 Helper function to check if a sid is a user. If it is a group sid it will use
693 recursion to find the users that are part of it.
694
695 .PARAMETER Sid
696
697 Sid in which to query.
698
699 .PARAMETER Domain
700
701 This will be domain to query. This is required.
702
703 .EXAMPLE
704
705 Helper-QueryGP-Convert-Sid -Domain contoso.com -Sid S-1-21-4565456561-54654564654-500
706#>
707 [CmdletBinding()]
708 Param(
709 [Parameter(Mandatory=$true)]
710 [string]$Sid,
711
712 [Parameter(Mandatory=$true)]
713 [string]$Domain
714 )
715
716 $class = (Get-ADObject -Filter "objectSid -eq '$sid'" -Server $Domain).ObjectClass
717
718 If ($class -eq "group"){
719 $groupName = (Get-AdGroup -Filter {SID -eq $sid} -Server $Domain).SamAccountName
720
721 try{
722 ForEach ($s in (Get-ADGroupMember -Identity $groupName -Server $Domain).SID){
723 Helper-QueryGP-Convert-Sid -Sid $s -Domain $Domain
724 }
725 }catch [Exception]{
726 write-host $groupName
727 }
728 }Else{
729 $Global:sids += $Sid
730 }
731}
732
733function Helper-QueryGP-Links-Applied{
734<#
735 .SYNOPSIS
736
737 Helper function to get all the OUs that a GP is applied against.
738
739 .PARAMETER Links
740
741 An Array of OU CanonicalNames. This is required
742
743 .PARAMETER Domain
744
745 This will be domain to query. This is required.
746
747 .EXAMPLE
748
749 Helper-QueryGP-Links-Applied -Domain contoso.com -Links @("Contoso.com/Domain Controllers", "Contoso.com/Servers/Primary Servers")
750
751 This will return an array of Distinguished Names.
752#>
753 [CmdletBinding()]
754 Param(
755 [Parameter(Mandatory=$true)]
756 [array]$Links,
757
758 [Parameter(Mandatory=$true)]
759 [string]$Domain
760 )
761
762 $computer_sids = @()
763 ForEach ($link in $Links){
764 $dn = (Get-ADOrganizationalUnit -Filter * -Properties CanonicalName -Server $Domain|Where-Object{ $_.CanonicalName -eq $link}).DistinguishedName
765
766 if ($dn.Length -eq 0){continue}
767
768 $computer_sids += $dn
769 #$computer_sids += (Get-ADComputer -Filter * -SearchBase $dn -Server $Domain).SID.Value
770 }
771
772 return $computer_sids
773}
774
775function Helper-QuerySCCM {
776<#
777 .SYNOPSIS
778
779 Helper function to run all SCCM queries. It should only be ran from Invoke-Execute.
780
781 .EXAMPLE
782
783 Helper-QuerySCCM
784#>
785 ForEach ($sccm in @($Global:CONF.SCCM.SCCM_2012, $Global:CONF.SCCM.SCCM_2007)){
786 if ($sccm.USING){
787 $version = $sccm.VERSION
788 $queries = @{
789 "SCCM_LOCAL" = "SELECT ResourceID, GroupID, RevisionID, AgentID, TimeStamp, Account0, Category0, Domain0, Name0, Type0, '$version' SCCM_Version FROM v_GS_LocalGroupMembers0"
790 "SCCM_INSTALLED_APPS" = "SELECT ResourceID, DisplayName0, Version0, Publisher0, TimeStamp, '$version' SCCM_Version FROM v_ADD_REMOVE_PROGRAMS"
791 "SCCM_RUNNING_APPS" = "SELECT ResourceID, FolderPath0, ExplorerFileName0, OriginalFileName0, `
792 FileVersion0, FileSize0, ProductName0, ProductVersion0, ProductLanguage0, FileDescription0, CompanyName0, LastUsedTime0, ProductCode0, `
793 msiDisplayName0, msiPublisher0, '$version' SCCM_Version FROM v_GS_CCM_RECENTLY_USED_APPS"
794 "SCCM_HEARTBEAT" = "SELECT ResourceID, AgentTime, '$version' SCCM_Version FROM v_AgentDiscoveries WHERE AgentName = 'Heartbeat Discovery'"
795 "SCCM_COMP_STATS" = "SELECT WD.MachineID, SD.Obsolete0, SD.Active0, WD.LastHwScan, '$version' SCCM_Version FROM System_Disc SD JOIN WorkstationStatus_Data WD ON WD.MachineID = SD.ItemKey"
796 "SCCM_TOP_USER" = "SELECT ResourceID, GroupID, RevisionID, TimeStamp, LastConsoleUse0, NumberOfConsoleLogons0, SystemConsoleUser0, TotalUserConsoleMinutes0, '$version' SCCM_Version `
797 FROM v_GS_SYSTEM_CONSOLE_USER"
798 "SCCM_PATCHING" = "SELECT UCS.ResourceID, UI.ArticleID, UCS.Status, '$version' SCCM_Version FROM v_update_compliancestatusreported UCS JOIN v_updateinfo UI ON UCS.ci_id = UI.ci_id WHERE UI.ArticleID IS `
799 NOT NULL AND NOT UCS.status = 3 AND NOT UCS.status = 1"
800 "SCCM_PATCHING_DESC" = "SELECT DISTINCT ArticleID, BulletinID, Severity, Title, Description, InfoURL, '$version' SCCM_Version FROM v_updateinfo WHERE NOT Severity = 0"
801 "SCCM_HARDWARE" = "SELECT DISTINCT vCS.ResourceID, vCS.Manufacturer0, vCS.Model0, vOS.Caption0 OSName0, vOS.CSDVersion0 OSSubVersion0, vOS.InstallDate0 OSInstallDate0, vBios.ReleaseDate0 `
802 BiosReleaseDate0, vBios.Manufacturer0 BiosManufacturer0, vBios.Name0 BiosName0, vBios.SerialNumber0 BiosSerialNumber0, vSE.ChASsisTypes0, '$version' SCCM_Version FROM v_GS_COMPUTER_SYSTEM `
803 vCS LEFT JOIN v_GS_PC_BIOS vBios ON vCS.ResourceID = vBios.ResourceID LEFT JOIN v_GS_OPERATING_SYSTEM vOS ON vCS.ResourceID = vOS.ResourceID LEFT JOIN v_GS_SYSTEM_ENCLOSURE vSE ON `
804 vCS.ResourceID = vSE.ResourceID"
805 "SCCM_NETWORKING" = "SELECT ResourceID, GroupID, RevisionID, AgentID, TimeStamp, DefaultIPGateway0, DHCPEnabled0, DHCPServer0, DNSDomain0, DNSHostName0, Index0, IPAddress0, IPEnabled0, IPSubnet0, `
806 MACAddress0, ServiceName0, '$version' SCCM_Version FROM v_Network_DATA_Serialized"
807 }
808
809 if ($sccm.VERSION -eq 5){
810 $queries.SCCM_VR_SYSTEM = "SELECT ResourceID, ResourceType, Active0, AD_Site_Name0, AlwaysInternet0, AMTFullVersion0, AMTStatus0, Client0, AgentEdition0, Client_Type0, `
811 Client_Version0, CPUType0, Creation_Date0, Decommissioned0, DeviceOwner0, Distinguished_Name0, EAS_DeviceID, Full_Domain_Name0, Hardware_ID0, InternetEnabled0, `
812 Is_AOAC_Capable0, Is_MachineChanges_Persisted0, IsClientAMT30Compatible0, Is_Assigned_To_User0, Is_Portable_Operating_System0, Is_Virtual_Machine0, `
813 Is_Write_Filter_Capable0, Last_Logon_Timestamp0, User_Domain0, User_Name0, Name0, Netbios_Name0, Object_GUID0, Obsolete0, Operating_System_Name_and0, `
814 Previous_SMS_UUID0, Primary_Group_ID0, PublisherDeviceID, Resource_Domain_OR_Workgr0, SID0, SMBIOS_GUID0, SMS_Unique_Identifier0, SMS_UUID_Change_Date0, Community_Name0, `
815 SuppressAutoProvision0, Unknown0, User_Account_Control0, Virtual_Machine_Host_Name0, WipeStatus0, WTGUniqueKey, '$version' SCCM_Version FROM v_R_System"
816 $queries.SCCM_VR_USER = "SELECT ResourceID, ResourceType, CloudUserId, Creation_Date0, Distinguished_Name0, Full_Domain_Name0, Full_User_Name0, Mail0, Name0, `
817 Network_Operating_System0, Object_GUID0, Primary_Group_ID0, SID0, Unique_User_Name0, User_Account_Control0, User_Name0, User_Principal_Name0, `
818 Windows_NT_Domain0, '$version' SCCM_Version FROM v_R_User"
819 $queries.SCCM_VR_USERGROUP = "SELECT ResourceID, ResourceType, AD_Domain_Name0, Creation_Date0, Group_Type0, Name0, Network_Operating_System0, Object_GUID0, SID0, Unique_Usergroup_Name0, `
820 Usergroup_Name0, Windows_NT_Domain0, '$version' SCCM_Version FROM v_R_UserGroup"
821 $queries.SCCM_PRIV_USERS = "SELECT vA.AdminID, CASE WHEN vA.IsGroup = 1 THEN vG.ResourceID ELSE vU.ResourceID END AS ResourceID, vA.IsGroup, vSSP.CategoryID, vSSP.RoleName, `
822 vR.RoleDescription, '$version' SCCM_Version FROM v_SecuredScopePermissions vSSP JOIN v_Admins vA ON vA.AdminID = vSSP.AdminID JOIN v_Roles vR ON vR.RoleName = vSSP.RoleName `
823 LEFT JOIN v_R_User vU ON vU.SID0 = vA.AdminSid LEFT JOIN v_R_UserGroup vG ON vG.SID0 = vA.AdminSid"
824 $queries.SCCM_AD_FORESTS = "SELECT CreatedBy, CreatedOn, Description, DiscoveryEnabled, ForestFQDN, ForestID, ModifiedBy, ModifiedOn, PublishingEnabled, `
825 PublishingPath, Tombstoned, LastDiscoveryTime, Account, LastDiscoveryStatus, PublishingStatus, DiscoveredTrusts, DiscoveredDomains, DiscoveredADSites, `
826 DiscoveredIPSubnets, '$version' SCCM_Version FROM vActiveDirectoryForests"
827 $queries.SCCM_AD_DOMAINS = "SELECT DomainID, ForestID, DomainName, DomainMode, LastDiscoveryTime, Flags, '$version' SCCM_Version FROM ActiveDirectoryDomains"
828 $queries.SCCM_AD_TRUST_RELATIONS = "SELECT ForestID, TrustedForestID, TrustDirection, TrustType, LastDiscoveryTime, Flags, '$version' SCCM_Version FROM ActiveDirectoryForestTrusts"
829 $queries.SCCM_ENCRYPTION = "SELECT ChangeAction, ResourceID, BatchingKey, GroupKey, TimeStamp, rowversion, DeviceID0, DriveLetter0, PersistentVolumeID0, ProtectionStatus0, `
830 '$version' SCCM_Version FROM SCCM_Ext.vex_GS_ENCRYPTABLE_VOLUME"
831 }elseif($sccm.VERSION -eq 4){
832 $queries.SCCM_VR_SYSTEM = "SELECT ResourceID, ResourceType, Active0, AD_Site_Name0, AlwaysInternet0, AMTFullVersion0, AMTStatus0, Client0, Null AgentEdition0, Client_Type0, `
833 Client_Version0, CPUType0, Creation_Date0, Decommissioned0, Null DeviceOwner0, Null Distinguished_Name0, Null EAS_DeviceID, FQDN0 Full_Domain_Name0, Hardware_ID0, `
834 InternetEnabled0, Null Is_AOAC_Capable0, Null Is_MachineChanges_Persisted0, Null IsClientAMT30Compatible0, Null Is_Assigned_To_User0, Null Is_Portable_Operating_System0, `
835 Null Is_Virtual_Machine0, Null Is_Write_Filter_Capable0, Null Last_Logon_Timestamp0, User_Domain0, User_Name0, Name0, Netbios_Name0, Null Object_GUID0, Obsolete0, `
836 Operating_System_Name_and0, Previous_SMS_UUID0, Primary_Group_ID0, Null PublisherDeviceID, Resource_Domain_OR_Workgr0, Null SID0, SMBIOS_GUID0, SMS_Unique_Identifier0, `
837 SMS_UUID_Change_Date0, Community_Name0, SuppressAutoProvision0, Unknown0, User_Account_Control0, Null Virtual_Machine_Host_Name0, Null Virtual_Machine_Type0, Null WipeStatus0, `
838 Null WTGUniqueKey, '$version' SCCM_Version FROM v_R_System"
839 $queries.SCCM_VR_USER = "SELECT 10 TOP ResourceID, ResourceType, Null CloudUserID, Creation_Date0, Null Distinguished_Name0, Null Full_Domain_Name0, Full_User_Name0, Mail0, Name0, `
840 Network_Operating_System0, Null Object_GUID0, Primary_Group_ID0, Null SID0, Unique_User_Name0, User_Account_Control0, User_Name0, Null User_Principal_Name0, Windows_NT_Domain0, `
841 '$version' SCCM_Version FROM v_R_User"
842 $queries.SCCM_VR_USERGROUP = "SELECT ResourceID, ResourceType, Active_Directory_Domain0 AD_Domain_Name0, Creation_Date0, Null Group_Type0, Name0, Network_Operating_System0, `
843 Null Object_GUID0, SID0, Unique_Usergroup_Name0, Usergroup_Name0, Windows_NT_Domain0, '$version' SCCM_Version FROM v_R_UserGroup"
844 }
845
846 Log-Write -LogPath $LOG_FILE -LineValue "`t[+] Running SCCM Queries for SCCM Version $version" -Foreground Green
847
848 if($sccm.WIN_AUTH) {
849 Invoke-SqlCmds -Queries $queries -Server $sccm.SCCM_SRV -Database $sccm.SCCM_DB
850 } else {
851 Invoke-SqlCmds -Queries $queries -Server $sccm.SCCM_SRV -Database $sccm.SCCM_DB -User $sccm.SCCM_CREDS.USER -Password $sccm.SCCM_CREDS.PASS
852 }
853
854 Log-Write -LogPath $LOG_FILE -LineValue "`t[+] SCCM Version $version Queries Done"
855 }
856 }
857}
858
859function Helper-QuestionShortAns {
860<#
861 .SYNOPSIS
862
863 Quick helper function to prompt for a short answer. I return the answer.
864
865 .PARAMETER Question
866
867 The question to ask. This is required.
868
869 .PARAMETER Default
870
871 If you don't put in an answer it autofills.
872
873 .EXAMPLE
874
875 Helper-QuestionShortAns -Question "Who wants to know"
876
877 Will prompt and ask the question.
878
879 .EXAMPLE
880
881 Helper-QuestionYn -Question "Who wants to know" -Default "Johnny Ray"
882
883 Will prompt and ask the question, if no answer is supplied it will use "Johnny Ray"
884#>
885 [CmdletBinding()]
886 Param(
887 [Parameter(Mandatory=$true,Position=1)]
888 [string]$Question,
889 [Parameter(Mandatory=$false)]
890 [string]$Default = ' '
891 )
892 $fields = new-object "System.Collections.ObjectModel.Collection``1[[System.Management.Automation.Host.FieldDescription]]"
893 $f = New-Object System.Management.Automation.Host.FieldDescription $Question
894 $f.DefaultValue = $Default
895 $f.Label = "&Label"
896 $fields.Add($f)
897 $answer = $Host.UI.Prompt( '', '', $fields)
898 return $answer.Values
899}
900
901function Helper-QuestionYn {
902<#
903 .SYNOPSIS
904
905 Quick helper function to prompt for a Yes/No Question. If the answer is Yes than we return 0
906 If the answer is No than we return 1.
907
908 .PARAMETER Question
909
910 The question to ask. This is required.
911
912 .PARAMETER YesHelp
913
914 If you want to have a help, than fill this with what they will be accepting by clicking Yes.
915
916 .PARAMETER NoHelp
917
918 If you want to have a help, than fill this with what they will be accepting by clicking No.
919
920 .EXAMPLE
921
922 Helper-QuestionYn -Question "Is it raining today"
923
924 This will prompt for the question with the option for Yes or No
925
926 .EXAMPLE
927
928 Helper-QuestionYn -Question "Is it raining today" -YesHelp "It is raining" -NoHelp "It is not raining"
929
930 This will prompt for the question and then if they hover over the icons or click help than they will
931 see an explaination.
932#>
933 [CmdletBinding()]
934 Param(
935 [Parameter(Mandatory=$true,Position=1)]
936 [string]$Question,
937 [Parameter(Mandatory=$false)]
938 [string]$YesHelp = 'yes',
939 [Parameter(Mandatory=$false)]
940 [string]$NoHelp = 'no'
941 )
942
943 $yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", $YesHelp
944 $no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", $NoHelp
945 $options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)
946 $answer = $host.ui.PromptForChoice('',$Question, $options,0)
947
948 if ($answer){return $false}
949 else{return $true}
950}
951
952function Helper-ZipData {
953<#
954 .SYNOPSIS
955
956 Helper function that will take data from a directory, compress it and put it in another directory.
957 It will also move all .log files to the $LOG_DIR directory.
958 Currently this requires Powershell version 3.
959
960 .PARAMETER Directory
961
962 The Directory that will be zipped. This is required.
963
964 .PARAMETER OutputPath
965
966 The file location that the zip file will go. This is required.
967
968 .EXAMPLE
969
970 Helper-ZipData -Directory c:\windows\system32 -OutputPath c:\users\test\desktop\system32.zip
971#>
972 [CmdletBinding()]
973 Param(
974 [Parameter(Mandatory=$true,Position=1)]
975 [string]$Directory,
976 [Parameter(Mandatory=$true)]
977 [string]$OutputPath
978 )
979
980 Add-Type -A System.IO.Compression.FileSystem
981 if (Test-Path -Path $OutputPath){Remove-Item -Path $OutputPath}
982
983 Log-Write -LogPath $LOG_FILE -LineValue "`t[+] Compressing Data and Cleaning up"
984 [IO.Compression.ZipFile]::CreateFromDirectory($Directory, $OutputPath)
985
986 if (Test-Path -Path $OutputPath){Remove-Item -Path "$Directory\*"}
987 else{Log-Error -LogPath $LOG_FILE -ErrorDesc "`t[!] Failed to write zip file, please zip up files `
988 in $Directory and put in $OutputPath"}
989}
990
991function Helper-MoveData {
992<#
993 .SYNOPSIS
994
995 Helper function that will take data from a directory and put it in another directory.
996
997 .PARAMETER Directory
998
999 The Directory that will be moved. This is required.
1000
1001 .PARAMETER OutputPath
1002
1003 The file location that the files will go. This is required.
1004
1005 .EXAMPLE
1006
1007 Helper-MoveData -Directory c:\windows\system32 -OutputPath c:\users\test\desktop\system32.zip
1008#>
1009 [CmdletBinding()]
1010 Param(
1011 [Parameter(Mandatory=$true,Position=1)]
1012 [string]$Directory,
1013 [Parameter(Mandatory=$true)]
1014 [string]$OutputPath
1015 )
1016
1017 Log-Write -LogPath $LOG_FILE -LineValue "`t[+] Organizing Data and Cleaning up"
1018 if(!(Test-Path $OutputPath)){New-Item $OutputPath -type directory | Out-Null}
1019
1020 Move-Item "$Directory\*" $OutputPath -force | Out-Null
1021}
1022
1023function Log-Start {
1024<#
1025 .SYNOPSIS
1026
1027 Creates the header for log file. It will write to the file and display to stdout. Use this prior to any other
1028 Log-* command.
1029
1030 .PARAMETER LogPath
1031
1032 File path you want to write the log to. This assumes the file directory exists. If a file exist with the same
1033 name, it will overwrite it. This is a required field.
1034
1035 .EXAMPLE
1036
1037 Log-Start -LogPath C:\Windows\Temp\mylog.log
1038#>
1039 [CmdletBinding()]
1040 Param (
1041 [Parameter(Mandatory=$true)]
1042 [string]$LogPath
1043 )
1044
1045 Process{
1046 #Check if file exists and delete if it does
1047 If((Test-Path -Path $LogPath)){Remove-Item -Path $LogPath -Force}
1048
1049 #Create file and start logging
1050 New-Item -Path $LogPath -ItemType File | Out-Null
1051 Add-Content -Path $LogPath -Value "***************************************************************************************************"
1052 Add-Content -Path $LogPath -Value "Started $TOOL_NAME at [$([DateTime]::Now)]."
1053 Add-Content -Path $LogPath -Value "***************************************************************************************************"
1054 Add-Content -Path $LogPath -Value ""
1055 Add-Content -Path $LogPath -Value "Running script version [$TOOL_VERSION]."
1056 Add-Content -Path $LogPath -Value ""
1057 Add-Content -Path $LogPath -Value "***************************************************************************************************"
1058 Add-Content -Path $LogPath -Value ""
1059
1060 #Write to screen for debug mode
1061 Write-Host "***************************************************************************************************"
1062 Write-Host "Started $TOOL_NAME at [$([DateTime]::Now)]."
1063 Write-Host "***************************************************************************************************"
1064 Write-Host ""
1065 Write-Host "Running script version [$TOOL_VERSION]."
1066 Write-Host ""
1067 Write-Host "***************************************************************************************************"
1068 Write-Host ""
1069 }
1070}
1071
1072function Log-Error {
1073<#
1074 .SYNOPSIS
1075
1076 Writes an error to the log file for troubleshooting. Also sends error to stderr. For
1077 best use, initialize the log with Log-Start prior to running Log-Error
1078
1079 .PARAMETER LogPath
1080
1081 File path you want to write the log to. This assumes the file directory exists. If a file exist with the same
1082 name, it will append to it. This is a required field.
1083
1084 .PARAMETER ErrorDesc
1085
1086 Brief error description. This is a required field.
1087
1088 .PARAMETER Exception
1089
1090 The Exception that was thrown
1091
1092 .EXAMPLE
1093
1094 Log-Error -LogPath C:\Windows\Temp\mylog.log -ErrorDesc "Something bad happened"
1095
1096 This will append a new to line to C:\Windows\Temp\mylog.log with the line "Something bad happened"
1097
1098 .EXAMPLE
1099
1100 Log-Error -LogPath C:\Windows\Temp\mylog.log -ErrorDesc "Something bad happened" -Exception $error[0]
1101
1102 This will append a new to line to C:\Windows\Temp\mylog.log with the line "Something bad happened". It
1103 will also output the exception to stderr.
1104#>
1105 [CmdletBinding()]
1106 Param (
1107 [Parameter(Mandatory=$true)]
1108 [string]$LogPath,
1109 [Parameter(Mandatory=$true)]
1110 [string]$ErrorDesc,
1111 [Parameter(Mandatory=$false)]
1112 [Exception]$Exception
1113 )
1114
1115 Process{
1116 Add-Content -Path $LogPath -Value "Error: $ErrorDesc"
1117 #Write exception information if present
1118 if($Exception) {
1119 $ExceptionType = $Exception.GetType().FullName
1120 $ExceptionMessage = $Exception.Message
1121 Add-Content -Path $logPath -Value "Exception type: $ExceptionType"
1122 Add-Content -Path $logPath -Value "Exception: $ExceptionMessage"
1123 }
1124
1125 #Write to screen for debug mode
1126 Write-Host "$ErrorDesc : $ExceptionMessage" -ForegroundColor Red
1127 }
1128}
1129
1130function Log-Write {
1131<#
1132 .SYNOPSIS
1133
1134 Writes a line to the log file. Also sends line to stdout. For best use, initialize the log with
1135 Log-Start prior to running Log-Write.
1136
1137 .PARAMETER LogPath
1138
1139 File path you want to write the log to. This assumes the file directory exists. If a file exist with the same
1140 name, it will append to it. This is a required field.
1141
1142 .PARAMETER LineValue
1143
1144 Brief description. This is a required field.
1145
1146 .PARAMETER ForegroundColor
1147
1148 Color to use when sending to stdout.
1149
1150 .EXAMPLE
1151
1152 Log-Write -LogPath C:\Windows\Temp\mylog.log -LineValue "Something happened"
1153
1154 This will append a new to line to C:\Windows\Temp\mylog.log with the line "Something happened"
1155
1156 .EXAMPLE
1157
1158 Log-Write -LogPath C:\Windows\Temp\mylog.log -LineValue "Something happened" -ForegroundColor Green
1159
1160 This will append a new to line to C:\Windows\Temp\mylog.log with the line "Something happened". It
1161 will also output the line to stdout with the text in green.
1162#>
1163 [CmdletBinding()]
1164 Param (
1165 [Parameter(Mandatory=$true)]
1166 [string]$LogPath,
1167 [Parameter(Mandatory=$true)]
1168 [string]$LineValue,
1169 [Parameter(Mandatory=$false)]
1170 [string]$ForegroundColor
1171 )
1172
1173 Process{
1174 Add-Content -Path $LogPath -Value $LineValue
1175
1176 #Write to screen for debug mode
1177 if ($ForegroundColor){ Write-Host $LineValue -ForegroundColor $ForegroundColor}
1178 else{ Write-Host $LineValue}
1179 }
1180}
1181
1182function Invoke-SqlCmds {
1183<#
1184 .SYNOPSIS
1185
1186 This is my rewrite of the Invoke-SqlCmd but in Powershell Version 2 complaince. This will read in a hash list
1187 and run the commands against a MSSQL database.
1188
1189 .PARAMETER Queries
1190
1191 A hash list with the key being the query name and the value being the actual query itself. This is a required
1192 field.
1193
1194 .PARAMETER Server
1195
1196 Server in which to connect to. Default is "localhost"
1197
1198 .PARAMETER WriteToFile
1199
1200 Boolean. If true, will output to a file using the key as part of the filename.
1201
1202 .PARAMETER User
1203
1204 If using username and password, this will store the username. If not supplied, it will attempt to authenticate with
1205 built in Windows Authentication for current user.
1206
1207 .PARAMETER Password
1208
1209 If using username and password, this will store the password. If not supplied, it will attempt to authenticate with
1210 built in Windows Authentication for current user.
1211
1212 .PARAMETER Database
1213
1214 The database in which to connect to. I make the assumption that if you do not supply a database then you are
1215 looking for SCCM's default database name. CM_*
1216
1217 .EXAMPLE
1218
1219 Invoke-SQLCmds -Queries @{"TEST" = "SELECT * FROM USER"} -User Test -Password p@ss -Database MSSQL_DB1 -Server MSSERVER01
1220
1221 This will connect to MSSERVER01 utilizing a username and password combo of Test/p@ss and attempt to query MSSQL_DB1 database
1222 with the "SELECT * FROM USER" query. If the query returns any rows, it will write to a file that starts with TEST
1223
1224 .EXAMPLE
1225
1226 Invoke-SQLCmds -Queries @{"TEST" = "SELECT name FROM Sys.Databases WHERE name LIKE 'CM_%'} -Server MSSERVER01 -WriteToFile 0
1227
1228 This will connect to MSSERVER01 utilizing Windows authentication and attempt to query the server for a database that starts
1229 with CM_ and returns any it finds. It does not write to file.
1230#>
1231 [CmdletBinding()]
1232 Param(
1233 [Parameter(Mandatory=$true,Position=1)]
1234 $Queries,
1235
1236 [Parameter(Mandatory=$false)]
1237 [string]$Server = 'localhost',
1238
1239 [Parameter(Mandatory=$false)]
1240 [bool]$WriteToFile = $true,
1241
1242 [Parameter(Mandatory=$false)]
1243 [string]$User,
1244
1245 [Parameter(Mandatory=$false)]
1246 [string]$Password,
1247
1248 [Parameter(Mandatory=$false)]
1249 [string]$Database
1250 )
1251
1252 if ($Database){
1253 if ($user -and $password){$connectionString = "Server=$Server;Database=$database;User Id=$User;Password=$Password"}
1254 else{$connectionString = "Server=$Server;Database=$database;Integrated Security=True;"}
1255 }else{
1256 if ($user -and $password){$connectionString = "Server=$sccmSrv;User Id=$user;Password=$password"}
1257 else{$connectionString = "Server=$sccmSrv;Integrated Security=True;"}
1258 }
1259
1260 $connection = New-Object System.Data.SqlClient.SqlConnection
1261 $connection.ConnectionString = $connectionString
1262 $connection.Open()
1263
1264 ForEach ($key in $Queries.Keys){
1265 [System.GC]::Collect() #Runs Garbage Collect
1266
1267 $query = $Queries.$Key
1268 $command = $connection.CreateCommand()
1269 $command.CommandText = $query
1270 Log-Write -LogPath $LOG_FILE -LineValue "`t`t[*] Attempting to run $key"
1271 try{
1272 $result = $command.ExecuteReader()
1273 }catch [Exception] {
1274 Log-Error -LogPath $LOG_FILE -ErrorDesc "`t`t[!] Failed to run [$key]" -Exception $_.Exception
1275 continue
1276 }
1277
1278 $table = new-object System.Data.DataTable
1279 $table.Load($result)
1280 $result = $null #free's memory
1281
1282 if ($WriteToFile){
1283 $tempFile = $Global:CONF.PROGRAM_PATH + "\Temp\$key$DATE.csv"
1284
1285 if ($table.Rows.Count -gt 0){$table | Export-Csv -NoTypeInformation -Append -Encoding UTF8 -Path $tempFile}
1286 else{Log-Error -LogPath $LOG_FILE -ErrorDesc "`t`t[!] $key Query returned 0 results"}
1287 }
1288
1289 if (-NOT $WriteToFile){return $table}
1290 }
1291
1292 $table = $null #free's memory
1293 $connection.Close()
1294}
1295
1296function Invoke-Update {
1297<#
1298 .SYNOPSIS
1299
1300 Function that runs each time checking to see if a new version of this tool is released. It does this by downloading
1301 the version on the server and checking to see if the MD5 is the same and the currently running script. If it is not,
1302 it will move the current file to a backup location and move the new copy to the current file's old location. Then it
1303 will delete the old file. In order for this to run, $Global:CONF.USING_INTERNET needs to be set to True and
1304 $Global:CONF.WEB_UL_DIR needs to be set to the download server.
1305
1306 .EXAMPLE
1307
1308 Invoke-Update
1309#>
1310 if(-not $Global:CONF.USING_INTERNET) {
1311 Log-Write -LogPath $LOG_FILE -LineValue "[!] Auto-Update disabled: `$Global:CONF.USING_INTERNET is `$false" -ForegroundColor Yellow
1312 return
1313 } elseif(-not $Global:CONF.WEB_UL_DIR) {
1314 Log-Error -LogPath $LOG_FILE -ErrorDesc "[!] Auto-Update disabled: `$Global:CONF.USING_INTERNET is `$true but `$Global:CONF.WEB_UL_DIR is undefined."
1315 return
1316 }
1317 $DL_PATH = $Global:CONF.PROGRAM_PATH
1318
1319 $ans = Test-Path -Path "$DL_PATH\$TOOL_NAME.ps1.old"
1320 if ($ans){Remove-Item -Path "$DL_PATH\$TOOL_NAME.ps1.old"}
1321
1322 try{
1323 $web_dl_path = $Global:CONF.WEB_UL_DIR + "/$TOOL_NAME.ps1"
1324 Invoke-WebRequest $web_dl_path -OutFile "$DL_PATH\$TOOL_NAME.ps1.new"
1325 }catch [Exception]{
1326 Log-Error -LogPath $LOG_FILE -ErrorDesc "[!] Failed to connect to $web_dl_loc for updating" -Exception $_.Exception
1327 return
1328 }
1329
1330 $md5 = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
1331 $hashNewScript = [System.BitConverter]::ToString($md5.ComputeHash([System.IO.File]::ReadAllBytes("$DL_PATH\$TOOL_NAME.ps1.new")))
1332 $hashCurrentScript = [System.BitConverter]::ToString($md5.ComputeHash([System.IO.File]::ReadAllBytes("$DL_PATH\$TOOL_NAME.ps1")))
1333
1334 if ($hashNewScript -ne $hashCurrentScript){
1335 Move-Item -Path "$DL_PATH\$TOOL_NAME.ps1" -Destination "$DL_PATH\$TOOL_NAME.ps1.old"
1336 Move-Item -Path "$DL_PATH\$TOOL_NAME.ps1.new" -Destination "$DL_PATH\$TOOL_NAME.ps1"
1337 Invoke-Expression "$DL_PATH\$TOOL_NAME.ps1"
1338 Exit
1339 }
1340}
1341
1342function Invoke-Upload {
1343<#
1344 .SYNOPSIS
1345
1346 Function that uploads any files in the $EX_PATH to a server. In order for this to run, $Global:CONF.USING_INTERNET
1347 needs to be set to True and $WEB_UL_DIR needs to be set.
1348
1349 .EXAMPLE
1350
1351 Invoke-Upload
1352#>
1353 if (-not $Global:CONF.USING_INTERNET){ return }
1354 $ul_dir = $Global:CONF.WEB_UL_DIR
1355 Log-Write -LogPath $LOG_FILE -LineValue "`t[+] Attempting to send data to $ul_dir"
1356
1357 if ((Get-ChildItem $EX_PATH | Measure-Object).Count -eq 0){
1358 Log-Write -LogPath $LOG_FILE -LineValue "`t[!] Didn't find any files to send" -ForegroundColor Yellow
1359 Sleep 60 #Sleeping in case the server did something wrong
1360 Invoke-Execute
1361 Return
1362 }
1363
1364 [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
1365 $urlRoot = $Global:CONF.WEB_UL_DIR
1366 if ($Global:CONF.WEB_ORG_ID -eq $false -or $Global:CONF.WEB_ORG_ID.ToLower() -eq "false"){ $orgId = "?orgId=DEFAULT"}
1367 else{ $orgId = "?orgId=" + $Global:CONF.WEB_ORG_ID }
1368
1369 $org = $orgId.Split('=')[-1]
1370 Log-Write -LogPath $LOG_FILE -LineValue "`t`t[*] Found data, sending them to $urlRoot, OrgId: $org" -ForegroundColor Yellow
1371
1372 ForEach ($file in (Get-ChildItem $EX_PATH).Name){
1373 Log-Write -LogPath $LOG_FILE -LineValue "`t`t[+] $file"
1374 $sourceFilePath = "$EX_PATH\$file"
1375 $urlDest = $Global:CONF.WEB_UL_DIR + "/horsepower/api/engine/upload"
1376 $urlCompute = $Global:CONF.WEB_UL_DIR + "/horsepower/api/engine/compute/"
1377
1378 $webClient = New-Object MyWebClient
1379 $count = 0
1380
1381 while ($count -lt 2){
1382 try{
1383 $webClient.Headers.add("Authorization", "Bearer " + $Global:CONF.WEB_MULTIPASS_TOKEN)
1384 $webClient.UploadFile($urlDest + $orgId, "POST", $sourceFilePath) |Out-Null
1385 if ($Global:CONF.WEB_DEL_AFTER_UL){Remove-Item $sourceFilePath }
1386 break
1387 }catch [Net.WebException]{
1388 Log-Error -LogPath $LOG_FILE -ErrorDesc "`t`t[!] Attempt $count`: $_`n`t`t[!] Will try again in 60 secs."
1389 sleep 60
1390 $count ++
1391 }
1392 }
1393
1394 if (($Global:CONF.WEB_COMPUTE)){
1395 try{
1396 $cDate = $sourceFilePath.Split('__')[-1].tolower().Trim('.zip')
1397 curl -Method POST -Uri "$urlCompute$cDate$orgId" -Headers @{"Authorization"= "Bearer " + $Global:CONF.WEB_MULTIPASS_TOKEN} | Out-Null
1398 }catch [exception]{
1399 continue
1400 }
1401 }
1402 }
1403}
1404
1405function Invoke-Execute {
1406<#
1407 .SYNOPSIS
1408
1409 Runs all modules that have been installed and enabled.
1410
1411 .EXAMPLE
1412
1413 Invoke-Execute
1414#>
1415 Log-Write -LogPath $LOG_FILE -LineValue "[+] Starting Analytics Engine" -ForegroundColor Green
1416
1417 $l = (Get-ChildItem $EX_PATH | Measure-Object).Count
1418 if (($l -gt 0) -and ($Global:CONF.USING_INTERNET)){Invoke-Upload}
1419
1420 if ($MOD_AD){
1421 $domains = @()
1422 foreach($d in Helper-QueryGetDomains){
1423 try{
1424 $var = Get-ADForest -Server $d -ErrorAction Stop
1425 $domains += $d
1426 }catch{
1427 Log-Error -LogPath $LOG_FILE -ErrorDesc "`t[!] Found domain named '$d', but unable to get data from it."
1428 }
1429 }
1430
1431 Helper-QueryAD -Domains $domains
1432 if ($MOD_GP){Helper-QueryGP -Domains $domains}
1433 }
1434
1435 Helper-QuerySCCM
1436
1437 Log-Write -LogPath $LOG_FILE -LineValue "[+] Stopping Analytics Engine" -ForegroundColor Green
1438}
1439
1440function Invoke-Install {
1441<#
1442 .SYNOPSIS
1443
1444 Installs all modules that a network has. This will run when $XML_CONF is not detected.
1445
1446 .EXAMPLE
1447
1448 Invoke-Install
1449#>
1450 Write-Host "Could not detect a config.xml, starting fresh" -ForegroundColor Yellow
1451 if (-not (Check-Privs)){$directory = $env:ALLUSERSPROFILE + "\$TOOL_NAME"}
1452 else{$directory = $env:ProgramFiles + "\$TOOL_NAME"}
1453
1454 $Global:CONF.PROGRAM_PATH = $directory
1455 while (-not (Helper-InstallProgramPath -Directory $directory)){$directory = Helper-QuestionShortAns -Question "Where Can I Install $TOOL_NAME $TOOL_VERSION"}
1456
1457 $EX_PATH = Helper-CreateDirectory -Path "$directory\Exports"
1458 $TEMP_PATH = Helper-CreateDirectory -Path "$directory\Temp"
1459 $LOG_PATH = Helper-CreateDirectory -Path "$directory\Logs"
1460
1461 Copy-Item $Script:MyInvocation.MyCommand.Path "$directory\$TOOL_NAME.ps1" | Out-Null #Moving current script to Program Path
1462
1463 $LOG_FILE = "$LOG_PATH\$TOOL_NAME`_Installation$DATE`.log"
1464 Log-Start -LogPath $LOG_FILE
1465 Log-Write -LogPath $LOG_FILE -LineValue "[*] Setting Directory: $directory"
1466
1467 #Installing Modules
1468 while (Helper-QuestionYn -Question "Add a new SCCM Server" -YesHelp "Adds SCCM Server" -NoHelp "Continues Installation"){Helper-InstallSCCM}
1469
1470 if($Global:CONF.SCHEDULE_TASK){Helper-InstallPersistance}
1471
1472 #Exporting Config
1473 $Global:CONF | Helper-HashTableToXml -Root 'Configuration' -Path "$directory\config.xml" #Building Object to write config to disk
1474 Copy-Item -Path $LOG_FILE -Destination $TEMP_PATH
1475}
1476
1477#Setting Global Params
1478$XML_CONF = $PSScriptRoot + '\config.xml'
1479$DATE = Get-Date -format __yyyy-MM-dd
1480
1481#Checking to see if this is first run
1482if (-Not (Get-Config)){Invoke-Install}
1483
1484#Setting Global Params
1485$TEMP_PATH = $Global:CONF.PROGRAM_PATH + "\Temp"
1486$EX_PATH = $Global:CONF.PROGRAM_PATH + "\Exports"
1487$LOG_PATH = $Global:CONF.PROGRAM_PATH + "\Logs"
1488$LOG_FILE = "$LOG_PATH\$TOOL_NAME$DATE`.log"
1489
1490
1491if (-not ($Global:CONF.WEB_UL_ONLY)){
1492 #Start Logging
1493 Log-Start -LogPath $LOG_FILE
1494
1495 #Checking for any new updates
1496 Invoke-Update
1497
1498 #Setting Global Params
1499 if (Get-Module -ListAvailable -Name ActiveDirectory){$MOD_AD = $true; Import-Module ActiveDirectory}
1500 else{$MOD_AD = $false; Log-Write -LogPath $LOG_FILE -LineValue "[!] Failed to detect ActiveDirectory module, skipping Active Directory Queries" -ForegroundColor Yellow}
1501
1502
1503 if (Get-Module -ListAvailable -Name GroupPolicy){$MOD_GP = $true; Import-Module GroupPolicy}
1504 else{$MOD_GP = $false; Log-Write -LogPath $LOG_FILE -LineValue "[!] Failed to detect GroupPolicy module, skipping Group Policy Queries" -ForegroundColor Yellow}
1505
1506 #Running Queries
1507 Invoke-Execute
1508
1509 #Post Processing data
1510 Log-Write -LogPath $LOG_FILE -LineValue "[+] Starting Post Processing" -ForegroundColor Green
1511 Copy-Item -Path $LOG_FILE -Destination $TEMP_PATH
1512
1513 if ($PSVersionTable.PSVersion.Major -ge 3){
1514 Helper-ZipData -Directory $TEMP_PATH -OutputPath "$EX_PATH\$TOOL_NAME$DATE`.zip"
1515 }else{
1516 Log-Write -LogPath $LOG_FILE -LineValue "[*] Could not zip data. Requires PowerShell 3.0 or greater."
1517 Helper-MoveData -Directory $TEMP_PATH -OutputPath "$EX_PATH\$TOOL_NAME$DATE"
1518 }
1519}
1520
1521#Pushing data to server
1522if ($Global:CONF.USING_INTERNET){Invoke-Upload}
1523
1524Log-Write -LogPath $LOG_FILE -LineValue "[+] Stopping Post Processing" -ForegroundColor Green