PowerShell to open gzip stream - powershell

Web searches for $s=New-Object IO.MemoryStream(,[Convert]::FromBase64String()) show numerous Pastebin's for similar events, but I cannot figure out how to decode it myself. The original base64 I decode with
param(
[Parameter(Mandatory=$True)]
[string]$b64
)
[System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String("$b64"))
which gives me this:
$s=New-Object IO.MemoryStream(,[Convert]::FromBase64String("Encrypted-String"))
IEX (New-Object IO.StreamReader(New-Object IO.Compression.GzipStream($s,[IO.Compression.CompressionMode]::Decompress))).ReadToEnd();
I have been unable to figure out how to use PowerShell to decompress the "Encrypted-String" so I can analyze what's happening.
I've seen similar posts but nothing answers my question of how to decode it myself. Any help is greatly appreciated.

I apologize for the formatting, I am still learning the nuances of posting questions/anwers on here. I also apologize if my question wasn't clear, but after much luck with today's research (been trying to figure this out for the past year).
I found a link (https://blog.kenaro.com/2010/10/19/how-to-embedd-compressed-scripts-in-other-powershell-scripts/) which gave me enough information to build this script. Thank you Ingo Karstein for your blog and all who viewed and asked for clarification.
The gzip stream is part of the results that needed further analysis which I was unable to figure out.
I create a folder in my Temp with the name of the machine that I obtained the suspicious batch file from that calls the encoded powershell command; remove all but the base64 code and rename it to a .txt file. I then run the code below with the computername and the file name to see what the attacker was doing. The answer that works for me:
(
[Parameter(Mandatory=$True)]
[string]$HostIP,
[Parameter(Mandatory=$True)]
[string]$file
)
New-Item C:\Temp\$HostIP\Results -ItemType Directory
$b64 = Get-Content C:\Temp\$HostIP\$file.txt -Raw
Write-Host
$results = [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String("$b64"))
$results | Out-File C:\Temp\$HostIP\Results\unicode_$file.txt
$ec64 = Get-Content C:\Temp\$HostIP\Results\unicode_$file.txt
$eb64 = $ec64|%{$_.split('"')[1]}
$data = [System.Convert]::FromBase64String("$eb64")
$ms = New-Object IO.MemoryStream
$ms.Write($data, 0, $data.Length)
$ms.Seek(0,0) | Out-Null
$cs = New-Object IO.Compression.GZipStream($ms, [IO.Compression.CompressionMode]::Decompress)
$sr = New-Object IO.StreamReader($cs)
$t = $sr.readtoend()
$t | Out-File C:\Temp\$HostIP\Results\decompressed_$file.txt
$dcb64 = Get-Content C:\Temp\$HostIP\Results\decompressed_$file.txt
$dc64 = $dcb64|%{$_.split('"')[1]}
$utf = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String("$dc64"))
$utf | Out-File C:\Temp\$HostIP\Results\utf8_$file.txt
$asc = [System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String("$dc64"))
$asc | Out-File C:\Temp\$HostIP\Results\ascii_$file.txt
$utf8 = "C:\Temp\$HostIP\Results\utf8_$file.txt"
$ascii = "C:\Temp\$HostIP\Results\ascii_$file.txt"
(Get-Content "$utf8") -replace "`0", "" | Set-Content "C:\Temp\$HostIP\Results\utf8_no-null_$file.txt"
(Get-Content "$ascii") -replace "`0", "" | Set-Content "C:\Temp\$HostIP\Results\ascii_no-null_$file.txt"
'

Related

Powershell - Retrieving content from a website that contains non-English characters and writing to a file results in incorrect characters

There is a news website I frequent that has a series of headlines on their main page. Clicking the headline takes you to the individual story. I am trying to write a Powershell script that will loop through all the headlines on the main page and write each story to a text file.
The problem I am having is the stories are in Spanish and the Spanish characters with accent marks do not show up properly in my text file (actually the weird thing is, sometimes they do, but the majority of the time they don't). I've checked the headers of each story and the charset is set to UTF8 so I think the web pages themselves are formatted correctly. I've tried every way I know of to set the output file as UTF8 as well, but I can't seem to get it fixed.
Anyone have any ideas? Here is the code:
$ie = New-Object -ComObject 'InternetExplorer.Application'
$url = "https://www3.nhk.or.jp/nhkworld/es/news/"
#$ie.Visible = $true
$ie.Navigate($url)
while($ie.busy) {Start-Sleep 1}
$file = "C:\temp\nhk.txt"
if(Test-Path $file) { Remove-Item $file }
$lastLink = $null
foreach($link in $ie.Document.getElementsByTagName("a")) {
if($link.href -match "\d{6}") { #the links to the stories we want are numbered with 6 digits
if(-not($link.href -eq $lastLink)) {
$uri = $link.href
$w = Invoke-WebRequest -Uri $uri
ForEach($element in $w.AllElements | where tagname -eq "p") {
$text = $element | select -expand innerText
$text = $text + "`r`n"
Add-Content -Path $file -Value $text
}
$lastLink = $link.href
}
}
}
I think it's the same basic problem as this question:
PowerShell Invoke-RestMethod Umlauts issues with UTF-8 and Windows-1252
The issue is the server is sending a response which is encoded using UTF8, but it's not correctly setting the Content-Type header to tell the client it's doing that, so the client is assuming it's encoded with the default ISO-8859-1 encoding.
This means, for example, the character ó is being sent by the server as the UTF8 byte sequence C3 B3 but the client is decoding that as an ISO-8859-1 byte sequence which becomes ó.
Since you can't presumably control the server's behaviour you might need to do some processing on the mangled text to recover the original version. I posted one way of doing that in an answer to the question above (see https://stackoverflow.com/a/58542493/3156906), but here it is again...
PS> $text = "ó"
PS> $bytes = [System.Text.Encoding]::GetEncoding("ISO-8859-1").GetBytes($text)
PS> $text = [System.Text.Encoding]::UTF8.GetString($bytes)
PS> write-host $text
ó
Did some more experimenting, and apparently, if you send the result of the Invoke-WebRequest call straight to a file using the -OutFile parameter, this file gets written in UTF8.
This should then (hopefully) do it:
# create a temporary file
$tempFile = (New-TemporaryFile).FullName
if(-not($link.href -eq $lastLink)) {
$uri = $link.href
$w = Invoke-WebRequest -Uri $uri
Invoke-WebRequest -Uri $uri -OutFile $tempFile
# read the file with encoding UTF8
$content = Get-Content -Path $tempFile -Raw -Encoding UTF8
# parse the html
$html = New-Object -Com "HTMLFile"
$html.IHTMLDocument2_write($content)
# and append the innerText to your file "C:\temp\nhk.txt"
Add-Content -Path $file -Value $html.body.innerText
Add-Content -Path $file # add extra empty line
# clean up
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($html) | Out-Null
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
$html = $null
$lastLink = $link.href
}
# remove the temp file
Remove-Item -Path $tempFile -Force

Preserve Emojis with Get-Content Powershell

I want to preserve Emojis with Get-Content.
When I pull the string from the feed I get the following result:
$WebResponse = Invoke-RestMethod $website
$str_outputNAME = $feed.title
Wanna try😉?
But when I save the content of the file and append it after I have the following result:
$content = (Get-Content -Path $file) -join "`n"
$toWrite = $top_line+$toWrite+$content
$toWrite | Out-File -FilePath $file;
Wanna try???
Background-Info
I want to use Powershell to read a rss-feed.
Therefor I need to append a string at the start of my CSV-File on update.
Because my question was regarding *.csv files I found that a better way is too use
$content = Import-Csv -Path $file
instead of
$content = Get-Content -Path $file
Now all my Emojis are preserved within the file but the processing of the script takes twice the time now.
I tried all different possible Get-Content -Encoding arguments but without luck.
Always resulted in loss towards the formatting of emojis.

Save Email body to html file powershell

I am trying to convert a folder full of MSG files to HTML files. I have a scrip that gets most of the way there, but instead of displaying the text in powershell I need it to save each one as an individual html file. For some reason I can't get the save to work. I've tried various options like out-file and $body.SaveAs([ref][system.object]$name, [ref]$saveFormat)
$saveFormat = [Microsoft.Office.Interop.Outlook.olSaveAsType]::olFormatHTML
Get-ChildItem "C:\MSG\" -Filter *.msg |
ForEach-Object {
$body = ""
$outlook = New-Object -comobject outlook.application
$msg = $outlook.Session.OpenSharedItem($_.FullName)
$body = $msg | Select body | ft -AutoSize
}
Any advice on how to save this as individual files would be great.
To start with, you should not capture the output of a Format-* cmdlet in a variable. Those are designed to output to something (screen, file, etc).
Ok, that aside, you are already opening the msg files, so you just need to determine a name and then output the HTMLBody property for each file. Easiest way would be to just tack .htm to the end of the existing name.
Get-ChildItem "C:\MSG\*" -Filter *.msg |
ForEach-Object {
$body = ""
$outlook = New-Object -comobject outlook.application
$msg = $outlook.Session.OpenSharedItem($_.FullName)
$OutputFile = $_.FullName+'.htm'
$msg.HTMLBody | Set-Content $OutputFile
}

Powershell not sending the right path for a file as argument

I'm trying to apply a hash function to all the files inside a folder as some kind of version control. The idea is to make a testfile that lists the name of the file and the generated checksum. Digging online I found some code that should do the trick (in theory):
$list = Get-ChildItem 'C:\users\public\documents\folder' -Filter *.cab
$sha1 = New-Object System.Security.Cryptography.SHA1CryptoServiceProvider
foreach ($file in $list) {
$return = "" | Select Name, Hash
$returnname = $file.Name
$returnhash = [System.BitConverter]::ToString($sha1.ComputeHash([System.IO.File]::ReadAllBytes($file.Name)))
$return = "$returnname,$returnhash"
Out-File -FilePath .\mylist.txt -Encoding Default -InputObject ($return) -Append
}
When I run it however, I get an error because it tries to read the files from c:\users\me\, the folder where I'm running the script. And the file c:\users\me\aa.cab does not exist and hence can't be reached.
I've tried everything that I could think of, but no luck. I'm using Windows 7 with Powershell 2.0, if that helps in any way.
Try with .FullName instead of just .Name.
$returnhash = [System.BitConverter]::ToString($sha1.ComputeHash([System.IO.File]::ReadAllBytes($file.FullName)))

(Powershell) Loop to delete files from an FTP Location

Good morning!
I have made it to the last (and rather pivotal) stage in my script, which is looping to delete files from a directory. I'm not going to pretend I'm knowledgeable at Powershell (far from it), so I'm sort-of chopping up blocks of code I find on the net, improvising and hoping it works.
I'm hoping someone can decipher what I'm trying to do here and see what I'm doing wrong!
# Clear FTP Directory
$DelLoop=1
$server = "www.newsbase.com"
$dir = "/usr/local/tomcat/webapps/newsbasearchive/monitors/asiaelec/"
"open $server
user Canttell Youthis
binary
cd $dir
" +(
For ($DelLoop=1; $DelLoop -le 5; 5)
{
$FileList[$DelLoop] | %{ "delete ""$_""`n" }
$DelLoop++
})| ftp -i -in
I know that the 'Open Connection' portion works, it's just the loop. It just keeps complaining about misplaced operators, and when I fix those, it doesn't throw up any errors - but it doesn't do anything either.
I spent the best part of 4 hours researching this yesterday, and I'm hoping one of you guys can help me.
Thanks in advance!
ADDENDUM:
Here is more of the code, as requested:
# Clear existing .htm file to avoid duplication
Get-ChildItem -path ".\" -recurse -include index.jsp | ForEach-Object {
Clear-Content "index.jsp"
}
# Set first part of .JSP Body
$HTMLPart1="</br><tr><td colspan=9 align=center><p style=""font-family:Arial"">Here are the links to the last 3 AsiaElec PDFs:</br><ul>"
# Recurse through directory, looking for 3 most recent .PDF files 3 times
$Directory="C:\PDFs"
$HTMLLinePrefix="<li><a style=""font-family:Arial""href="""
$HTMLLineSuffix="</a></li>"
$HTMLLine=#(1,2,3,4)
$Loop=1
$PDF=#(1,2,3,4)
Get-ChildItem -path $Directory -recurse -include *.pdf | sort-object -Property LastWriteTime -Descending | select-object -First 3 | ForEach-Object {
$PDF[$Loop]=$_.name
$HTMLLine[$Loop]=$HTMLLinePrefix + $_.name + """>" + $_.name + $HTMLLineSuffix
$Loop++
}
# Final .JSP File Assembly
Get-Content "header.html" >> "index.jsp"
$HTMLPart1 >> "index.jsp"
$LineParse=""
$Loop2=1
For ($Loop2=1; $Loop2 -le 3; 3)
{
$HTMLLine[$Loop2] >> "index.jsp"
$Loop2++
}
Get-Content "tail.html" >> "index.jsp"
# Prepare File List
$FileList=#(1,2,3,4,5)
$FileList[2]=$PDF[2]
$FileList[3]=$PDF[3]
$FileList[4]="index.jsp"
# Clear FTP Directory
$DelLoop=1
$server = "www.newsbase.com"
$dir = "/usr/local/tomcat/webapps/newsbasearchive/monitors/asiaelec/"
"open $server
user derek bland1ne
binary
cd $dir
" +(
For ($DelLoop=1; $DelLoop -le 5; 5)
{
$FileList[$DelLoop] | %{ "delete ""$_""`n" }
$DelLoop++
})| ftp -i -in
This isn't all of it, but I believe it contains all the relevant info.
Your $dir path looks like you're on a unix system so this may be a little different, but all you need to do is change your final loop a little bit:
For ($DelLoop=1; $DelLoop -le 5; $DelLoop++)
{
$FileList[$DelLoop] | % { rm $FileList[$DelLoop] }
}
This is assuming that $FileList contains the files you want to delete and not only (what I'm guessing are dummy) numbers. I also suggest that you download the Module that #Graimer mentions and then put it in WindowsPowerShell > Modules > %ModuleFolder% > %Module.psm1% and import it from your profile.
You can then just use PS> Remove-FTPItem -Path "/myFolder" -Recurse to remove your FTP stuff. Making your life easier.
Tweaking the solution to this post may also help Upload files with FTP using PowerShell
e.g:
Using $ftp.Method = [System.Net.WebRequestMethods+Ftp]::DeleteFile to delete the file,
and $response = $ftp.GetResponse() to find out if things went smoothly.
EDIT
Wrote this function after doing a little bit of research from here http://social.msdn.microsoft.com/forums/en-US/netfxnetcom/thread/17a3abbc-6144-433b-aadd-1f776c042bd5 and adapting the code from the Accepted Answer in the above link as well as the module #Graimer talked about.
function deleteFTPSide
{
Param(
[String] $ftpUserName = "muUserName",
[String] $ftpDomain = "ftp.place.com", # Normal domains begin with "ftp" here
[String] $ftpPassword = "myPassword",
[String] $ftpPort = 21, # Leave as the default FTP port
[String] $fileToDelete = "folder.domain.com/subfolder/file.txt"
)
# Create the direct path to the file you want to delete
[String] $ftpPath = "ftp://"+"$ftpUserName"+":"+"$ftpPassword#$ftpDomain"+":"+"$ftpPort/$fileToDelete"
# create the FtpWebRequest and configure it
$ftp = [System.Net.FtpWebRequest]::Create($ftpPath)
$ftp.Method = [System.Net.WebRequestMethods+Ftp]::DeleteFile
$ftp.Credentials = new-object System.Net.NetworkCredential($ftpUserName,$ftpPassword)
$ftp.UseBinary = $true
$ftp.UsePassive = $true
$response = [System.Net.FtpWebResponse]$ftp.GetResponse()
$response.Close()
}
While, admittedly, not one of the most elegant solutions written, I've tested it and it works at deleting a specified file off an FTP server.