Searching multiple servers for files,registry

Hello - iam new to ps, hoping to learn more.

To perform a “scan” for files/folders and registry. I started to create a script…some of the script works(files & folder w/files) but iam struggeling to get the scanning for .exe,.txt,vbs etc. in C$ to work, so far only tested with .txt. and cant seem to get it right - and…also need some pointers on how to check registry. Localy it works, but remotly…hmm,not so much.

I think i have been starring to long at the code and iam not getting anywhere, and i need to ask for some assistance.(and coffee) If you have some pointers on what iam doing wrong i would appriciate that. Please be kind, like i said - iam not a expert.

 

Write-Host "searching for files......."

$serverlist = Get-Content -path "\\share\target.txt"
$containers = @("folders", "files")


$loks = Get-Content -Path "\\share\folders.txt"

$total=@{}

$files=@("c:\temp\1.exe", "c:\temp\2.exe","c:\temp\3.exe")


foreach ($server in $serverlist) {

$sess=New-PSSession -Name $server



$reslist=@{}
foreach ($lok in $loks){
$res=@{}
$inv=Invoke-Command -Session $sess -ScriptBlock {param($param) Test-Path $param} -ArgumentList $lok
$res.add($lok, $inv.ToString()) 
$reslist+=$res
}

foreach ($file in $files){
$res=@{}
$inv=Invoke-Command -Session $sess -ScriptBlock {param($param) Test-Path $param} -ArgumentList $file
$res.add($file, $inv.ToString()) 
$reslist+=$res
}

$scope=Invoke-Command -Session $sess -ScriptBlock {Get-ChildItem -path c:\ -Include 1.exe, 1.txt, 1.bat, 1.vbs, 1.php }
$total.add($server.tostring(),$reslist)

}

foreach ($target in $total.GetEnumerator()){

foreach($i in $target.value.GetEnumerator()){
write-host ("{0},{1},{2}" -f $target.key,$i.key,$i.Value)
#$i

#$i.value
}

} 
if (!$scope){
write-host "no files found." 
}

return

Are you getting an error? Looking at your code you might be getting an error with your “reslist” hash table. On line 25 and 32 you are using a += operator which on hash table objects appends the value on the right to the hash table. Combine this with hash table keys must be unique and you may get an error that looks like “Item has already been added. Key in dictionary:…” I think what you probably want to do is declare “reslist” as an array on line 22 instead of a hash table. Simply change the {} to ()

$reslist=@()

There are some other things I might change from an efficiency standpoint such as using invoke-command with all the remote machines at once instead of iterating. Also, you should close your session when complete, but first I’d work on fixing any errors.

So, you may be able to make your life a lot easier. If your network has the default administrative shares enabled, you can forego the need to use Invoke-Command or New-PSSession.
That is, if you can use file explorer to access the C: drive of a remote computer via:

\\hostname\c$\

then you can do the same thing in PowerShell, like this:

Set-Location \\hostname\c$\

where hostname is the name of the remote computer.
In fact, you can simply do this:

Test-Path '\\hostname\c$\temp\'

or this:

Get-ChildItem '\\hostname\c$\temp\'

and get results much faster.
Also, accessing remote file systems this way doesn’t rely on WinRM the way that Invoke-Command does, so you can avoid a long list of potential problems.
If all you need to do is look at the file system, using the admin share is a lot easier.

Handling the registry with PowerShell is actually pretty easy, as PowerShell treats the registry as if it were a drive. There’s a good tutorial here: How to Get, Edit, Create and Delete Registry Keys with PowerShell, and Microsoft’s documentation on the subject is also pretty good.

However, the above again relies on Invoke-Command and WinRM to work on remote computers - and again, that can be avoided. Rather than using the PowerShell cmdlets, you can access the registry via .NET instead. This method requires the Remote Registry service to be running on the remote system, but frequently this service is already running. With this method, you can get information from a remote registry like this:

[Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', "hostname").OpenSubKey("Software\Microsoft").GetSubKeyNames()

This probably looks complicated, but again the advantage is that it doesn’t depend on WinRM and doesn’t require that you have performed Enable-PSRemoting on the remote system, and it’s faster than Invoke-Command.

[quote quote=201714][/quote]

Sorry, i forgot to mention that i got no errors, everything above $scope works. Able to check servers from the target.txt list and return false/true if the folders exist or a file in a path exist.

its the part about looking for files -Recurse even, to se if these files are anywhere in any folder. This works local. I guess if i figure this out then i can use it for looking in the registry as well ?

$scope=Invoke-Command -Session $sess -ScriptBlock {Get-ChildItem -path c:\ -Include 1.exe, 1.txt, 1.bat, 1.vbs, 1.php }
$total.add($server.tostring(),$reslist)

[quote quote=201825]So, you may be able to make your life a lot easier. If your network has the default administrative shares enabled, you can forego the need to use Invoke-Command or New-PSSession.

That is, if you can use file explorer to access the C: drive of a remote computer via:

<textarea class="ace_text-input" style="opacity: 0; height: 18px; width: 6.59771px; left: 44px; top: 0px;" spellcheck="false" wrap="off"></textarea>
1
\\hostname\c$\
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
then you can do the same thing in PowerShell, like this:
<textarea class="ace_text-input" style="opacity: 0; height: 18px; width: 6.59771px; left: 44px; top: 0px;" spellcheck="false" wrap="off"></textarea>
1
Set-Location \\hostname\c$\
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
where hostname is the name of the remote computer.

In fact, you can simply do this:

<textarea class="ace_text-input" style="opacity: 0; height: 18px; width: 6.59771px; left: 44px; top: 0px;" spellcheck="false" wrap="off"></textarea>
1
Test-Path '\\hostname\c$\temp\'
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
or this:
<textarea class="ace_text-input" style="opacity: 0; height: 18px; width: 6.59771px; left: 44px; top: 0px;" spellcheck="false" wrap="off"></textarea>
1
Get-ChildItem '\\hostname\c$\temp\'
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
and get results much faster.

Also, accessing remote file systems this way doesn’t rely on WinRM the way that Invoke-Command does, so you can avoid a long list of potential problems.

If all you need to do is look at the file system, using the admin share is a lot easier.

Handling the registry with PowerShell is actually pretty easy, as PowerShell treats the registry as if it were a drive. There’s a good tutorial here: How to Get, Edit, Create and Delete Registry Keys with PowerShell, and Microsoft’s documentation on the subject is also pretty good.

However, the above again relies on Invoke-Command and WinRM to work on remote computers – and again, that can be avoided. Rather than using the PowerShell cmdlets, you can access the registry via .NET instead. This method requires the Remote Registry service to be running on the remote system, but frequently this service is already running. With this method, you can get information from a remote registry like this:

<textarea class="ace_text-input" style="opacity: 0; height: 18px; width: 6.59771px; left: 44px; top: 0px;" spellcheck="false" wrap="off"></textarea>
1
[Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', "hostname").OpenSubKey("Software\Microsoft").GetSubKeyNames()
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
This probably looks complicated, but again the advantage is that it doesn't depend on WinRM and doesn't require that you have performed Enable-PSRemoting on the remote system, and it's faster than Invoke-Command.

[/quote]

Thank you for a good and informational answer, much appriciated.

Its a lot of servers to check . So my plan was to use the targets.txt file from the fileshare that is a list of all the servers, i am able to add servers to this list and check for folders + folder w/files. this part works.

I found out that all the servers allow psremote.

Will read up on the registry part, very interresting. My other plan was to limit the script so it can be moved around and not need any files from outside the script…except the targets.txt…and…folders.txt…i just deviated from my plan - but hope you understand my orginal plan :slight_smile: