⠛⠥⠝⠑⠽⠎⠥⠎ /home/asguneysu

Unblocking Files with .NET That Downloaded from Internet

by Ahmed Şeref

Discovered A Powershell Function Named Unblock-File

It is under the Microsoft.PowerShell.Utility module. So we will inspect this module’s source code.

>  get-command Unblock-File                                                                                                                                                                                                                                                                                                                                                                                                                                                               CommandType     Name                                               Version    Source                                                                                                                                                         -----------     ----                                               -------    ------                                                                                                                                                         Cmdlet          Unblock-File                                       3.1.0.0    Microsoft.PowerShell.Utility

The module is placed under the System32 folder at \WindowsPowerShell\v1.0\Modules\

Microsoft.PowerShell.Utility.psm1 does not have a function named Unblock-File. It must be defined in an .NET assembly.

Lets inpsect the Powershell module definition:

@{
GUID="1DA87E53-152B-403E-98DC-74D7B4D63D59"
Author="Microsoft Corporation"
CompanyName="Microsoft Corporation"
Copyright="© Microsoft Corporation. All rights reserved."
ModuleVersion="3.1.0.0"
PowerShellVersion = '5.1'
...
NestedModules="Microsoft.PowerShell.Commands.Utility.dll","Microsoft.PowerShell.Utility.psm1"
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}

Found the Module Source Code at Github

Since Powershell is an Open Source Project, we are able to inspect it’s source on Github 1

/// <summary>Removes the Zone.Identifier stream from a file.</summary>
[Cmdlet(VerbsSecurity.Unblock, ...)]
public sealed class UnblockFileCommand : PSCmdlet

  ...

  AlternateDataStreamUtilities.DeleteFileStream(path, "Zone.Identifier");

  ...

Again, AlternateDataStreamUtilities is defined in another assembly: System.Management.Automation

Found the Module on Nuget

We found the System.Management.Automation assembly on Nuget 2 And downloaded it for decompiling. Upon decompiling with ILSpy, found the internal method eventually.

<details class="ba bw2 mv2 pa2 b--light-gray">
    <summary class="fira mv1 dim fw7">Unblock File</summary>
    <span><a download="delete-file-stream-decompiled.cs" class="link black bg-animate hover-bg-light-yellow pv3 ph3" href="./src/delete-file-stream-decompiled.cs"><i
        class="icon icon-download"> </i> download</a> </span>        
    <div class="highlight"><pre class="chroma"><code class="language-cs" data-lang="cs"><span class="c1">// System.Management.Automation.Internal.AlternateDataStreamUtilities

using System.IO;

internal static void DeleteFileStream(string path, string streamName) { if (path == null) { throw new ArgumentNullException("path"); } if (streamName == null) { throw new ArgumentNullException("streamName"); } string text = streamName.Trim(); if (text.IndexOf(':') != 0) { text = ":" + text; } File.Delete(path + text); }

Reimplementing with LinqPad

 var path = @"C:\Users\guneysus\Downloads\PowerToysSetup-0.18.0-x64.msi";
 var streamName = "Zone.Identifier";
 string text = streamName.Trim();

 if (text.IndexOf(':') != 0)
 {
  text = ":" + text;
 }

 var fileStreamName = (path + text);

 fileStreamName.Dump();

 File.Delete(fileStreamName);

It worked. We implemented a feature Unblock File like Microsoft’s Streams 3 tool.

removing file

Implementing with Pure Powershell Function

Too more layer for a simple function.

A powershell function defined in an assembly that depends a Nuget Package.

Let’s try to reimplement it with pure Powershell function disregarding the reality “Powershell depends to .NET”

A simple and dirty PoC succeeded.

> $stream = "C:\Users\guneysus\Downloads\system.management.automation.7.0.1.nupkg:Zone.Identifier"
>  rm $stream

removing file streams with powershell

Conclusion

I do not think that Microsoft is hiding the implementation of Unblocking Files with Removing Alternate File Streams. Wrapping .NET assemblies with a thin layer of Powershell scripts seems a good practise, since .NET assemblies is more reusable and testable.

And in some time, you may need a simple functionality in a limited environment.

In brief:

Discovering and learning the under the hood” mindset is trademark of a a hacker.

hacker logo


  1. github.com/PowerShell/PowerShell/UnblockFile.cs#L130 ↩︎

  2. nuget.org/packages/System.Management.Automation ↩︎

  3. Sysinternals Streams Tool ↩︎

comments powered by Disqus
DMCA.com Protection Status